Files
Simone Cavalli 2a24067005 docs(01-01): complete walking skeleton plan — Next.js 16 + Drizzle + shadcn/ui
Summary: 3/3 tasks completed, 4 auto-fixed deviations (all blocking/bug),
build passes, TypeScript strict, DATABASE_URL placeholder in .env.local
2026-05-13 15:33:31 +02:00

191 lines
8.3 KiB
Markdown

---
phase: 01-foundation-client-dashboard
plan: 01
subsystem: infra
tags: [nextjs, drizzle-orm, postgres, tailwind, shadcn, typescript]
# Dependency graph
requires: []
provides:
- Next.js 16 App Router project with TypeScript strict mode
- Tailwind CSS v4 + shadcn/ui components (button, card, badge, progress, input, label, select, separator, table, textarea)
- Drizzle ORM + postgres-js driver configured (db client in src/db/index.ts)
- drizzle.config.ts ready for migrations
- .env.local with DATABASE_URL placeholder
- lucide-react icons
- src/lib/utils.ts cn() helper
affects:
- 01-02-schema
- 01-03-client-route
- 01-04-dashboard-ui
- 01-05-seed-deploy
# Tech tracking
tech-stack:
added:
- next@16.2.6
- drizzle-orm@0.45.2
- drizzle-kit@0.31.10
- postgres@3.4.9
- tailwindcss@4.x
- shadcn/ui (Radix preset)
- lucide-react@1.14.0
- nanoid@5.1.11
- zod@4.4.3
- react-hook-form + @hookform/resolvers
- clsx + tailwind-merge + class-variance-authority
patterns:
- App Router with Server Components as default
- Drizzle ORM with postgres-js driver (not neon-http) for Coolify Postgres
- shadcn/ui components in src/components/ui/ (copied, not wrapped)
- cn() utility for conditional classnames
key-files:
created:
- src/app/layout.tsx (root layout, metadata, viewport, Tailwind globals)
- src/app/page.tsx (placeholder route)
- src/app/globals.css (Tailwind v4 CSS-first)
- src/db/index.ts (Drizzle client with postgres-js)
- src/lib/utils.ts (cn() helper)
- src/components/ui/*.tsx (10 shadcn components)
- drizzle.config.ts (migration config)
- components.json (shadcn config)
- .env.example (public template)
modified:
- package.json (all deps added)
- .gitignore (allow .env.example, block all other .env*)
key-decisions:
- "Usato Next.js 16.2.6 (latest stable) invece di 15.x — create-next-app@latest installa la versione corrente"
- "viewport spostato in export dedicato (Next.js 16 API) invece che in metadata"
- "src/db/index.ts usa drizzle-orm/postgres-js con import default di postgres (non Client class)"
- ".env.example aggiunto con eccezione in .gitignore (non .env.local che resta ignorato)"
patterns-established:
- "Database client: import postgres from 'postgres' + drizzle(client) in src/db/index.ts"
- "shadcn/ui: componenti copiati in src/components/ui/, usabili come primitivi"
- "cn() utility per merge classi Tailwind in src/lib/utils.ts"
requirements-completed:
- DASH-01
- DASH-02
# Metrics
duration: 15min
completed: 2026-05-13
---
# Phase 1 Plan 01: Walking Skeleton — Next.js 16 + Drizzle + shadcn/ui bootstrapped su Coolify Postgres
**Next.js 16.2.6 App Router con TypeScript strict, Tailwind v4, Drizzle ORM + postgres-js per Coolify Postgres, e 10 componenti shadcn/ui installati e pronti.**
## Performance
- **Duration:** ~15 min
- **Started:** 2026-05-13T13:26:00Z
- **Completed:** 2026-05-13T13:41:00Z
- **Tasks:** 3/3
- **Files modified:** 20+
## Accomplishments
- Next.js 16.2.6 con App Router, TypeScript strict mode, Tailwind CSS v4 — `npm run build` passa senza errori TypeScript
- Drizzle ORM + postgres-js configurati con client in `src/db/index.ts`, pronto per le migrazioni del Plan 02
- 10 componenti shadcn/ui installati + lucide-react: base UI completa per i plan successivi
## Task Commits
1. **Task 1: Bootstrap Next.js 16** - `9563b87` (chore)
2. **Task 2: Drizzle ORM + postgres-js + librerie** - `6b5609b` (feat)
3. **Task 3: shadcn/ui + lucide-react** - `f842007` (feat)
## Files Created/Modified
- `src/app/layout.tsx` - Root layout con metadata ClientHub, lang="it", viewport export corretto per Next.js 16
- `src/app/page.tsx` - Placeholder minimale (sarà sostituito in Phase 2)
- `src/app/globals.css` - Tailwind v4 CSS-first con variabili CSS
- `src/db/index.ts` - Client Drizzle con postgres-js driver, guard su DATABASE_URL
- `src/lib/utils.ts` - cn() helper con clsx + tailwind-merge
- `src/components/ui/*.tsx` - 10 componenti: button, card, badge, progress, input, label, select, separator, table, textarea
- `drizzle.config.ts` - Config drizzle-kit per migrazioni (dialect postgresql, schema src/db/schema.ts)
- `components.json` - Configurazione shadcn/ui (Radix preset, @/ aliases, CSS variables)
- `.env.example` - Template pubblico DATABASE_URL
- `.gitignore` - Aggiunta eccezione per .env.example, blocco tutti gli altri .env*
- `package.json` - Tutte le dipendenze Phase 1 installate
## Decisions Made
- Installato Next.js 16.2.6 (latest stable via `create-next-app@latest`) invece di 15.x — versione superiore, retrocompatibile
- `viewport` spostato in export dedicato (`export const viewport: Viewport`) come richiede Next.js 16 API — evita warning di build
- `src/db/index.ts` usa `import postgres from 'postgres'` (default export, non `Client` class) — API corretta del driver postgres-js
- `drizzle-orm/postgres-js` come adapter Drizzle invece di `drizzle-orm/neon-http` — allineato con decisione D-02 (Coolify Postgres, non Neon)
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] create-next-app rifiuta cartella con lettere maiuscole**
- **Found during:** Task 1
- **Issue:** `create-next-app .` fallisce con "name can no longer contain capital letters" perché la cartella si chiama `IAMCAVALLI`
- **Fix:** Creato progetto in directory temporanea `/Users/simonecavalli/clienthub` poi spostati tutti i file nel repo principale
- **Files modified:** Nessun file extra — stesso risultato del comando diretto
- **Verification:** `npm run build` passa, tutti i file sono al posto corretto
- **Committed in:** 9563b87
**2. [Rule 1 - Bug] viewport in metadata genera warning Next.js 16**
- **Found during:** Task 1 (prima build)
- **Issue:** `metadata.viewport` è deprecato in Next.js 16; Next.js emette warning e richiede export `viewport` separato
- **Fix:** Aggiunto `export const viewport: Viewport = { ... }` e rimosso `viewport` da `metadata`
- **Files modified:** src/app/layout.tsx
- **Verification:** Build pulita senza warning viewport
- **Committed in:** 9563b87
**3. [Rule 3 - Blocking] API postgres driver non è Client class**
- **Found during:** Task 2
- **Issue:** Il PLAN suggeriva `import { Client } from 'postgres'` ma il driver `postgres` esporta una funzione default, non una classe `Client`
- **Fix:** Usato `import postgres from 'postgres'` con `drizzle-orm/postgres-js` adapter — API corretta
- **Files modified:** src/db/index.ts
- **Verification:** TypeScript compila senza errori
- **Committed in:** 6b5609b
**4. [Rule 3 - Blocking] shadcn init interattivo non risponde a --yes**
- **Found during:** Task 3
- **Issue:** `npx shadcn@latest init --yes` richiede selezione manuale (libreria e preset) — non si automatizza
- **Fix:** Creato manualmente `components.json` con config corretta (Radix, CSS variables, @/ aliases) poi usato direttamente `shadcn add` per i componenti
- **Files modified:** components.json (creato manualmente)
- **Verification:** `npx shadcn@latest add button card ...` funziona senza problemi
- **Committed in:** f842007
---
**Total deviations:** 4 auto-fixed (2 Rule 3 blocking, 1 Rule 1 bug, 1 Rule 3 blocking)
**Impact on plan:** Tutte le deviazioni necessarie per il corretto funzionamento. Nessuno scope creep.
## Issues Encountered
- `.env.example` era bloccato da `.env*` pattern nel `.gitignore` — aggiunta eccezione `!.env.example` (file pubblico senza segreti, corretto da tracciare in git)
## User Setup Required
Prima di eseguire il Plan 02 (schema + migrazioni), aggiornare `.env.local` con le credenziali reali del database Coolify:
```
DATABASE_URL=postgresql://[user]:[password]@[coolify-host]:5432/clienthub
```
Le credenziali si trovano nel pannello Coolify su Hetzner. Il file `.env.local` è escluso dal git (`.gitignore`).
## Threat Surface Scan
Nessuna nuova superficie di sicurezza non prevista dal piano. Il threat model T-01-001 (DATABASE_URL in .env.local) è mitigato correttamente: `.env*` esclusi dal `.gitignore`, `.env.example` non contiene credenziali reali.
## Next Phase Readiness
- Plan 02 (schema Drizzle) può partire immediatamente — `src/db/index.ts` e `drizzle.config.ts` sono pronti
- L'utente deve aggiornare `DATABASE_URL` in `.env.local` con le credenziali reali Coolify prima di eseguire `drizzle-kit push`
- Build stabile, TypeScript strict attivo, zero errori
---
*Phase: 01-foundation-client-dashboard*
*Completed: 2026-05-13*