Personal portfolio + blog.
Built on TanStack Start (SSR) with a custom dark design system, Nocturne (twilight violet-slate, single-hue, kinetic display type).
- Framework — TanStack Start (SSR) + TanStack Router file-based routing
- UI — React 19, Tailwind CSS v4, GSAP for motion, Phosphor icons
- Tooling — Vite, Vitest, ESLint (@tanstack/eslint-config), Prettier
- Deploy — Nitro (Node-compatible, any host)
pnpm install
pnpm dev # → http://localhost:3000Requires Node 22 (see
.nvmrc) and pnpm.
| Command | Description |
|---|---|
pnpm dev |
Dev server on port 3000 |
pnpm build |
Production build |
pnpm preview |
Preview the build |
pnpm test |
Run Vitest |
pnpm lint |
ESLint |
pnpm format |
Prettier write + ESLint fix |
pnpm generate-routes |
Regenerate the route tree (tsr generate) |
src/
routes/ file-based routes (/, /blog, /components)
components/ui/ Nocturne component library (see /components)
lib/ cn, site config, gsap, highlight, hooks
styles.css Tailwind v4 @theme — design tokens
content/ blog content
Tokens live in src/styles.css (@theme): the violet ramp, surface/text/line
scales (well / base / surface / elevated, ink / muted / faint),
glow shadows, and the nocturne-* utilities. Fonts: Sora (display), Inter
(body), JetBrains Mono (labels/code).
The full component library — buttons, inputs, overlays, blog primitives — is
exported from #/components/ui and showcased live at the /components route.
Routes are files under src/routes. The route tree
(src/routeTree.gen.ts) is generated automatically by the Vite plugin in dev,
or via pnpm generate-routes.
Nitro produces a self-contained Node server:
pnpm build
node .output/server/index.mjsFor host presets (Vercel, Netlify, Cloudflare, etc.) see https://nitro.build/deploy.