How I Built This Portfolio
A deep dive into the architecture behind this portfolio: Edge Proxy routing, dual-experience rendering, the 3D pipeline, and performance decisions.
Dual-Experience Routing
The site operates under a single URL but serves two completely different experiences. An Edge Proxy intercepts every request, reads the User-Agent and Client Hints headers, and performs an invisible rewrite to either the Heavy (3D desktop) or Light (minimal mobile) route. Direct access to internal routes is blocked — the proxy redirects back to the locale root.
SEO & Dynamic Serving
Both experiences consume the exact same data layer, guaranteeing content parity. The Vary: User-Agent header notifies search engines of dynamic serving. Semantic HTML (headings, text, links) is identical across versions — only media rendering differs.
3D Pipeline & Performance
The Heavy experience uses React Three Fiber with procedurally generated scenes — no heavy .glb assets. A PerformanceMonitor adaptively adjusts DPR. The Light route never imports any Three.js code, ensuring zero WebGL overhead on mobile.
Next.js 16 & the Proxy Rename
Next.js 16 introduced a breaking change: middleware.ts was renamed to proxy.ts, and the exported function changed from middleware() to proxy(). The proxy now defaults to the Node.js runtime instead of Edge. Our single proxy function chains three responsibilities — locale detection (cookie preference → Accept-Language negotiation), device classification (Client Hints → User-Agent fallback), and the invisible rewrite that inserts the experience segment after the locale in the URL path.
Internationalization Strategy
The i18n system operates on two layers. The proxy resolves the user's locale via a NEXT_LOCALE cookie (set by the language switcher) with an Accept-Language fallback, defaulting to Spanish. The data layer uses a LocalizedText type ({ en: string; es: string }) for every user-facing field, ensuring both Heavy and Light experiences render identical bilingual content. The Vary: User-Agent, Accept-Language, Device-Memory header informs CDNs and search engines that responses differ by device, language, and hardware capability.
Experience: HEAVY (3D Desktop)