Personal site built as an editorial portfolio for John Herrera, combining gastronomy and digital product craft in one narrative system.
- Next.js 16.2.1 (App Router, React Compiler)
- React 19
- TypeScript
- Tailwind CSS 4
- Lenis (smooth-scroll behavior)
npm install
npm run devOpen http://localhost:3000.
npm run lint
npm run build
npm start/Home editorial entry point/worksWorks split (gastronomy + development)/aboutProfile and trajectory/contactContact installation
src/
├── app/ # App Router, layout, metadata, og image
├── design/
│ ├── primitives/ # SectionPrimitive, CardPrimitive, MonoToken, Eyebrow
│ ├── tokens/ # primitives/semantic/components tokens
│ └── ui/ # composed DS blocks (SectionChrome)
├── features/
│ ├── about/
│ ├── contact/
│ ├── development/
│ ├── gastronomy/
│ ├── home/
│ └── works/
├── components/
│ └── shared/ # shared infra UI (TopNav, ErrorBoundary, scroll helpers)
└── lib/ # constants, hooks, utils
Active source of truth is under src/design/:
src/design/tokens/*for visual decisionssrc/design/primitives/*for base building blockssrc/design/ui/*for composed design-system pieces
Configured globally in next.config.ts:
Content-Security-PolicyPermissions-PolicyCross-Origin-Opener-PolicyCross-Origin-Resource-PolicyStrict-Transport-SecurityX-Frame-OptionsX-Content-Type-OptionsReferrer-Policy
Optional env vars:
NEXT_PUBLIC_GTM_ID=GTM-XXXXXXX
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXXNEXT_PUBLIC_GTM_ID: enables Google Tag ManagerNEXT_PUBLIC_GA_ID: enables direct GA4 installation- If GA4 is already sent via GTM, leave
NEXT_PUBLIC_GA_IDempty to avoid duplicates
Tracked custom events:
cta_contact_clickmailto_clickproject_clicknav_click
GitHub Actions workflow: .github/workflows/ci.yml
Runs on every push and pull request:
npm cinpm run lintnpm run build
- Configure env vars (
NEXT_PUBLIC_GTM_ID, optionalNEXT_PUBLIC_GA_ID). - Run
npm run lintandnpm run build. - Verify events in GTM/GA debug view.
- Deploy.
See CONTEXT.md for full AI-oriented project context.
See docs/phase4-audit.md for cleanup decisions applied in Phase 4.