A pnpm and Turborepo monorepo. Every word on this page — the roles, the projects, the skills, even the cards below — is a row read from the FastAPI service through a repository port. There is no bundled copy to fall back on, which is the only way the page can be trusted to be current. The skill rail, the two panels, the job tags that open a breakdown and the indicator above are the only client components. Dashed cards are the layers that are not serving this page yet.
Client
BrowserServer-rendered HTML arrives first; only the trace layer hydrates.
Framework
Next.js App RouterServer components for all content, one client boundary for the trace interaction.
Design system
packages/uiFive layers: headless hooks, polymorphic primitives, variant-bound elements, domain components, then the thin leaves the page places.
Data
packages/dataA repository port with one adapter behind it: the HTTP client generated from the API's OpenAPI schema. Nothing that renders the page knows where the rows came from.
Build
Turborepo + pnpmFour workspace packages, typechecked together. Developed on Windows through WSL.
API
FastAPI serviceThe read API for this CV, with an OpenAPI schema generating the TypeScript client.
Persistence
PostgresJobs, skills and the join between them as rows — which is what makes the trace a query rather than an array filter.
RuntimePlanned
Docker behind NGINXOne container per service on an Ubuntu VPS, with TLS terminated at the edge. The same box that runs the enrollment system.