Updated 2026-09-20
Architecture
Project structure, data flow, and how the site is built.
The site is a Next.js 16 application (App Router) built as static HTML at build time, styled with the YuTheme design language, deployed on Vercel. There is no server runtime.
Stack
- Next.js 16 (App Router, static generation)
- React 19
- TypeScript
- pnpm (package manager, version pinned via
packageManager) - Turborepo monorepo (
apps/,packages/) - next-intl for the seven locales,
localePrefix: as-needed - YuTheme tokens and editorial conventions (see design.md)
- Lucide icons via
lucide-react - Fonts: Geist Variable and Geist Mono Variable via
next/font/local
The only client JavaScript is a small amount of hydration: the header mobile menu, scrollspy, anchor smooth scrolling, and scroll reveals.
Structure
apps/web/src/
app/
[locale]/
layout.tsx document shell, fonts, metadata, JSON-LD
page.tsx single-page home
docs/page.tsx documentation index
docs/[slug]/page.tsx individual documentation pages
globals.css YuTheme tokens, base styles, motion
sitemap.ts sitemap for all locales
robots.ts
components/
Analytics.tsx Umami hook, env-gated, inert by default
Footer.tsx
Header.tsx fixed header, scrollspy, mobile sheet
Icon.tsx Lucide icon map, typed icon names
Reveal.tsx IntersectionObserver scroll reveal
sections/
Hero.tsx headline + terminal card
About.tsx
WhatIDo.tsx card grid
HowIWork.tsx
WhereILive.tsx
SelectedWork.tsx public work list
data/site.ts site constants: URLs, navigation
i18n/ routing, request config, typed navigation
lib/docs.ts markdown pipeline for documentation pages
packages/
content/ docs/ sources, read per locale with EN fallback
i18n/ locale list + messages for the seven locales
ui/styles/ canonical YuTheme CSS files, token reference
Localization
- Locales: en (default, no prefix), pt, es, fr, de, ja, zh-CN.
- UI copy lives in
packages/i18n/messages/<locale>.json. - Documentation lives in
packages/content/docs/<locale>/; when a locale is missing a file, the English version is served as fallback. - Routes are static: every locale and every doc slug is prerendered at
build time through
generateStaticParams. - Metadata and JSON-LD descriptions are localized: the schema on each page uses the locale's translated summary.
Docs pipeline
Documentation pages read the packages/content/docs/ folder through
packages/content/src/index.ts:
- each doc is a Markdown file with frontmatter:
title,description,order,updated; - the app renders it with remark/rehype (GFM, slugged headings,
autolinks, sanitized HTML) at
/docs/<slug>with an index at/docs; @ellamizuki/contentis kept external to the app bundle (serverExternalPackages) so the filesystem reads work in production.
Because the collection reads the same folder that is versioned in the repository, the docs stay in sync: one source of truth, two views (site page and repo files).
Data flow
- Build time: Next.js prerenders
/,/docs,/docs/*for every locale. - Content is prerendered; there is no server, no API, no runtime data.
- Analytics (Umami) is only injected when both
NEXT_PUBLIC_UMAMI_SRCandNEXT_PUBLIC_UMAMI_WEBSITE_IDare set at build time.
Conventions
- Semantic HTML with a single
h1per page. - Section headings ordered (
h2thenh3), never skipped levels. - External links open in a new tab with
rel="noopener noreferrer". - Links rendered by next-intl never receive an already-prefixed href; the locale prefix is always added by the navigation helpers.
- Reduced motion is respected everywhere: shimmer, reveals, and transitions
are gated behind
prefers-reduced-motion.