Replace Next.js 16 + React 19 with Astro 5. Same visual design, same deploy pipeline, zero client-side framework. - All components rewritten as .astro files - Dark mode via inline scripts (no React context) - Timeline animation via IntersectionObserver script - Nav active state computed at build time - Self-hosted Source Code Pro woff2 fonts - Drop Font Awesome (icons were never loaded) - Drop unused headshot PNG (1MB, unreferenced) - Fix pfSense hardware refs (Netgate 1100, not N100) - Output: 212KB static HTML vs 2.6MB before - JS shipped: ~700 bytes inline vs ~130KB React runtime
3.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Project: [PERSONAL PORTFOLIO] Stack: [Astro 5 + TypeScript + Tailwind v4] Deployed to: [lerkolabs.com — self-hosted via Gitea Actions]
Branch Strategy
This repo uses two branches:
master— built output only; reserved for future GitHub mirrordev— source code; all development happens here
Always work on the dev branch. Never manually edit files on master.
Commands
npm run dev # Dev server at localhost:4321
npm run build # Production build into out/ (static export)
npm run preview # Preview production build locally
Architecture
Astro 5 static-export portfolio site with TypeScript. Zero client-side framework — all interactivity via inline <script> tags.
src/layouts/Base.astro— Root layout; self-hosted Source Code Pro font, blocking theme script, Nav + Footersrc/pages/index.astro— Home page (Hero, Timeline)src/pages/projects.astro— Featured + archive projectssrc/pages/homelab.astro— At-a-glance stats, VLAN table, services grid, ADRs, Gitea CTAsrc/pages/archive.astro— Meta-refresh redirect to /projects/src/components/— Nav, Footer, Hero, Timeline, Widget, ProjectCard, Skills (all.astro)src/data/projects.ts— All projects typed, featured + archive splitsrc/data/services.ts— Homelab services with categoriessrc/data/timeline.ts— Career/project timeline entriessrc/styles/globals.css— Full design system: colors, fonts, breakpoints, keyframes (Tailwind v4 CSS-first config)public/fonts/— Self-hosted Source Code Pro woff2 (latin + latin-ext).gitea/workflows/deploy.yml— CI: builds, rsyncsout/to portfolio LXC, restarts Docker container
Dark mode
Blocking <script is:inline> in Base.astro <head> reads localStorage('lerko96-dark-mode'), defaults dark, adds .dark class before paint. Toggle logic in Nav.astro <script>.
Tailwind v4 note
Tailwind v4 is CSS-first — there is no tailwind.config.ts. All custom tokens live in globals.css under @theme {}. Dark mode variant is defined as @variant dark (&:where(.dark, .dark *)).
Coding Standards
Commit messages
Never include any of the following in commit messages — a local commit-msg hook will reject them:
- AI tool names:
claude,chatgpt,gemini,copilot,mistral - Company names:
anthropic,openai - Model names:
haiku,opus,sonnet,gpt-4,gpt-3, etc. - Generic AI terms:
llm,generated with ai,co-authored-by: claude - AI attribution footers (e.g. the default Claude Code co-author line)
Write commit messages as if you wrote the code yourself.
The enforcement hook lives in .git/hooks/commit-msg (not committed — local only).
Deployment
Push to dev on Gitea triggers .gitea/workflows/deploy.yml:
- Builds the static site (
npm run build) - rsyncs
out/to the portfolio LXC at10.99.0.23 - Rebuilds and restarts the Docker container serving lerkolabs.com