---
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*
