---
phase: 01-foundation
plan: 01
subsystem: auth
tags: [next-auth, jwt, drizzle-orm, neon, postgresql, bcryptjs, zod, vercel-blob, next.js]

# Dependency graph
requires: []
provides:
  - Next.js 16.2.0 project scaffold with TypeScript, Tailwind CSS, App Router
  - src/lib/db/schema.ts — users table (id, email, password_hash, created_at)
  - src/lib/db/index.ts — Drizzle + Neon HTTP lazy singleton
  - src/lib/auth.ts — Auth.js v5 JWT strategy, 7-day rolling session, Credentials provider
  - middleware.ts — /agent/* route protection at project root
  - scripts/seed.ts — one-time seeder for Teressa's account
  - drizzle/0000_milky_black_cat.sql — committed SQL migration for users table
  - drizzle.config.ts — Drizzle Kit config pointing to schema.ts
affects:
  - 01-02
  - 01-03
  - all subsequent phases that import from @/lib/auth or @/lib/db

# Tech tracking
tech-stack:
  added:
    - next-auth@5.0.0-beta.30 (pinned exact version)
    - drizzle-orm@0.45.1
    - @neondatabase/serverless@1.0.2
    - bcryptjs@3.0.3
    - @vercel/blob@2.3.1
    - zod@4.3.6
    - drizzle-kit@0.31.10
    - tsx@4.21.0
    - dotenv@17.3.1
  patterns:
    - Auth.js v5 Credentials provider with JWT strategy (no adapter, no server-side sessions)
    - Drizzle ORM with Neon HTTP driver (serverless-compatible)
    - Lazy Proxy singleton for db initialization (prevents build-time crash without DATABASE_URL)
    - middleware.ts at project root (not src/) for Next.js edge middleware
    - export const dynamic = 'force-dynamic' on auth API route

key-files:
  created:
    - teressa-copeland-homes/src/lib/auth.ts
    - teressa-copeland-homes/src/lib/db/schema.ts
    - teressa-copeland-homes/src/lib/db/index.ts
    - teressa-copeland-homes/middleware.ts
    - teressa-copeland-homes/scripts/seed.ts
    - teressa-copeland-homes/drizzle.config.ts
    - teressa-copeland-homes/drizzle/0000_milky_black_cat.sql
    - teressa-copeland-homes/src/app/api/auth/[...nextauth]/route.ts
  modified:
    - teressa-copeland-homes/package.json

key-decisions:
  - "next-auth pinned to exact version 5.0.0-beta.30 (not 'beta' alias)"
  - "db:migrate and db:seed pending — require Neon DATABASE_URL from user setup"
  - "middleware.ts at project root, not inside src/ (silently ignored by Next.js if in src/)"
  - "Lazy Proxy singleton for db prevents neon() crash when DATABASE_URL not set during build"
  - "force-dynamic on /api/auth/[...nextauth] route marks it as server-rendered on demand"

patterns-established:
  - "Lazy db singleton pattern: never call neon() at module scope; use Proxy wrapper"
  - "Auth route force-dynamic: all Next.js auth routes require dynamic = force-dynamic"
  - "Drizzle migrations committed to repo for auditable schema history"

requirements-completed: [AUTH-01, AUTH-02, AUTH-03]

# Metrics
duration: 6min
completed: 2026-03-19
---

# Phase 1 Plan 01: Foundation Scaffold Summary

**Next.js 16.2.0 project with Auth.js v5 JWT + Credentials auth, Drizzle ORM + Neon HTTP schema, and /agent/* route protection middleware — all foundation contracts for Plans 02 and 03**

## Performance

- **Duration:** ~6 min
- **Started:** 2026-03-19T19:27:22Z
- **Completed:** 2026-03-19T19:33:46Z
- **Tasks:** 3
- **Files modified:** 9 created, 1 modified

## Accomplishments

- Scaffolded Next.js 16.2.0 project with TypeScript, Tailwind CSS 4, ESLint, App Router, src dir
- Defined users table schema and Drizzle + Neon HTTP db singleton with lazy initialization
- Configured Auth.js v5 with JWT strategy, 7-day rolling session, Credentials provider, bcrypt password verification
- Created route protection middleware at project root protecting all /agent/* routes
- Generated and committed Drizzle SQL migration (drizzle/0000_milky_black_cat.sql)

## Task Commits

Each task was committed atomically:

1. **Task 1: Scaffold Next.js 15 project and install all dependencies** - `dac1bc8` (feat)
2. **Task 2: Define database schema, configure Drizzle Kit, and write seed script** - `f46e702` (feat)
3. **Task 3: Configure Auth.js v5 with JWT strategy and create route-protection middleware** - `e5db79a` (feat)

## Files Created/Modified

- `teressa-copeland-homes/package.json` - Added db:generate, db:migrate, db:seed, db:studio scripts; pinned next-auth@5.0.0-beta.30
- `teressa-copeland-homes/src/lib/db/schema.ts` - users table (id, email, password_hash, created_at)
- `teressa-copeland-homes/src/lib/db/index.ts` - Drizzle + Neon HTTP lazy singleton via Proxy
- `teressa-copeland-homes/drizzle.config.ts` - Drizzle Kit config with postgresql dialect
- `teressa-copeland-homes/drizzle/0000_milky_black_cat.sql` - CREATE TABLE users migration
- `teressa-copeland-homes/scripts/seed.ts` - Seeds Teressa's account from AGENT_EMAIL + AGENT_PASSWORD env vars
- `teressa-copeland-homes/src/lib/auth.ts` - NextAuth config: JWT, 7-day session, Credentials provider with bcrypt
- `teressa-copeland-homes/src/app/api/auth/[...nextauth]/route.ts` - GET/POST handlers + force-dynamic
- `teressa-copeland-homes/middleware.ts` - /agent/* route guard at project root

## Decisions Made

- **next-auth pinned to 5.0.0-beta.30** — exact version, no caret, as required to avoid accidental beta upgrades
- **db:migrate and db:seed not yet run** — requires user to provision Neon database first; these commands are ready to run after `vercel env pull` populates DATABASE_URL
- **middleware.ts at project root** — confirmed NOT inside src/ (Next.js silently ignores middleware placed in src/)
- **Lazy Proxy singleton for db** — prevents neon() from crashing at build time when DATABASE_URL is absent; auto-fixed deviation from plan's original eager initialization
- **force-dynamic on auth API route** — signals Next.js to never statically prerender the auth route

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 1 - Bug] Lazy Proxy singleton for Neon db connection**
- **Found during:** Task 3 (Auth.js configuration and build verification)
- **Issue:** Original `src/lib/db/index.ts` called `neon(process.env.DATABASE_URL!)` at module scope. During `npm run build`, Next.js "collects page data" by evaluating all route modules, which triggered the auth route import chain → db/index.ts → `neon()` → crash: "No database connection string was provided to `neon()`"
- **Fix:** Replaced eager initialization with a Proxy-based lazy singleton. `neon()` and `drizzle()` are only called on first property access (i.e., first actual database query), not at import time.
- **Files modified:** `teressa-copeland-homes/src/lib/db/index.ts`
- **Verification:** `npm run build` passes; /api/auth/[...nextauth] shows as Dynamic (ƒ) route
- **Committed in:** `e5db79a` (Task 3 commit)

**2. [Rule 1 - Bug] Added force-dynamic to auth API route**
- **Found during:** Task 3 (Build verification)
- **Issue:** Next.js attempted to statically analyze the auth route during build even though it handles authentication requests that are always dynamic
- **Fix:** Added `export const dynamic = 'force-dynamic'` to the route handler
- **Files modified:** `teressa-copeland-homes/src/app/api/auth/[...nextauth]/route.ts`
- **Verification:** Build passes; route renders as server-rendered on demand
- **Committed in:** `e5db79a` (Task 3 commit)

---

**Total deviations:** 2 auto-fixed (both Rule 1 - Bug)
**Impact on plan:** Both fixes required for correct build-time behavior. No change to exported interfaces or auth contracts. All downstream plans (02, 03) depend on the same exports.

## Issues Encountered

None beyond the auto-fixed build-time Neon initialization issue above.

## User Setup Required

**External services require manual configuration before db:migrate and db:seed can run.**

Three services need to be provisioned:

1. **Neon (PostgreSQL):**
   - Create project 'teressa-copeland-homes' at https://console.neon.tech/app/new (us-east-1)
   - Get the Pooled connection string (?sslmode=require URL)
   - Set `DATABASE_URL` in Vercel Dashboard environment variables

2. **Vercel Blob:**
   - Create Blob store 'teressa-copeland-homes-blob' in Vercel Dashboard → Storage
   - Set `BLOB_READ_WRITE_TOKEN` in Vercel Dashboard environment variables

3. **Vercel Project:**
   - Create project at https://vercel.com/new linked to the Git repo
   - Generate AUTH_SECRET with `npx auth secret`
   - Set all 5 env vars: DATABASE_URL, BLOB_READ_WRITE_TOKEN, AUTH_SECRET, AGENT_EMAIL, AGENT_PASSWORD

**After setup, run:**
```bash
vercel env pull        # Pulls env vars to .env.local
npm run db:migrate     # Applies migration to Neon
npm run db:seed        # Creates Teressa's account
```

## Next Phase Readiness

- Foundation contracts ready: `auth.ts`, `schema.ts`, `db/index.ts`, `middleware.ts`, `seed.ts` all committed
- Plan 02 (login UI) and Plan 03 (agent dashboard) can proceed immediately — they import from `@/lib/auth` and `@/lib/db`
- Build passes with zero TypeScript errors
- Blockers: Neon + Vercel setup required before runtime features work (but code compiles without them)

## Self-Check: PASSED

All key files verified present:
- FOUND: teressa-copeland-homes/src/lib/auth.ts
- FOUND: teressa-copeland-homes/src/lib/db/schema.ts
- FOUND: teressa-copeland-homes/src/lib/db/index.ts
- FOUND: teressa-copeland-homes/middleware.ts
- FOUND: teressa-copeland-homes/scripts/seed.ts
- FOUND: teressa-copeland-homes/drizzle.config.ts
- FOUND: teressa-copeland-homes/drizzle/0000_milky_black_cat.sql
- FOUND: teressa-copeland-homes/src/app/api/auth/[...nextauth]/route.ts

All task commits verified in git log:
- FOUND: dac1bc8 (Task 1)
- FOUND: f46e702 (Task 2)
- FOUND: e5db79a (Task 3)

---
*Phase: 01-foundation*
*Completed: 2026-03-19*
