AI on-ramp to Oregon's public records law (ORS 192). Interview a citizen, draft a properly-scoped request, route to the right custodian, send it, and publish responses to a shared library — after human review.
See PITCH.md for the why and the team ask.
Next.js 16 (App Router, Turbopack) · TypeScript · Tailwind v4 · shadcn/ui · Drizzle ORM · Neon Postgres · Vercel AI SDK (Anthropic) · Resend (outbound + inbound) · Vercel Blob.
pnpm install
cp .env.example .env.local
# fill in DATABASE_URL, ANTHROPIC_API_KEY, RESEND_API_KEY at minimum
pnpm db:push # apply schema to the dev database
pnpm db:seed # load the hand-curated custodian directory
pnpm dev # http://localhost:3000These need human action before the dev server is useful:
- Neon Postgres — provision via Vercel Marketplace. Sets
DATABASE_URL. - Anthropic API key —
console.anthropic.com→ API keys. SetsANTHROPIC_API_KEY. - Resend — create a domain (e.g.
fifteenday.org), configure SPF/DKIM/DMARC, register an inbound route forreq-*@inbound.fifteenday.orgpointing at/api/inbound/resend. SetsRESEND_API_KEY,RESEND_WEBHOOK_SECRET,INBOUND_DOMAIN,OUTBOUND_FROM_EMAIL. - Vercel Blob — create a store in the Vercel dashboard. Sets
BLOB_READ_WRITE_TOKEN. - Admin password — generate a long random string. Sets
ADMIN_PASSWORD.
See .env.example for the full list.
The full plan lives at ~/.claude/plans/great-lets-implement-it-validated-dongarra.md.
- A — Scaffold ✅ Next.js + Tailwind + shadcn + Drizzle schema + custodian seed
- B — Interview + Draft + Send the wizard, the routing, the Resend send
- C — Inbound + Library webhook receiver, public library, admin publish toggle
- D — Stretch PDF text extraction, moderator queue, magic-link auth
- Email deliverability is the entire product's spine. New domains have terrible deliverability — warm the domain before sending to agencies.
- Manual redaction only. Inbound responses default to
published=false. A human must review before publish. Automated redaction is explicitly out of scope. - Fee waivers under ORS 192.324(5) require an explicit, user-affirmed public-interest rationale. The LLM does not decide.
- Verify every seeded custodian email before sending real requests. The seed in
lib/custodians/seed.tsis plausible but unverified.