Files
Chandler Copeland 86e43d442c docs(17): create phase plan for Docker deployment
Two plans in 2 waves:
- Plan 01 (Wave 1): standalone output, DB pool limit, remove @vercel/blob, health endpoint
- Plan 02 (Wave 2): Dockerfile, docker-compose.yml, .dockerignore, .env.production.example

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:46:24 -06:00

7.0 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
17-docker-deployment 01 execute 1
teressa-copeland-homes/next.config.ts
teressa-copeland-homes/src/lib/db/index.ts
teressa-copeland-homes/package.json
teressa-copeland-homes/src/app/api/health/route.ts
true
DEPLOY-01
DEPLOY-02
DEPLOY-04
truths artifacts key_links
next.config.ts has output: 'standalone' so Next.js produces a self-contained server.js
Database connection pool is limited to 5 connections to avoid Neon free tier exhaustion
@vercel/blob is removed from dependencies (dead dependency)
GET /api/health returns 200 with db connectivity check
path provides contains
teressa-copeland-homes/next.config.ts Standalone output config output: 'standalone'
path provides contains
teressa-copeland-homes/src/lib/db/index.ts Pool-limited database client max: 5
path provides exports
teressa-copeland-homes/src/app/api/health/route.ts Health check endpoint
GET
from to via pattern
teressa-copeland-homes/src/app/api/health/route.ts teressa-copeland-homes/src/lib/db/index.ts db import for SELECT 1 import.*db.*from
Prepare the application codebase for Docker deployment by making four targeted code changes: enable standalone output, limit the database connection pool, remove the dead @vercel/blob dependency, and add a health check endpoint.

Purpose: These changes are prerequisites for the Dockerfile and docker-compose.yml (Plan 02). Standalone output is required for the three-stage Docker build. Pool limiting prevents Neon connection exhaustion. The health endpoint enables Docker's HEALTHCHECK directive.

Output: Modified next.config.ts, db/index.ts, package.json; new /api/health route

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/17-docker-deployment/17-CONTEXT.md

@teressa-copeland-homes/next.config.ts @teressa-copeland-homes/src/lib/db/index.ts @teressa-copeland-homes/package.json

Task 1: Enable standalone output, limit DB pool, remove @vercel/blob teressa-copeland-homes/next.config.ts, teressa-copeland-homes/src/lib/db/index.ts, teressa-copeland-homes/package.json - teressa-copeland-homes/next.config.ts - teressa-copeland-homes/src/lib/db/index.ts - teressa-copeland-homes/package.json 1. **next.config.ts** (per D-05): Add `output: 'standalone'` to the NextConfig object. Keep existing `transpilePackages` and `serverExternalPackages` intact. Result: ```typescript const nextConfig: NextConfig = { output: 'standalone', transpilePackages: ['react-pdf', 'pdfjs-dist'], serverExternalPackages: ['@napi-rs/canvas'], }; ```
2. **src/lib/db/index.ts** (per D-08): Change `postgres(url)` to `postgres(url, { max: 5 })` in the `createDb` function. This limits the connection pool to 5 connections, leaving headroom on Neon's free tier (10 max). Change line 12 from:
```typescript
const client = postgres(url);
```
to:
```typescript
const client = postgres(url, { max: 5 });
```

3. **package.json** (per D-09): Remove `@vercel/blob` from dependencies. Run `npm uninstall @vercel/blob` from the `teressa-copeland-homes` directory. This removes the dead dependency that is imported nowhere in the codebase. Verify no import of `@vercel/blob` exists in src/ after removal.
cd /Users/ccopeland/temp/red/teressa-copeland-homes && grep -q "output: 'standalone'" next.config.ts && grep -q "max: 5" src/lib/db/index.ts && ! grep -q "@vercel/blob" package.json && echo "PASS" - `grep "output: 'standalone'" teressa-copeland-homes/next.config.ts` returns a match - `grep "max: 5" teressa-copeland-homes/src/lib/db/index.ts` returns a match - `grep "@vercel/blob" teressa-copeland-homes/package.json` returns NO match - `grep -r "@vercel/blob" teressa-copeland-homes/src/` returns NO match - `transpilePackages` and `serverExternalPackages` still present in next.config.ts next.config.ts has standalone output, db pool is limited to 5, @vercel/blob removed from package.json Task 2: Create /api/health endpoint with DB connectivity check teressa-copeland-homes/src/app/api/health/route.ts - teressa-copeland-homes/src/lib/db/index.ts - teressa-copeland-homes/src/lib/db/schema.ts (first 20 lines, for import pattern) Create `src/app/api/health/route.ts` (per D-10). This is a public endpoint (no auth) that: - Runs `SELECT 1` via the Drizzle db client using `db.execute(sql\`SELECT 1\`)` - Returns `{ ok: true, db: 'connected' }` with status 200 on success - Returns `{ ok: false, error: message }` with status 503 on failure - Wraps the DB call in try/catch
Full file content:
```typescript
import { db } from '@/lib/db';
import { sql } from 'drizzle-orm';

export async function GET() {
  try {
    await db.execute(sql`SELECT 1`);
    return Response.json({ ok: true, db: 'connected' });
  } catch (e) {
    const message = e instanceof Error ? e.message : 'Unknown error';
    return Response.json({ ok: false, error: message }, { status: 503 });
  }
}
```

No auth check — this endpoint is intentionally public so Docker HEALTHCHECK can reach it without credentials.
cd /Users/ccopeland/temp/red/teressa-copeland-homes && test -f src/app/api/health/route.ts && grep -q "SELECT 1" src/app/api/health/route.ts && grep -q "export async function GET" src/app/api/health/route.ts && echo "PASS" - File exists at `teressa-copeland-homes/src/app/api/health/route.ts` - File exports a GET function - File contains `SELECT 1` database check - File returns `{ ok: true, db: 'connected' }` on success - File returns status 503 on failure - No auth import or session check present GET /api/health endpoint exists, runs SELECT 1 via Drizzle, returns 200/503 based on DB reachability All code changes compile: ```bash cd teressa-copeland-homes && npx tsc --noEmit ```

<success_criteria>

  • next.config.ts has output: 'standalone' alongside existing config
  • db/index.ts creates postgres client with { max: 5 }
  • @vercel/blob removed from package.json dependencies
  • /api/health route exists and checks DB connectivity
  • npx tsc --noEmit passes </success_criteria>
After completion, create `.planning/phases/17-docker-deployment/17-01-SUMMARY.md`