50by50
Day 3 / 132 ·

Day 3 in retrospect: four workstreams, two counted launches, one very full day

The day the factory engines came online, a side-quest went live, a real product attached its domain, and the news aggregator stopped looking like a dev tool. Four streams. Forty-one commits across three repos.

A note on this post before we start: Day 3 was a four-stream day, not a one-stream day, and the first version of this recap I published mid-afternoon got that wrong. It only told the LaunchCost + Parent Care story because that was the only stream I had clean git timestamps for at the time. The version below is the rewrite — with the LocalShoot Houston-launch closing arc, the Handscript domain-attach + persistence ship, and the TrustCore Media editorial refresh + §5 gate close-out all in their proper places.

Day 1 was me writing all morning, the agent writing all afternoon, one site live by midnight. Day 2 was a parallel-pair scaffold day with five working hours and an aesthetic rebuild. Day 3 is the third pattern, and the one I’m going to keep arguing for: a day where four products move in parallel because the factory rules are clear enough to keep each one moving without the others jamming. The honest version of what that looked like is below.


The big picture

By end of Day 3:

  • 2 counted launches on the 50by50 scoreboard: LocalShoot (localshoot.app) and Handscript (handscript.app).
  • 1 live but not yet counted: TrustCore Media (trustcore-media.vercel.app). Sitting at 8/10 on the §5 launch gate; the remaining two items (GA4 measurement ID + Search Console verification) are paste-in-Vercel work for Thursday.
  • 2 in build for Friday: LaunchCost and Parent Care, both with working engines, tests passing, supporting articles written, and a clean smoke-test-and-ship runway.
  • Forty-one commits across three repos (Birthday-Challenge, trustcore-media, Handscript). Plus a separate LocalShoot repo, where the bulk of work happened.

Day 3 of 132. 129 days remaining. 2/25 minimum, 2/50 stretch. If Friday lands the three building sites we’re at 5/25 by end of Day 5 — ahead of the Path C cadence.


Stream 1 — The 50by50 factory engines

This was the planned stream. I wrote a long handoff brief at noon and the coding agent executed against it. Seven commits in eighteen minutes. Then the polish + doc passes that compounded through the rest of the day.

12:25 PM — Status flip, handoff goes in

f790024 — Day 2 status flipped to done, Day 3 queued. Last user-typed commit of the day on this stream. The handoff brief itself ran longer than I expected: standing rules, all eleven TrustCore coding-standards records inlined from Pinecone, Tier 1 / Tier 2 / Tier 3 priorities with explicit “Friday-launch-blocking” tagging on the two engines, decisions-already-made I didn’t want the agent to relitigate, repo-specific quirks (Vite version pin, prettier ignore, eslint import-order strictness, the subpath-export pattern), and the two questions I owed me-the-user later (GA4 IDs, Search Console verification path).

12:27 PM — 00fcb3f LaunchCost calc engine math + 25 tests

Pure TypeScript module, no I/O. Five inputs (team size, stack, paid distribution, office mode, legal setup) return {low, mid, high} totals + a per-line breakdown with rationale notes. Defaults sourced from BLS wage data, public SaaS list prices, Apple’s $99 developer fee, three public Delaware LLC filings.

The thing I want to flag about this commit is the discipline that made the next four cheap: no I/O, no DOM, no fetch in the calc module. That’s how the same module ended up powering the homepage UI and the CLI with zero drift between them.

12:32 PM — d99100c Wire calc into the homepage

LaunchCost stops being scaffolding here. SSR baseline computed at build time. Client script that reads every form select, runs calculate() on change, patches the result card + breakdown in place. No framework, no state library — three event listeners and a render function.

Manual hand-check: team→3, paid→heavy, office→leased. Mid jumps $42,180 → $139,780. The math hand-confirms: $93,600 founder time + $2,640 hosting + $18,000 leased office + $24,000 heavy paid + $1,540 legal/accounting/domain. Eyes-on-actual-dollars verification I trust more than a test.

12:33 PM — 49e9ef9 LaunchCost CLI (cs-08)

The coding standards say every feature gets a CLI. Five minutes after the homepage was working, the CLI shipped. npx tsx scripts/calc-cli.ts --json emits machine-readable JSON. --team 99 exits 2 with [calc-cli] --team must be 1, 2, or 3 (got "99"). Fix: --team 2. on stderr.

This matters more than its size. The calculator is now scriptable for agents — anything from Paperclip to a future autoresearch loop can ask “what does a 3-person mobile team’s year-one look like” without parsing HTML.

12:37 PM — 0589961 Parent Care checklist engine + 30 tests

The bigger engine. Twelve questions across four domains (daily living, medical, finance, support), each answer weighted 0–3 concern. Five conditional follow-ups that surface inline when a base answer flags a specific risk — for instance, “needs daily help bathing” triggers “have they fallen in the last six months.” Follow-ups don’t contribute to the readiness score; they sharpen the agency-call packet only.

Four-band readiness scoring at 25 / 50 / 75 percent boundaries: stable → watch → plan → urgent. The agency-call packet only generates from concerns at level ≥ 2, so a stable family gets a clean result, not a generic checklist dump.

12:41 PM — 1e4b780 Parent Care UI + client-side PDF

End-to-end. Twelve numbered radio sections, four per domain. Result panel updates live — band, per-domain percent bars, flagged-concern summary in plain English, agency packet appearing only when earned by the answers.

PDF export via window.print() + a print-only stylesheet. No library dependency, no data leaves the device. The print stylesheet inlines its own Source Sans / serif typography to match the design system.

Privacy posture made explicit in the result panel copy: “Answers stay on your device. This entire page runs on your device.” No analytics fire on answer values.

12:45 PM — 3e102cf All four supporting article stubs filled

Roughly 3,500 words across the four nanocluster supporting pieces. Hosting Costs names the egress trap explicitly (“100GB/month on AWS S3 is $9 in egress, which seems trivial until you multiply by 12 and remember it’s per region”). Stack Tiers compares Managed / Serverless / DIY with cost shapes in dollars. Agency Questions ships twelve specific things to ask with the answer shape to expect. Independent vs Agency walks five structural differences with California 2026 loaded-cost math.

The Parent Care articles carry a “nothing on this page is medical, legal, or tax advice” disclaimer. The four placeholder reviewer names in the Methodology block are now flagged in the article body as pending consent — so any visitor reading the page sees the qualifier instead of relying on a hidden STUB comment.

Then the polish + doc passes (12:47 PM onward)

  • 12:47 PM — First version of this recap published (80dbe4b). It only covered the 12:25–12:45 window because that’s all I had clean evidence for. You’re reading the rewrite.
  • 12:59 PM54677f4 LaunchCost layout fix. Removed the hero scene image that was bisecting the calculator inputs from the result card. Three-second design call: image gone, ~150KB JPEG out of critical render, tool→result reads as one continuous block.
  • 1:03 PM8ffb3b9 Hub /roadmap link fix. The card title was only wrapped in an anchor when s.domain was set; Handscript had staging_url but no domain, so its card was unlinked. Added a fallback that uses staging_url and surfaces a quiet “(staging ↗)” cue. (Soon to be moot — Handscript’s actual domain attached this evening.)
  • 1:47 PMe594251 Daily-card update: nine Day 3 tasks marked done with one-line notes each, three deferred, status flipped to in_progress.
  • 4:54 PMb1c80ee First doc pass: roadmap.yaml, portfolio tracker, CHANGELOG, both LAUNCH_LOGs.

Stream 2 — LocalShoot (Houston launch arc closes)

This stream actually started Monday night and finished today. Pulling the commit history into one place:

Monday 5/12 night — Session 1 (9:43 PM → 11:43 PM, ~2h)

Spec arrived around 9:30 PM Eastern. First scaffold commit at 9:43 PM.

TimeCommitWhat
9:43 PM9464188Initial Next 16 + Tailwind scaffold
9:54 PM6 commits in 75 secondsToolchain (ESLint, Prettier, Husky, strict TS), Supabase schema migration, lib + Button primitive, homepage + Houston page, README
10:21 PM7962b28 2086f2dWired Supabase clients, Houston map renders live pins from DB
10:43 PM3323398Domain bought mid-session — full rebrand “Shot Spot” → “LocalShoot”
10:58 PMc0f1a2dFirst 10 Houston seed locations + apply-sql CLI
11:32 PM25f6f76Brand Kit applied (warm paper, Flare orange, Mint, Bricolage, custom map pins)
11:38 PM45580a7Location detail pages
11:43 PM3d35aeeSubmit form + admin moderation queue

End of Monday: site live with 10 seeded spots, brand kit applied, submission flow working. Eleven commits in two hours.

Tuesday 5/13 — Session 2 (11:56 AM → 4:23 PM, ~4.5h with debugging)

TimeCommitWhat
11:56 AM5fb75057 “Coming soon” stubs + newsletter form skeleton
12:41 PM546fca2Real Wikimedia Commons photos for 7 of 10 spots
1:01 PM5e3f1b2Minimal “Photo: ” captions
1:15 PMb33c5c4Pivot newsletter from API → Beehiiv loader script (Cloudflare blocks server POSTs)
1:47 PM7394bf8First deploy-hang fix attempt (force-dynamic)
~1.5hDead zone debugging Vercel “limited” status — every deploy stuck at UNKNOWN
3:19 PM789f30bReal fix: removed generateStaticParams + force-dynamic conflict; surfaced a [email protected] git config issue too
3:31 PM783537eFilter chips URL-driven + Unsplash fallbacks for last 3 photos
3:52 PM0325b44Seeded 20 more Houston locations → 30 total, all with photos
3:54 PMbbe3e70Caption cleanup (strip location info from author names)
4:11 PM98a379dCreator contributions: “Shot here” links per location + OG scraper + admin moderation
4:23 PMec71e72/tips live feed of all contributions across the city

End of afternoon: 30 spots with real photos, working filters, creator contributions, /tips magazine, all deployed.

Tuesday 5/13 — Session 3 (5:22 PM → 8:19 PM, ~3h)

TimeCommitWhat
5:22 PMa054120Business owner magic-link auth foundation (/business/login, /auth/callback, /business/dashboard)
~2hDesign pass on For Businesses + challenges feature + accountability + verification, plan locked
8:19 PMc516587Creator accounts: /login, /me, Save Spot button works, signed-in @handle chip in header

LocalShoot totals

  • Wall clock from spec → tonight: ~22h 36m
  • Active build time across 3 sessions: ~9.5 hours
  • Commits: 26
  • Lines shipped: ~4,500 (rough — SQL migrations, components, server actions, scripts)

From “text to an old friend about an idea” to “live product with 30 locations, creator accounts, and a moderation pipeline” in under 10 hours of actual work. Counted on the 50by50 scoreboard. Note in the roadmap card honestly flags it as a side-quest custom build — not factory template — because build-in-public means the scoreboard tells the truth about how each launch happened.

Stream 3 — Handscript flips live

12 commits across three sessions in the Handscript repo today. 3,880 insertions / 821 deletions across 35 files. Started the day with a partially-working pipeline that returned a TTF binary and no UI. Ended with a live, auth-gated, custom-domained product at handscript.app.

Pipeline + initial deploy (3:00 PM → 3:40 PM)

  • 3:03 PM3d3f289 Pipeline rewrite: per-corner Vision detection, char-class font assembly (909 ins / 589 del, 12 files). End of yesterday’s debugging: Vision was anchoring to page corners not registration marks, dewarp was off, fonts came out garbled. Today’s fix: per-corner Vision crops + Python centroid refinement + character-classified font assembly.
  • 3:10 PM3958775 HTTP server for live deployment. Wrapped the pipeline in an Express server (POST /generate accepts a multipart photo, returns TTF binary).
  • 3:11 PM6d6c3d3 /create page that uploads + downloads. Initial sync MVP — client component, photo upload, fetch-from-worker, blob download.
  • 3:33 PMc291c9e Site nav, /template page, 3-step flow. Shared <SiteNav /> + <SiteFooter /> mounted in root layout. Home redesigned around “Download template → Fill + photo → Upload + download”.
  • 3:37 PM1ace71c Recommend Sharpie instead of pen. Thin pens produced skinny illegible fonts; the discovery led to a three-place copy update (PDF instruction, /template page, /create tips).

Somewhere in here, handscript.app got wired via Cloudflare DNS API → Vercel.

Hardening + persistence (4:00 PM → 5:00 PM)

  • 4:27 PM554bea6 Rate limits, concurrency cap, daily abuse cap. Per-IP 5/hr + 20/day, MAX_CONCURRENT=3, daily total 500. /health exposes inFlight and dailyUsed. Smoke-tested: 3rd request in a row returns 429 with the right message.
  • 4:39 PMe01bf51 The big commit (812 ins / 284 del, 12 files). Worker now requires Supabase JWT, generates .ttf / .otf / .woff2 plus a preview PNG (the printed template re-rendered with the new font), uploads everything to Supabase Storage at <user_id>/<font_id>/, inserts a fonts row, returns {font_id}. Web /create becomes auth-gated; new /fonts/[id] shows preview + 3 download cards; new /fonts lists past fonts. SiteNav becomes auth-aware.
  • 4:43 PM4223176 Old scaffolded dashboard redirected to /fonts.
  • 4:47 PMd973058 Bump worker to Node 22 for native WebSocket. First Railway deploy of the persistence code crashed at startup: supabase-js’s realtime client requires WebSocket which Node 20 doesn’t ship.
  • 4:56 PM9e6cbb9 Email + password sign-up and sign-in. Google OAuth attempt failed (no provider configured); replaced with email/password using admin.createUser + email_confirm: true so sign-up is instant.

Polish (8:00 PM → 8:30 PM)

  • 8:06 PM8cc53c7 Capture name at signup + simple profile page. Name flows through handle_new_user trigger into profiles.display_name. SiteNav shows the name (clickable to /profile).
  • 8:29 PM4b0ba38 Per-char anchors + reject text-strip cells. Punctuation tuning. Each char gets a precise vertical anchor (top, midx, midhigh, near-baseline, below). New pre-filter rejects bitmaps that look like horizontal text strips bled into a cell — these render as missing-glyph boxes (▢) instead of smeared blobs.

Handscript verified end-to-end

End-to-end run twice today with two different writers’ template photos. Photo → font → install in ~6 seconds via the live worker. Production performance was 4–5x faster than dev (25–30s) — still investigating why, but consistently good.

Counted on the 50by50 scoreboard as launch #2. Card on /roadmap links straight to handscript.app.

Stream 4 — TrustCore Media: editorial refresh + §5 gate close-out

Three commits in the TC Media repo today.

3:18 PM — 7f7215a Editorial refresh

User-prompted: “real crappy looking, needs help.” Diagnosis: not broken, just no personality. Generic dark-mode dashboard aesthetic, no editorial voice, dual amber+indigo accents fighting each other, At-a-Glance card overloaded with three columns of stats + trending + latest, masthead a plain wordmark with no identity.

The refresh, keeping Next.js 16 + React 19 + Tailwind v4 architecture:

  • Warm paper-black palette (#0F0D0B / #171513 / #1C1916), warm cream text, single terracotta accent (#D97757). Dropped the dual-accent system — category is signaled only by small mono kicker labels (CRYPTO / AI) so the eye stays anchored on one accent.
  • Added Newsreader serif for headlines + lede + section heads + editor’s deck. Geist kept for UI body. Mono kickers for labels.
  • Masthead now reads as a real wordmark: serif “TrustCore” + italic terracotta “Media”, dateline + edition info in mono, italic-serif editor’s deck (“Calm signal from the crypto and AI firehoses — hand-picked from 13 sources, every morning. No commentary, just what moved.”).
  • At-a-Glance → Today’s Brief lead: two ledes (one crypto, one AI) with kicker labels, italic-serif headlines, snippet, source + time in mono. Trending row on a thin top rule below.
  • Top Stories → magazine StoryColumns with a feature lede (16:9 image + serif headline + snippet + kicker) and three secondary stories below.
  • “Full Feed” → “The full file — Every headline, in order”: calmer rows, category kicker, headline, source + time.
  • Sidebar restructured into stacked panels (kicker over hairline).
  • Subscribe form becomes an editorial inset on a left accent rule.
  • Footer becomes a colophon.

Build clean, typecheck clean, lint clean (one apostrophe escape later). Looks like a publication now, not a dev tool.

4:43 PM — 6901c19 Lint warnings + CryptoSlate 403

Two follow-ups from the refresh:

  • Raw <img> swapped to next/image with unoptimized + fill + sizes. Bandwidth profile unchanged, layout-shift prevention gained.
  • CryptoSlate had been returning 403 to every request from rss-parser. Confirmed via curl that Cloudflare blocks the polite-bot UA on this network regardless of UA strings. Added a native-fetch fallback path with a full browser UA + raw-XML entity sanitization. CryptoSlate now renders in the source list (200 → 210 items). The sanitizer also gets past LangChain Blog’s malformed & entities — though LangChain’s URL turns out not to be valid RSS, so it still fails on the “not RSS 1 or 2” check.

8:35 PM — 146bc1f §5 launch-gate close-out

Four of the five gate items I could close without user input shipped in one commit:

  • #4 SEO hygieneapp/robots.ts (Allow all, Disallow /api/, sitemap reference, env-driven host), app/sitemap.ts (homepage hourly priority 1 + /privacy yearly), layout.tsx gains metadataBase, alternates.canonical, OpenGraph + Twitter cards.
  • #6 Analytics frameworksrc/components/analytics.tsx. GA4 + Search Console verification component. Both inert until NEXT_PUBLIC_GA4_ID and NEXT_PUBLIC_GSC_VERIFICATION env vars are set in Vercel. Privacy defaults wired: anonymize_ip: true, allow_google_signals: false, allow_ad_personalization_signals: false.
  • #9 Compliance footer — Footer gains Privacy + Contact + 50by50 nav links, outbound-affiliate disclosure, publisher-attribution line. New /privacy page with full statement: what we collect (GA4 anonymized pageviews, subscriber email, standard Vercel logs), what we don’t (no Pixel, no fingerprinting, no session replay), source attribution, contact, affiliate disclosure. Last-updated stamp.
  • #10 Launch log — New LAUNCH_LOG.md at the TC Media repo root following the 50by50 template: persona, core asset, MVP pages, CTA, monetization, privacy posture, full §5 gate scorecard, step-by-step “to flip counts to true” instructions, kill-clock, Day-3 EOD state.

TC Media now sits at 8/10 on the gate. The two remaining items (analytics + Search Console) are paste-the-IDs-in-Vercel work for Thursday. Once those land, single one-line edit to roadmap.yaml (counts_toward_total: true) flips TC Media to count #3.

Doc passes and decisions logged

Two large doc passes today, both at EOD windows. One after the LaunchCost + Parent Care burst (4:54 PM) and one after the LocalShoot / Handscript / TC Media flips (8:04 PM, MasterPlan; 8:11–8:36 PM, three roadmap entries).

The CHANGELOG gained five Day 3 strategy-level decisions:

  1. Agent-execution day pattern — handoff rules that make it work. Standards inline (paste, don’t cite). Tier 1 / 2 / 3 explicit. Decisions-already-made section. Honest “what slips if it slips” budget. Verbal handoffs don’t work.
  2. No email gate on calculator results. Free results, soft capture via BeforeYouLeaveCTA below result. The “five questions, honest range, no signup required” promise is a structural commitment.
  3. Reviewer-consent policy. Every named reviewer with a credential needs real, written consent on file before any deploy. Placeholder names get credential-only entries or stay hidden until consent. No invented person on a production page.
  4. Metric-gated domain-purchase rule. Stay on *.50by50.dev subdomain through Week 1. Buy + 301-redirect in Week 2 only if metrics earn it: ≥500 unique visitors AND ≥20 primary-action completions AND ≥5 email signups for the week.
  5. window.print() + print stylesheet as the standard pattern for client-side PDF. No PDF library dependency, no data leaves the device, modern browsers all expose “Save as PDF” in the native dialog.

MasterPlan §15 gained a “Day 3” subsection capturing these five in their canonical form. §16 gained a Day 3 entry pointing at the full CHANGELOG.

What slipped to Thursday

  • GA4 measurement IDs + Search Console verification for both 50by50 spokes AND TC Media. Waiting on me-the-user to provide IDs.
  • TC Media counts_toward_total: true flip — depends on those analytics + SC IDs + a real contact email replacing the [email protected] placeholder in the footer + privacy page.
  • Parent Care reviewer-consent calls. Names remain placeholder pending real consent on file.
  • media.50by50.dev DNS attach for TC Media.
  • LangChain Blog feed URL fix in TC Media. Their configured URL turns out not to be a valid RSS feed; needs a real feed URL or removal from the source list.
  • Handscript punctuation polish — one text-strip cell is still slipping through the filter; either tighten the filter or build a “no-fly zone” mask over the template’s static content regions.

The thing I want to say about today

The first version of this recap missed three of the four streams because I wrote it at 12:47 PM and only knew what the agent-execution stream had shipped. The actual day kept going: editorial refresh in the afternoon, LocalShoot creator-accounts arc in the evening, Handscript flipping live, TC Media closing eight of ten gate items.

What made it possible to have four products moving in one day was that the factory rules don’t require my attention to function. The coding standards exist as 11 records I can paste into a handoff. The §5 launch gate exists as 10 numbered items I can score against. The nanocluster pattern exists as a doc I can point at. The decisions log exists as something I can append to. When the rules are durable, each new product can borrow them without me being the routing layer.

That’s the version of “shipping fast” I want to be testing in this sprint. Not “lots of code per hour” — anyone can do that, briefly, and pay for it in incoherence two weeks later. The thing I’m testing is “ship the right code per hour because the rules are clear” — and Day 3 was the first day where the test ran on four products at once and didn’t fall over.

Day 3 of 132. 129 days remaining. Two counted launches on the board. Three more building.

Tomorrow: GA4 + Search Console wiring across the three pending sites, the reviewer-consent calls, a Handscript polish window, and the Friday-launch dry run for LaunchCost + Parent Care. Detailed checklist lives in day-004.md.


Subscribe

Follow the build

One email a week. Real numbers, real lessons. No hype.

Unsubscribe in one click. No selling, no sharing.