{"slug":"scaffold-app-workflow","title":"App Scaffolding Workflow: Next.js 15 from Zero to Running","tags":["nextjs","scaffold","typescript","tailwind","setup"],"agent_summary":"Step-by-step workflow for scaffolding a new Next.js 15 app with TypeScript, Tailwind CSS 4, ShadCN, and Supabase from zero to dev server running.","trigger_phrases":["scaffold Next.js app","create Next.js project","new Next.js app","Next.js setup","ShadCN setup","Tailwind 4 setup"],"runnable":true,"markdown":"\n## Overview\n\nThe 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.\n\n## Step 1: Create Project\n\n```bash\nnpx create-next-app@latest my-app \\\n  --typescript \\\n  --tailwind \\\n  --eslint \\\n  --app \\\n  --src-dir \\\n  --import-alias \"@/*\" \\\n  --use-npm\n\ncd my-app\n```\n\n**Required flags:**\n- `--typescript` — always\n- `--app` — App Router (not Pages Router)\n- `--src-dir` — organizes code under `src/`\n- `--import-alias \"@/*\"` — cleaner imports than `../../`\n\n## Step 2: Add ShadCN\n\n```bash\nnpx shadcn@latest init\n```\n\nChoose: New York style, Zinc color, CSS variables. ShadCN writes components to `src/components/ui/` — these are YOUR files, edit freely.\n\nAdd components as needed:\n\n```bash\nnpx shadcn@latest add button card input label form toast\n```\n\n## Step 3: Environment Variables\n\nCreate `.env.local` (never commit this):\n\n```bash\n# Database\nDATABASE_URL=postgresql://...\n\n# Auth (Clerk)\nNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...\nCLERK_SECRET_KEY=sk_...\n\n# Supabase\nNEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...\nSUPABASE_SERVICE_ROLE_KEY=eyJ...\n\n# AI\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\n```\n\n`.gitignore` must include `.env.local` and `.env*.local`. Verify before first commit.\n\n## Step 4: Directory Structure\n\n```\nsrc/\n  app/\n    layout.tsx          # Root layout\n    page.tsx            # Home\n    (dashboard)/        # Route group\n      dashboard/\n        page.tsx\n    api/\n      route.ts\n  components/\n    ui/                 # ShadCN components\n    layout/             # Header, Footer, Sidebar\n    features/           # Feature-specific components\n  lib/\n    utils.ts            # cn() helper + shared utilities\n    db.ts               # Database client\n    auth.ts             # Auth helpers\n  types/\n    index.ts            # Shared TypeScript types\n```\n\n## Step 5: CSS Architecture (Named Classes, Not Raw Tailwind in JSX)\n\n```css\n/* src/app/globals.css */\n@import \"tailwindcss\";\n\n@layer components {\n  .page-container {\n    @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;\n  }\n\n  .card-base {\n    @apply bg-white rounded-lg shadow-sm border border-gray-200 p-6;\n  }\n\n  .btn-primary {\n    @apply bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md\n           font-medium transition-colors disabled:opacity-50;\n  }\n}\n```\n\n**Rule:** Named CSS classes in `globals.css`, not raw Tailwind utility strings in TSX. Keeps components readable.\n\n## Step 6: Supabase Client Setup\n\n```typescript\n// src/lib/supabase.ts\nimport { createClient } from \"@supabase/supabase-js\";\nimport type { Database } from \"@/types/database\";\n\nexport const supabase = createClient<Database>(\n  process.env.NEXT_PUBLIC_SUPABASE_URL!,\n  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n);\n\n// Server-side client (service role — API routes only)\nexport function createServerClient() {\n  return createClient<Database>(\n    process.env.NEXT_PUBLIC_SUPABASE_URL!,\n    process.env.SUPABASE_SERVICE_ROLE_KEY!\n  );\n}\n```\n\n## Step 7: Start Dev Server and Verify\n\n```bash\nnpm run dev\n```\n\nVerify at `http://localhost:3000`:\n- Default page loads without errors\n- Browser console is clean\n- TypeScript compiles without errors (`npm run type-check`)\n- Lint passes (`npm run lint`)\n\n**Never move to feature development until the baseline is green.**\n\n## Pre-Commit Checklist\n\n```bash\n# Create .gitignore before first commit\ncat > .gitignore << 'EOF'\n.env.local\n.env*.local\nnode_modules/\n.next/\nEOF\n\ngit init\ngit add .\ngit commit -m \"init: scaffold Next.js 15 + TypeScript + Tailwind + ShadCN\"\n```\n\n## Port Conflicts\n\n```bash\n# Kill whatever is on port 3000\nnpx kill-port 3000\n# Or use a different port\nPORT=3001 npm run dev\n```\n","html":"<h2>Overview</h2>\n<p>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.</p>\n<h2>Step 1: Create Project</h2>\n<pre><code class=\"language-bash\">npx create-next-app@latest my-app \\\n  --typescript \\\n  --tailwind \\\n  --eslint \\\n  --app \\\n  --src-dir \\\n  --import-alias \"@/*\" \\\n  --use-npm\n\ncd my-app\n</code></pre>\n<p><strong>Required flags:</strong></p>\n<ul>\n<li><code>--typescript</code> — always</li>\n<li><code>--app</code> — App Router (not Pages Router)</li>\n<li><code>--src-dir</code> — organizes code under <code>src/</code></li>\n<li><code>--import-alias \"@/*\"</code> — cleaner imports than <code>../../</code></li>\n</ul>\n<h2>Step 2: Add ShadCN</h2>\n<pre><code class=\"language-bash\">npx shadcn@latest init\n</code></pre>\n<p>Choose: New York style, Zinc color, CSS variables. ShadCN writes components to <code>src/components/ui/</code> — these are YOUR files, edit freely.</p>\n<p>Add components as needed:</p>\n<pre><code class=\"language-bash\">npx shadcn@latest add button card input label form toast\n</code></pre>\n<h2>Step 3: Environment Variables</h2>\n<p>Create <code>.env.local</code> (never commit this):</p>\n<pre><code class=\"language-bash\"># Database\nDATABASE_URL=postgresql://...\n\n# Auth (Clerk)\nNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...\nCLERK_SECRET_KEY=sk_...\n\n# Supabase\nNEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...\nSUPABASE_SERVICE_ROLE_KEY=eyJ...\n\n# AI\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\n</code></pre>\n<p><code>.gitignore</code> must include <code>.env.local</code> and <code>.env*.local</code>. Verify before first commit.</p>\n<h2>Step 4: Directory Structure</h2>\n<pre><code>src/\n  app/\n    layout.tsx          # Root layout\n    page.tsx            # Home\n    (dashboard)/        # Route group\n      dashboard/\n        page.tsx\n    api/\n      route.ts\n  components/\n    ui/                 # ShadCN components\n    layout/             # Header, Footer, Sidebar\n    features/           # Feature-specific components\n  lib/\n    utils.ts            # cn() helper + shared utilities\n    db.ts               # Database client\n    auth.ts             # Auth helpers\n  types/\n    index.ts            # Shared TypeScript types\n</code></pre>\n<h2>Step 5: CSS Architecture (Named Classes, Not Raw Tailwind in JSX)</h2>\n<pre><code class=\"language-css\">/* src/app/globals.css */\n@import \"tailwindcss\";\n\n@layer components {\n  .page-container {\n    @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;\n  }\n\n  .card-base {\n    @apply bg-white rounded-lg shadow-sm border border-gray-200 p-6;\n  }\n\n  .btn-primary {\n    @apply bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md\n           font-medium transition-colors disabled:opacity-50;\n  }\n}\n</code></pre>\n<p><strong>Rule:</strong> Named CSS classes in <code>globals.css</code>, not raw Tailwind utility strings in TSX. Keeps components readable.</p>\n<h2>Step 6: Supabase Client Setup</h2>\n<pre><code class=\"language-typescript\">// src/lib/supabase.ts\nimport { createClient } from \"@supabase/supabase-js\";\nimport type { Database } from \"@/types/database\";\n\nexport const supabase = createClient&#x3C;Database>(\n  process.env.NEXT_PUBLIC_SUPABASE_URL!,\n  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n);\n\n// Server-side client (service role — API routes only)\nexport function createServerClient() {\n  return createClient&#x3C;Database>(\n    process.env.NEXT_PUBLIC_SUPABASE_URL!,\n    process.env.SUPABASE_SERVICE_ROLE_KEY!\n  );\n}\n</code></pre>\n<h2>Step 7: Start Dev Server and Verify</h2>\n<pre><code class=\"language-bash\">npm run dev\n</code></pre>\n<p>Verify at <code>http://localhost:3000</code>:</p>\n<ul>\n<li>Default page loads without errors</li>\n<li>Browser console is clean</li>\n<li>TypeScript compiles without errors (<code>npm run type-check</code>)</li>\n<li>Lint passes (<code>npm run lint</code>)</li>\n</ul>\n<p><strong>Never move to feature development until the baseline is green.</strong></p>\n<h2>Pre-Commit Checklist</h2>\n<pre><code class=\"language-bash\"># Create .gitignore before first commit\ncat > .gitignore &#x3C;&#x3C; 'EOF'\n.env.local\n.env*.local\nnode_modules/\n.next/\nEOF\n\ngit init\ngit add .\ngit commit -m \"init: scaffold Next.js 15 + TypeScript + Tailwind + ShadCN\"\n</code></pre>\n<h2>Port Conflicts</h2>\n<pre><code class=\"language-bash\"># Kill whatever is on port 3000\nnpx kill-port 3000\n# Or use a different port\nPORT=3001 npm run dev\n</code></pre>\n"}