Production-ready full-stack starter built with:
- Next.js 15 App Router
- DrizzleORM
- Supabase (Postgres)
- Auth0
- Shadcn UI
- Tailwind CSS
- TypeScript.
- Node.js 20+
- pnpm 9+ (recommended)
- Supabase project (or a Postgres database)
- Auth0 application
pnpm installCopy the .env.example file, rename it to .env.local and set your real environment credentials
Environment variables are validated at runtime via src/types/env.ts using Zod. Clear errors will be thrown if any are missing or malformed.
Generate and apply migrations, then seed sample data:
pnpm db:generate
pnpm db:migrate
pnpm db:seedFor details on schema, queries, migrations, and best practices, see DATABASE.md (already included in this repo).
pnpm devOpen http://localhost:3000.
pnpm dev # Start Next.js dev server (Turbopack)
pnpm build # Build for production (Turbopack)
pnpm start # Start production server
pnpm lint # Run ESLint
# Drizzle / DB
pnpm db:generate # Generate SQL migrations from Drizzle schema
pnpm db:migrate # Apply migrations (uses src/db/migrate.ts)
pnpm db:seed # Seed development database
pnpm db:studio # Open Drizzle Studio
pnpm db:check # Validate migrations
pnpm db:drop # Drop database objects (danger)
pnpm db:reset # Drop, generate, migrate, seedsrc/
app/ # App Router (RSC-first)
(routes)/ # Routes and route components
actions/ # Server Actions (mutations)
layout.tsx # Root layout
loading.tsx # Route-level loading fallback
components/ # UI components (client where necessary)
ui/ # Shadcn UI primitives
layout/ # App shell (sidebar, topbar)
db/ # Database layer (Drizzle + Supabase)
migrations/ # SQL migrations (generated)
queries/ # Reusable server-only queries
schemas/ # Drizzle schemas
seeds/ # Seeding data
index.ts # Connection + Drizzle client
migrate.ts # Migration runner
seed.ts # Seed script
utils.ts # Database utility functions
hooks/ # React hooks
lib/ # App libraries (auth, utils)
types/ # Shared types (env validation, etc.)
middleware.ts # Auth0 middleware function from SDK.
Conventions:
- Prefer React Server Components; minimize
use client - Use Server Actions for mutations
- Keep database access in
src/db/queries/*(server-only) - Co-locate route components under
src/app/(routes) - Use Zod for input validation in Server Actions
Auth0 is integrated via @auth0/nextjs-auth0.
- Middleware is configured in
src/middleware.tsto protect routes src/lib/auth/auth0.tsexposes a thin wrapper to get the sessionsrc/lib/auth/sync-user.tsupserts the Auth0 profile into Postgres
Set the Auth0 Application URLs to match your environment:
- Allowed Callback URLs:
http://localhost:3000/api/auth/callback - Allowed Logout URLs:
http://localhost:3000 - Allowed Web Origins:
http://localhost:3000 - Allowed Origins (CORS):
http://localhost:3000/auth/callback
- Tailwind CSS 4
- Shadcn UI components under
src/components/ui - Radix primitives for accessibility and UX
- Mobile-first, responsive design
This project uses DrizzleORM with postgres.js and Supabase (managed Postgres). It is configured for the Supabase transaction pooler (prepare: false). For schema design, migrations, querying patterns, pagination utilities, and performance tips, read DATABASE.md.
- TypeScript everywhere; prefer interfaces over types
- Declarative, functional React components; avoid classes
- Descriptive names (e.g.,
isLoading,hasError) - Minimize
useEffectand client state; prefer RSC + Server Actions - Use
nuqsfor URL state when needed - Follow Next.js data fetching and caching guidelines
Linting:
pnpm lintRecommended: Vercel + Supabase
- Set all environment variables in Vercel project settings
- Use Supabase Transaction Pooler connection string for
DATABASE_URL - Run migrations in CI/CD or manually before first deploy
- Ensure RLS policies are configured in Supabase if required
- "prepared statement already exists": ensure
prepare: falsein DB config - Too many connections: use Supabase pooler and keep pool size conservative (
max: 10) - Missing env vars: see error output from
src/types/env.ts - Migration issues: regenerate with
pnpm db:generateand re-runpnpm db:migrate