Modern website and headless CMS for Dino, built with Next.js 15 and Payload. The site powers public pages (home, services, case studies, resources, careers) and a secure admin for content management.
- Next.js 15 (App Router) with React 19
- Payload CMS on PostgreSQL
- Tailwind CSS 4 + shadcn/ui
- Media via Vercel Blob, email via Resend
- Animations with GSAP and 3D via Three.js/@react-three/fiber
- TypeScript and Biome for DX
- Framework: Next.js 15, React 19
- CMS: Payload CMS (
withPayload) + PostgreSQL - Styling: Tailwind CSS 4, shadcn/ui (New York)
- Media: Vercel Blob storage
- Email: Resend
- Data: TanStack React Query
- Animation/3D: GSAP, @gsap/react, Three.js, @react-three/fiber; smooth scroll via Lenis
- Tooling: TypeScript, Biome
- Node.js 18+ (Node 20+ recommended)
- A package manager (
npm,pnpm,yarn, orbun) - PostgreSQL database and credentials
- Install dependencies
npm install- Environment variables
Create a .env.local file in the project root with:
PAYLOAD_SECRET=your-strong-secret
DATABASE_URI=postgres://user:pass@host:5432/dbname?sslmode=require
BLOB_READ_WRITE_TOKEN=vercel_blob_rw_...
RESEND_API_KEY=re_...
Notes:
- PostgreSQL: Neon or another managed Postgres works well. Ensure SSL if required.
- Vercel Blob: Token must have read/write scope for media.
- Resend: Use a verified sender domain; defaults are configured in
src/payload.config.ts.
- Development
npm run dev- App: http://localhost:3000
- Admin (Payload): http://localhost:3000/admin
Build and start production:
npm run build
npm startsrc/app/(frontend): Public site routes, layout, andglobals.csssrc/app/(payload): Payload admin and API routes (GraphQL, REST)src/collections: Payload collections (Users, Media, CaseStudies, Resources, Services, Careers, ContactSubmissions, Pages)src/globals: Global site settings (e.g., CompanyAbout)src/components: UI and shared components (navigation, providers, ui, universal)src/lib: Utilities and helperssrc/emails: Email templates
- Admin URL:
/admin - Collections: Users, Media (Vercel Blob), Pages, CaseStudies, Resources, Services, Careers, ContactSubmissions
- Globals: CompanyAbout
- GraphQL endpoint:
/api/graphql - GraphQL playground (dev):
/api/graphql-playground
npm run dev— Start Next.js + Payload in devnpm run build— Build production bundle and generate Payload typesnpm start— Start production servernpm run lint— Biome checksnpm run format— Biome format (write)
- Next.js (
next.config.ts): useswithPayload. Image optimization allowslocalhostmedia; add production asset domains before deploying. - Payload (
src/payload.config.ts):DATABASE_URIfor PostgreSQLPAYLOAD_SECRETfor auth/session- Vercel Blob via
BLOB_READ_WRITE_TOKEN - Resend via
RESEND_API_KEY(default from name/address set here)
Recommended: Vercel
- Set env vars:
PAYLOAD_SECRET,DATABASE_URI,BLOB_READ_WRITE_TOKEN,RESEND_API_KEY - Add production media/image domains in
next.config.tsimages.remotePatterns - Ensure Postgres is reachable from Vercel with SSL if needed
- Verify Resend domain and DNS (SPF/DKIM) for sending
- Admin login issues: verify
PAYLOAD_SECRETand database connectivity - Media upload errors: check
BLOB_READ_WRITE_TOKENand Blob binding - Emails not sending: confirm
RESEND_API_KEYand verified sender domain
- Do not commit secrets. Use
.env.localfor local development. - If any secrets were previously committed, rotate them immediately (database, blob token, email API key).
Maintained by Madeley Design Studio for Dino.