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