Overview
The fastest path from description to running Next.js app. Based on the Corbin Brown scaffolding methodology — get a working app running before writing any feature code.
Step 1: Create Project
npx create-next-app@latest my-app \
--typescript \
--tailwind \
--eslint \
--app \
--src-dir \
--import-alias "@/*" \
--use-npm
cd my-app
Required flags:
--typescript— always--app— App Router (not Pages Router)--src-dir— organizes code undersrc/--import-alias "@/*"— cleaner imports than../../
Step 2: Add ShadCN
npx shadcn@latest init
Choose: New York style, Zinc color, CSS variables. ShadCN writes components to src/components/ui/ — these are YOUR files, edit freely.
Add components as needed:
npx shadcn@latest add button card input label form toast
Step 3: Environment Variables
Create .env.local (never commit this):
# Database
DATABASE_URL=postgresql://...
# Auth (Clerk)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
# AI
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
.gitignore must include .env.local and .env*.local. Verify before first commit.
Step 4: Directory Structure
src/
app/
layout.tsx # Root layout
page.tsx # Home
(dashboard)/ # Route group
dashboard/
page.tsx
api/
route.ts
components/
ui/ # ShadCN components
layout/ # Header, Footer, Sidebar
features/ # Feature-specific components
lib/
utils.ts # cn() helper + shared utilities
db.ts # Database client
auth.ts # Auth helpers
types/
index.ts # Shared TypeScript types
Step 5: CSS Architecture (Named Classes, Not Raw Tailwind in JSX)
/* src/app/globals.css */
@import "tailwindcss";
@layer components {
.page-container {
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
}
.card-base {
@apply bg-white rounded-lg shadow-sm border border-gray-200 p-6;
}
.btn-primary {
@apply bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md
font-medium transition-colors disabled:opacity-50;
}
}
Rule: Named CSS classes in globals.css, not raw Tailwind utility strings in TSX. Keeps components readable.
Step 6: Supabase Client Setup
// src/lib/supabase.ts
import { createClient } from "@supabase/supabase-js";
import type { Database } from "@/types/database";
export const supabase = createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
// Server-side client (service role — API routes only)
export function createServerClient() {
return createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
}
Step 7: Start Dev Server and Verify
npm run dev
Verify at http://localhost:3000:
- Default page loads without errors
- Browser console is clean
- TypeScript compiles without errors (
npm run type-check) - Lint passes (
npm run lint)
Never move to feature development until the baseline is green.
Pre-Commit Checklist
# Create .gitignore before first commit
cat > .gitignore << 'EOF'
.env.local
.env*.local
node_modules/
.next/
EOF
git init
git add .
git commit -m "init: scaffold Next.js 15 + TypeScript + Tailwind + ShadCN"
Port Conflicts
# Kill whatever is on port 3000
npx kill-port 3000
# Or use a different port
PORT=3001 npm run dev