Files
clienthub/.planning/phases/01-foundation-client-dashboard/01-01-PLAN.md
T
Simone Cavalli 81c667838f docs(01-foundation-client-dashboard): complete phase 1 planning with 5-plan structure
Create comprehensive phase plans for Foundation & Client Dashboard:
- 01-01-PLAN.md: Walking Skeleton (Next.js 15 bootstrap + DB connection)
- 01-02-PLAN.md: Database schema (11 tables, Drizzle ORM, drizzle-kit push)
- 01-03-PLAN.md: Middleware token validation + ClientView type + data fetching
- 01-04-PLAN.md: Client dashboard UI (header, timeline, progress, payments, docs, notes)
- 01-05-PLAN.md: Seed script + DNS CNAME configuration

Also create SKELETON.md documenting locked architectural decisions for all future phases:
- Next.js 15 + Drizzle + postgres-js driver (Coolify Postgres)
- Token as separate rotatable field (not PK)
- ClientView enforcement (no quote_items exposed to client API)
- Approved_at immutable audit trail
- Two independent auth systems (client token + admin session)
- Vercel deployment with custom domain

Update ROADMAP.md to mark Phase 1 as planned (5 plans created) and ready for execution.

All plans follow MVP vertical-slice structure with 2-3 tasks per plan.
Walking Skeleton proves the entire stack works end-to-end.
Requirements mapping: DASH-01 through DASH-04, DASH-07 through DASH-10 covered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 11:27:19 +02:00

9.6 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
01-foundation-client-dashboard 01 execute 1
package.json
tsconfig.json
next.config.ts
src/app/layout.tsx
src/app/page.tsx
.env.local
true
DASH-01
DASH-02
truths artifacts key_links
Next.js 15 App Router is bootstrapped and compiles without errors
DATABASE_URL env var is set and Drizzle can connect to Postgres
A simple test route exists and responds with 200
TypeScript strict mode is enabled
path provides contains
package.json All dependencies for Next.js + Drizzle + auth + UI next@15
path provides min_lines
src/app/layout.tsx Root layout with Tailwind setup 15
path provides contains
.env.local DATABASE_URL pointing to Coolify Postgres DATABASE_URL
from to via pattern
.env.local Drizzle client initialization process.env.DATABASE_URL DATABASE_URL=postgres://
from to via pattern
src/db/index.ts Postgres on Coolify postgres-js driver import.*postgres.*from.*postgres-js
**Walking Skeleton:** Bootstrap the Next.js project, install all Phase 1 dependencies, configure Tailwind, connect to the Postgres database on Coolify via Drizzle ORM, and verify the entire stack is operational with a simple test route.

Purpose: Establish the project foundation so subsequent plans can build on a known-good state. This plan proves Next.js 15 + Drizzle + postgres-js + Tailwind work together before writing any feature code.

Output: Runnable Next.js dev server (npm run dev) with DB connection confirmed, TypeScript types working, Tailwind CSS active, ready for schema creation.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-foundation-client-dashboard/01-CONTEXT.md @.planning/research/STACK.md @.planning/research/ARCHITECTURE.md Task 1: Bootstrap Next.js 15 with TypeScript, App Router, src/ directory, and Tailwind CSS v4 package.json tsconfig.json next.config.ts src/app/layout.tsx src/app/page.tsx tailwind.config.ts postcss.config.mjs .gitignore None (greenfield project) Execute: `npx create-next-app@latest . --typescript --tailwind --app --src-dir --eslint --import-alias '@/*'`
Verify created:
- `src/` directory with `app/` subdirectory
- `tsconfig.json` with `"strict": true`
- `tailwind.config.ts` (v4, CSS-first)
- `postcss.config.mjs`
- Next.js 15.x in package.json

After creation, modify `src/app/layout.tsx`:
- Import Tailwind globals: `import './globals.css'`
- Set viewport and basic meta tags
- Ensure `<html>` and `<body>` exist with proper className for Tailwind

Modify `src/app/page.tsx`:
- Replace default template with a simple div: `<div className="text-center py-20">Welcome to ClientHub</div>`
- Keep it minimal — this route will be replaced in Phase 2
grep -q "\"next\": \"^15" package.json && echo "Next.js 15 installed" grep -q "\"strict\": true" tsconfig.json && echo "TypeScript strict mode enabled" test -f src/app/layout.tsx && grep -q "globals.css" src/app/layout.tsx && echo "Tailwind globals imported" test -f next.config.ts && echo "next.config.ts exists" - `npm install` succeeds without errors - `npm run build` succeeds (no TypeScript errors, no Next.js errors) - `npm run dev` starts server without crashing - Visiting http://localhost:3000 returns 200 and displays the welcome message Task 2: Install Drizzle ORM, postgres-js, and supporting libraries; create .env.local with DATABASE_URL package.json .env.local .env.example src/db/index.ts None (greenfield) Install packages: ``` npm install drizzle-orm postgres npm install -D drizzle-kit ```
Note: The package is `postgres` (not `postgres-js` — that's the npm package name for postgres-js driver).

Create `src/db/index.ts`:
```typescript
import { Client } from 'postgres';
import * as schema from './schema';

if (!process.env.DATABASE_URL) {
  throw new Error('DATABASE_URL env var is required');
}

const client = new Client({
  connectionString: process.env.DATABASE_URL,
});

export const db = drizzle(client, { schema });
```

Create `.env.local`:
```
DATABASE_URL=postgresql://[user]:[password]@[coolify-host]:5432/[database]
```
Use the actual Coolify credentials. If not yet available, use a placeholder and update before plan 02.

Create `.env.example`:
```
DATABASE_URL=postgresql://user:password@host:5432/database
```

Install additional dependencies:
```
npm install nanoid zod @hookform/resolvers react-hook-form
npm install -D @types/node
```

Auth.js will be installed in a later plan (Phase 2 only).
grep -q "drizzle-orm" package.json && echo "Drizzle installed" grep -q "postgres" package.json && echo "postgres-js installed" grep -q "drizzle-kit" package.json && echo "drizzle-kit installed" test -f .env.local && grep -q "DATABASE_URL" .env.local && echo ".env.local exists with DATABASE_URL" test -f .env.example && echo ".env.example exists" grep -q "postgres" src/db/index.ts && echo "postgres-js driver imported in db/index.ts" - `npm install` succeeds - `src/db/index.ts` exists and exports `db` object - `.env.local` contains DATABASE_URL (value will be filled in by executor or user) - `npm run build` succeeds with no import errors Task 3: Install shadcn/ui components and configure; add lucide-react icons package.json components.json src/components/ui/*.tsx (multiple) tailwind.config.ts Initialize shadcn/ui: ``` npx shadcn@latest init --yes ```
This creates `components.json` with the proper configuration.

Add essential components for Phase 1:
```
npx shadcn@latest add button card badge progress input label select separator table textarea
```

Install lucide-react:
```
npm install lucide-react
```

Verify `src/components/ui/` directory contains all component files.
test -f components.json && echo "components.json created" test -d src/components/ui && ls src/components/ui/ | wc -l | grep -qE "[0-9]+" && echo "UI components installed" grep -q "lucide-react" package.json && echo "lucide-react installed" - `components.json` exists with proper shadcn configuration - At least 8 component files exist in `src/components/ui/` - `npm run build` succeeds

<threat_model>

Trust Boundaries

Boundary Description
Client (browser) → API Clients access /c/[token]/* routes; middleware must validate token
Client (browser) → Database Drizzle queries filtered by token; no client can see other clients' data
Admin → Vercel environment variables DATABASE_URL, future ADMIN_PASSWORD must be secret

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-01-001 Information Disclosure DATABASE_URL in .env.local mitigate Never commit .env.local; .gitignore enforces this; use Vercel Secrets for production
T-01-002 Tampering Schema initialization mitigate Use Drizzle migrations + drizzle-kit push before any data is written; immutable migration history
T-01-003 Denial of Service Database connection pooling accept postgres-js handles connection lifecycle; Coolify Postgres has resource limits acceptable for Phase 1 scale

</threat_model>

After plan execution: 1. Run `npm run build` → no errors 2. Run `npm run dev` → server starts on http://localhost:3000 3. Visit http://localhost:3000 → page loads with welcome message 4. Check `src/db/index.ts` → imports postgres-js correctly 5. Check `.env.local` → DATABASE_URL is set (value may be placeholder) 6. Check `components.json` → exists with @/ alias

<success_criteria>

  • Next.js dev server starts and responds to requests
  • TypeScript compiles without errors
  • Tailwind CSS is active (can verify via DevTools)
  • Database connection string is configured (even if not yet tested with actual DB)
  • All Phase 1 dependencies are installed
  • Ready to proceed to Task 02 (schema creation) </success_criteria>
After completion, create `.planning/phases/01-foundation-client-dashboard/01-01-SUMMARY.md`