2026-03-23
What shipped today
This was the biggest single-day sprint in the project’s history — 23 issues closed across four scout runs, a Cowork product test run, a newsletter pipeline audit, Stripe setup, and a marketing questionnaire. The session ran continuously from the previous day’s rollover, driven by a combination of autonomous scouting and reactive bug fixes from Paul’s live testing.
The day’s work fell into four major themes. First, new user onboarding and signup flow — the Cowork test run exposed a chain of dead ends and missing feedback in the signup-to-first-article journey. Email confirmation was redirecting to an empty articles page instead of onboarding (#431). After signup, users saw no “check your email” message (#424). The onboarding “Start discovering” button led to an empty page with no scanning indicator (#428, #422). All of these were fixed: signup now shows a confirmation screen, email confirmation routes to onboarding, and the articles page polls for scan progress (“Scanning your sources… 2 of 4 complete”) while the pipeline runs. The onboarding wizard was also updated to mention website monitoring (#427) and the CTA was changed to “Finish setup.”
Second, conversion and billing infrastructure. Stripe was set up from scratch — product, price ($8/mo Pro), webhook endpoint, and all three env vars configured in Vercel production. The landing page Pro CTA was differentiated from the Free CTA (now links to /signup?plan=pro, and authenticated users get redirected to the billing section). A persistent but dismissible upgrade banner was added for free-tier users (#430). The “coming soon” podcast and read-later badges were removed from the landing page (#434) — read-later actually works, and podcast TTS isn’t built. An API key security issue was found and fixed: the raw Anthropic key was being sent to the browser (#429), now masked to "***".
Third, newsletter pipeline repair. The Mailgun SKIP_PATTERNS bug discovered yesterday was the tip of a larger issue. The email\.mg\. pattern was silently dropping all Mailgun-tracked links in every newsletter — which is most of them (Substack, Beehiiv, etc.). After fixing the pattern, a migration was written to reprocess all newsletters that completed with zero articles before the fix (#433), recovering previously lost content. The Brevo webhook was also hardened to wrap each item in try/catch so one failure doesn’t block the batch (#435).
Fourth, vote notes and tooltips. The article voting system was overhauled: downvotes now ask for a reason before archiving, vote notes are stored on the votes table (with a migration + backfill), and Radix UI tooltips replaced browser-native title attributes. Score badges show the AI explanation on hover, and voted thumbs show the user’s note. The podcast source filter was also fixed (was using a broken feeds.type join, now uses content_type).
Completed
- #406 — Fix NameError in website_scan: feeds vs feed_rows
- #407 — Batch link scoring in website_scan to match rss/google patterns
- #408 — Add error handling and loading states to bookmarks page
- #409 — Add security headers to Next.js config
- #410 — Consolidate two ratings queries into one in user_context
- #416 — Add voteNote to feeds.ts query and newsletter detail page
- #417 — Add tests for website_scan handler (6 tests)
- #418 — Feed scan now button doesn’t refresh the last scanned timestamp
- #419 — Add empty state to briefings page
- #420 — Add error handling to onboarding completion
- #422 — Trigger immediate scan after onboarding + scanning progress indicator
- #423 — Signup link on login page (closed as not reproducible)
- #424 — Show check-your-email confirmation after signup
- #425 — Pre-existing session hijacks “Get started free” CTA
- #426 — Show estimated time to first briefing on empty briefings page
- #427 — Update onboarding step 2 to mention website monitoring
- #428 — Onboarding CTA “Start discovering” → “Finish setup”
- #429 — Fix API key field: stop sending raw key to client
- #430 — Show dismissible upgrade banner for free-tier users
- #431 — Email confirmation redirects to /onboarding instead of /articles
- #432 — Pro CTA links to /signup?plan=pro, authenticated users go to billing
- #433 — Reprocess newsletters with zero articles from before SKIP_PATTERNS fix
- #434 — Remove coming-soon features from landing page
- #435 — Brevo webhook returns 500 on total batch failure
Also shipped (not tracked as issues):
- Newsletter SKIP_PATTERNS fix (removed email.mg. blocking all Mailgun URLs)
- Stripe product/price/webhook setup via CLI
- Marketing onboarding questionnaire for Synaxis agency
- Vote notes, tooltips, podcast filter, downvote-asks-reason flow (batch commit)
Carry-over
- Verify Stripe checkout flow end-to-end in production (product/price/webhook are test mode — need to test the full signup → upgrade → webhook path)
- Verify newsletter reprocessing migration actually recovered articles (check if the poller picked up the reset commands)
- Confirm security headers are present on production responses after Vercel deploy
- Pre-existing build error in admin users page (type mismatch on feeds name vs title)
- Engine needs redeployment on Railway to pick up all engine changes (website_scan fixes, SKIP_PATTERNS, Brevo webhook hardening, batch scoring)
Risks
- Stripe is in test mode — live payments won’t work until switched to live keys. This is intentional for testing but must be resolved before launch.
- The newsletter reprocessing migration resets commands to pending — if the engine hasn’t been redeployed with the fixed SKIP_PATTERNS, the reprocessed newsletters will hit the same bug again.
Flags and watch-outs
- API key was being leaked to the browser (fixed in #429) — no known exploitation, but worth noting for security audit
- The vote notes migration (20260323000001) backfills from engagement_events to votes.note — if any engagement events were deleted, those notes are lost
- The Brevo webhook now returns
failurescount in its response — monitor logs for non-zero failure counts - Test suite is 169 tests, all passing. New: 6 website_scan tests.
- The landing page no longer shows podcast feed or “coming soon” badges — if podcast TTS ships later, the cards need to be re-added
Why customer tools are organized wrong
This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.
Infrastructure shapes thought
The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.
Server-side dashboard architecture: Why moving data fetching off the browser changes everything
How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.
The work of being available now
A book on AI, judgment, and staying human at work.
The practice of work in progress
Practical essays on how work actually gets done.
When the queue goes empty
Most products don't fail at building. They fail at the handoff between building and becoming real. What happens when the code is done and the only things left are judgment calls?
When your agents start breaking each other's code
Two agents modified the same file independently and created database locks. The fleet hit 135 issues in one day — and the coordination problem that comes with it.
The removal tax
The most productive thing you can do with a product is take features away. Eighty-nine issues closed across eight projects, and the hardest lesson came from a pipeline that ran perfectly and produced nothing.