Personal editorial portfolio for John Herrera, combining kitchen craft and digital product work in one route-based experience.
- Next.js 16.2.1 App Router
- React 19
- TypeScript
- Tailwind CSS 4
- Lenis for smooth scroll behavior
- React Compiler enabled
npm install
npm run dev
npm run lint
npm run typecheck
npm run build
npm start- Install dependencies with
npm install. - Copy
.env.exampleto.env.localif you want analytics enabled locally. - Run
npm run dev. - Open
http://localhost:3000.
Documented in .env.example.
NEXT_PUBLIC_GTM_ID: optional Google Tag Manager container ID.NEXT_PUBLIC_GA_ID: optional GA4 measurement ID.
If GA4 is already loaded through GTM, keep NEXT_PUBLIC_GA_ID empty to avoid duplicate pageviews.
/Home hero and editorial entry point/worksHospitality and digital work/aboutProfile, trajectory, and working position/contactContact CTA and social links
Route pages live in src/app/(site)/ and are static server-rendered pages.
src/
├── app/ # Layout, route pages, metadata, OG/Twitter image, robots, sitemap
├── components/ # App-level effects and shared UI
├── design/ # Design system primitives, tokens, composed UI
├── features/ # Feature-owned UI and data
├── lib/ # Shared constants, hooks, utils, SEO helpers
├── assets/ # Reserved for source assets
├── config/ # Reserved for project configuration
├── content/ # Reserved for content
└── types/ # Global TypeScript types
- Design tokens live in
src/design/tokens/. - Base primitives live in
src/design/primitives/. - Composed design-system UI lives in
src/design/ui/. - Feature-specific UI lives in
src/features/*/ui/. - Shared app logic lives in
src/lib/.
- Root metadata and site JSON-LD live in
src/app/layout.tsx. - Per-route metadata is derived from
PAGE_SEOinsrc/lib/constants.ts. - Page metadata and page JSON-LD are built in
src/lib/seo.ts. - Dynamic OG image generation lives in
src/app/opengraph-image.tsx. src/app/twitter-image.tsxreuses the OG image output.src/app/robots.tsandsrc/app/sitemap.tsare generated from site constants.
Analytics is optional and disabled unless env vars are set.
NEXT_PUBLIC_GTM_IDenables Google Tag Manager.NEXT_PUBLIC_GA_IDenables direct GA4.
Tracked custom events:
cta_contact_clickmailto_clickproject_clicknav_click
Run these before shipping changes:
npm run lint
npm run typecheck
npm run build