Build log

Everything we ship, one commit at a time — building in public.

BUILD LOGNL-04 fixes: use after()for reliable welcome send,add tests + runbook
NL-04 fixes: use after() for reliable welcome send, add tests + runbook

- app/api/subscribe/route.ts: replace fire-and-forget with after() from next/server — uses waitUntil on Vercel so the welcome send survives the serverless lifecycle - Add vitest + 8 tests for welcome dedup contract, unsub tokens, send guard - docs/NL-RUNBOOK.md: complete copy-paste runbook for all three tasks (NL-02/03/04) with DRY_RUN, live commands, migration verification, DNS checks, and DONE WHEN proofs

10/26/2026fc0c7fb
BUILD LOGNL-03 fixes: SPF mergesafety, DMARC no-overwrite(p=none), custom MAILFROM, tests
NL-03 fixes: SPF merge safety, DMARC no-overwrite (p=none), custom MAIL FROM, tests

- SPF: reads existing apex TXT, merges include:amazonses.com — never creates second SPF, never drops existing mechanisms - DMARC: does not overwrite existing _dmarc record; defaults to p=none (monitoring) not quarantine - Custom MAIL FROM: bounce.{domain} MX + SPF for DMARC SPF alignment (region configurable via AWS_REGION) - CLI script shows before/after for SPF merge in dry-run - Add vitest + 17 tests covering all pure functions - Admin API GET now includes plan notes

10/26/20261a89f19
BUILD LOGNL-02 fixes: drop CNAME(Workers Custom Domainsmanage DNS), fix pathencoding, add tests
NL-02 fixes: drop CNAME (Workers Custom Domains manage DNS), fix path encoding, add tests

- Remove cfEnsureProxiedDns from admin route — Workers Custom Domains auto-manage DNS records - Remove CNAME step from deploy script — same reason; also remove unused node:fs imports - Fix worker script: don't encodeURIComponent the domain in /p/{domain} path (Next.js expects raw) - Add vitest + 16 tests: hostname extraction (multi-part TLDs), worker script assertions, sitemap host logic

10/26/2026aee04eb
BUILD LOGCount real visitors withVNOC Analytics
Count real visitors with VNOC Analytics
10/23/2026c46f4eb
BUILD LOGDocument Vercel env varsfor smaller-domain mailand deliverability.
Document Vercel env vars for smaller-domain mail and deliverability.

Co-authored-by: Cursor <[email protected]>

10/17/2026843948d
BUILD LOGAdd mail routing forsmaller domains withshared deliverabilitychecks.
Add mail routing for smaller domains with shared deliverability checks.

Wire a single outbound mailer, consent-safe welcome and confirm flows, and pre-send verification so smaller domains can run without mixing into the main track. Co-authored-by: Cursor <[email protected]>

10/17/2026ab09f2f
BUILD LOGdocs(plan): phase 1 taskfor the smaller-domainnewsletter track
docs(plan): phase 1 task for the smaller-domain newsletter track
10/16/2026b31a670
BUILD LOGdocs(plan): automatednewsletter track forsmaller domains
docs(plan): automated newsletter track for smaller domains
10/16/20262862c59
BUILD LOGNL-01: Seed defaultdraft-only Site Config forqualified domains withfeeds so existing
NL-01: Seed default draft-only Site Config for qualified domains with feeds so existing compose/auto crons pick them up

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

10/12/20260ac43cd
BUILD LOGNL-UI-02: Bring the sentemail HTML into visualparity with the livearchive page
NL-UI-02: Bring the sent email HTML into visual parity with the live archive page

Classic theme already used the brand palette; the gaps were structural. - Declare a font. The email had no font-family at all, so Outlook rendered Times New Roman while the live page is Geist. Geist via <link> where honoured, system sans fallback, MSO conditional pins Outlook to Arial. Applied inline on wrapper cells and every <a>/button. - Render the subject as a heading under the logo, mirroring the live h1. - Rebuild the footer as a band matching SiteFooter: newsletter.org logo, tagline, opt-out line, © legal. Footer text contrast raised from 2.6:1 to 5.2:1 on classic/cards. - Admin /admin/issues/{slug} preview now shows the HTML as sent instead of whitewashing the canvas; removed adminPreviewHtml (sole caller). {{unsubscribe_url}} stays the literal placeholder in the footer href. No changes to lib/ses.ts, cron/send, or the table layout.

10/12/20266058ea0