build log · daily-ish
What shipped, what was hard, what Claude Code helped with.
Capturing as I go, not at the end. The discipline is to write the entry the same day the work happens — by retrospective time, the texture has already faded.
·Day 1 Sections 1-9 functional in one focused build session
Starting from the scaffolded hero repo, ran through the entire BUILD.md spine in a single session. Toolchain verification, 13 service accounts (Anthropic, Clerk, Stripe, Voyage, Exa, Trigger.dev, Resend, Sentry, Langfuse, Braintrust, GitHub, Cloudflare, plus the original Neon → Azure pivot mid-Section-3 when Neon turned out not to support Apache AGE).
Sections shipped: prerequisites, Next.js 16 + Tailwind 4 + shadcn scaffold, Postgres + AGE + pgvector + 7-table Drizzle schema + AGE graph helpers + seed, Clerk auth + proxy.ts, agent fleet (claim-detector, verifier, gap-detector, contradiction-finder, reconciler, critic, outline, cowriter, AI-detector, synonyms, explainer), Tiptap editor with custom marks + selection bubble menu + cowriter dock + typewriter scene, Braintrust eval harness with 30-entry gold set, Sentry source maps wired, Vercel config and DEPLOY.md script.
Caught and worked around 16 BUILD.md staleness items along the way — Tiptap v3 collaboration-cursor renamed to caret, @trigger.dev/nextjs deprecated, AGE LOAD restricted to superusers on Azure (use shared_preload_libraries instead), AGE cypher() needs a SQL literal not a parameter, drizzle-kit push needs a TTY, etc. Each is logged in the relevant commit.
Eval scores after expanding gold set 12 → 30: claim_count_match 100%, type_match 86.36% (crosses BUILD.md target ≥ 0.85), confidence_above_min 77.27%. Verifier smoke-tested end-to-end: Sonnet found a bibliography row via pgvector cosine search, used Exa web search to surface ContraDoc + Novarrium, marked a claim SUPPORTED at 0.81-0.85, identified a category-error tension between two seed claims.
Claude Code division of labor held: every architectural choice was author-side (Neon → Azure pivot, no-AI design register, Newsreader + Libre Franklin pairing, two-tier model routing). Drizzle table writeups, route handlers, agent scaffolding, and most of the SVG typewriter were delegated.
·Day 2 Polish + audience widening
Mobile responsive pass across landing, sign-in/up, and editor (with a "best on desktop" notice rather than pretending the editor works on phones). Newsletter publishing wired via Resend — subscribers table, anonymous /api/v1/essays/[id]/subscribe, broadcast endpoint that sends one Resend batch to all subscribers.
Three selection-driven craft tools added: context-aware synonyms, phrase explainer, and AI-detection check. The detection tool inverts AI-watermarking: instead of flagging whether someone used AI, it helps writers verify their own voice still reads as theirs. The synonym tool reads the surrounding sentence and returns alternatives with connotation notes — not a generic thesaurus. The explainer reflects a writer’s phrase back at them in plain reading + unpacked assumptions.
Typography revised twice in one day. First pass: drop Geist Sans, alias mono to Geist Mono. Second pass: drop Geist Mono visually too, alias both to Newsreader serif. Third pass: introduce Libre Franklin (open-source Franklin Gothic) for chrome — labels, tabs, footer, nav. Final state is the NYT pairing pattern: Newsreader serif body + Libre Franklin sans-grotesque chrome. Architecture-list lead-ins (“Yjs CRDT + custom Tiptap/ProseMirror schema”, etc.) styled as serif italic, like proper editorial usage of technical names.
Reorganized the editor canvas: scroll lives inside the writing surface only; cowriter bar and typewriter machine are pinned to the viewport bottom. The page fits the browser exactly at any prose length. Voice-check button moved into the document chrome row alongside publish + broadcast (was its own toolbar, read as clutter).
README rewrote with eval scores table, architecture diagram (SVG), what’s-intentionally-not-in-v1 section, status checklist filled. Decision log written: 12 load-bearing choices with tradeoffs and revisit conditions. /architecture and /build-log routes added so the footer links resolve. Custom 404 page added.