# 03 — Drizzle + Postgres setup ## Goal Wire Drizzle ORM to a Postgres 16 instance, with migrations and a working `db` client. ## Depends on - 02 (Next.js skeleton) ## Scope - Install `drizzle-orm`, `drizzle-kit`, `postgres` (the `postgres` driver, not `pg`). - `drizzle.config.ts` pointing at `src/modules/**/schema.ts` and writing to `./drizzle/`. - `src/lib/db.ts` exporting a singleton `db` client built from `DATABASE_URL`. - Initial schema in `src/modules/_core/schema.ts`: - `users` (id uuid pk, email unique, display_name, created_at) - `households` (id uuid pk, name, created_at) - `household_members` (household_id, user_id, role enum: `owner` | `member`, pk on both) - pnpm scripts: `db:generate`, `db:migrate`, `db:studio`. - `docker-compose.dev.yaml` at repo root with a `famapp-db` service for local dev (Postgres 16, exposed on 5432, named volume). ## Out of scope - Module-specific tables (calendar/lists/notes ship in their own tasks). - Seed data (in task 07). ## Acceptance criteria - [ ] `docker compose -f docker-compose.dev.yaml up -d` starts Postgres locally. - [ ] `pnpm db:generate && pnpm db:migrate` produces `drizzle/0000_*.sql` and applies it. - [ ] A throwaway script can `import { db } from "@/lib/db"` and `select` from `users` (returning empty). - [ ] `tsc --noEmit` passes. ## Notes - Use the `postgres` driver — works in both Node and edge-light contexts and is what Drizzle docs prefer for serverless-shaped apps. - Keep the dev compose file separate from the production `deploy/compose.yaml` (task 05).