50by50
Day 2 / 132 ·

Day 2 in retrospect: eight commits between school drop-off and the recital

Planned to scaffold two sites. Shipped a design system instead — between a power outage at 2 PM and my daughter's band recital at 6:15. The honest hour-by-hour record.

It’s 5:45 PM and Day 2 has a hard stop coming in thirty minutes. My daughter has a band recital at 6:15 and we’re walking out the door at 6:00. Which means this post gets written compressed — the way most of today went — and the honest version of “what happened” is shorter than Day 1’s because the working hours were shorter too.

Day 1 was ten loose hours and a single live site. Day 2 was about five working hours — split by a power outage, bookended by a school drop-off and a band recital — and the public record at end-of-day is eight commits, two more sites scaffolded and deployed, a complete spoke-side aesthetic rebuild that wasn’t in the plan, and the Handscript MVP pipeline working end-to-end on a parallel thread.

Some of that was the plan. Most of the interesting parts weren’t.

This is the journal. Real timestamps from git. Real meals. No invented detail. The thing you would have seen if you’d watched me work.


~8:00 AM — Handoff

I started the morning with a Day 2 handoff prompt I’d written for myself the night before. Eleven specific tasks, the most concrete plan I’ve had at any single moment in this project. Scaffold Calculator #2. Scaffold Parent Care. Reuse components. Create two Cloudflare Pages projects, attach DNS, wire deploy workflows, fill launch logs. Start TrustCore Media polish. Add GA4 + Search Console. The eleventh item was a domain-purchase decision: buy launchcost.dev for $15 or stay on the subdomain through Week 1.

The plan’s quality wasn’t the question. The question was whether I’d actually do the things on it or end up doing some different thing entirely.

Spoiler: some of each.

The health check the prompt asked me to start with showed 5.5 hours of sleep, down from Day 1’s six and below the seven the coach video told me I needed to hit. Water target for the day: 16 oz, double yesterday. I’d taken my son to school during the conversation and gone for a 45-minute walk. Energy was a 7. The day started cogent, not great.


~8:30 AM — The architecture call I didn’t realize I was making

The first real decision was about how to share components across sites. Item 3 on the plan said “Reuse Base/Header/Footer/SubscribeBlock components (copy or shared package).” I’d left myself the choice on purpose.

I said shared, based on the gut intuition that one place to edit is better than fifty places. The coding agent pushed back honestly: a fully-shared cross-package Astro component pattern is technically more risk than it’s worth at site #2 — TypeScript-only shared utilities are 80% of the win with 20% of the risk. We’d share the sprint math, the Beehiiv form ID, and the author/repo branding as a @50by50/shared package. Each site would keep its own copy of the .astro markup but import the constants.

I told myself a thing I’d recognize later: the architectural decision wasn’t actually the interesting one. It was the visual decision I was implicitly making by reusing the Hub’s components — the dark/orange/JetBrains-Mono aesthetic — that would become the actual story of the day.

I didn’t catch that yet. I said “do it” and walked away.


~8:35 AM — Out the door

Took my son to school. Then walked. Forty-five minutes today, less than Day 1 — but enough.

Autonomous block, agent’s hands on the keyboard, while I was gone.


8:44 AM — Commit 5a66c37: npm workspaces

The repo became a monorepo at this commit. Root package.json with workspaces: ["packages/*", "sites/*"]. New packages/shared/ package with the three TypeScript modules I’d agreed to (sprint math, Beehiiv constants, branding), plus 13 unit tests for the sprint date logic. The Hub got refactored to consume the shared package — its existing lib/site.ts now re-exports the shared sprint functions so no page-level imports had to change.

The migration also surfaced its own bug: when vitest got added to the root workspace, it pulled vite@8 which collided with Astro’s vite@7, breaking astro check. The fix was a single overrides: { vite: "^7.3.3" } entry at root. Not the kind of thing you can predict; the kind you can only catch with the verify gate green-or-red.

The Hub auto-deployed on this commit. CI green in 1:11. Live site healthy.

8:49 AM — Commit f2c1bc5: the spokes go up (on the wrong aesthetic)

LaunchCost and Parent Care scaffolded from the Hub template. Both shipped in roughly fifteen minutes once the workspace pattern existed. Each site got its own package.json, astro.config.mjs, tsconfig.json, eslint.config.js, src/lib/site.ts (its own identity, consuming @50by50/shared), src/styles/global.css, src/components/{Header,Footer,SubscribeBlock}.astro, src/layouts/Base.astro, and a placeholder src/pages/index.astro.

They looked exactly like the Hub. Dark #0A0A0A background, electric orange #FF7A1A accent on the sprint badge, JetBrains Mono everywhere, hairline-bordered cards, all-caps mono pills.

I would not figure out for another seven hours that this was wrong.

8:51 AM — Commit 34c4cce: the roadmap caught up

Quick housekeeping commit. Updated roadmap.yaml to rename the two new spoke entries to match their actual directory slugs. Bumped their status from queued to scaffolding. Filled in done: true on the tasks in day-002.md that had landed. Rewrote the “Set up” section of playbooks/sop-new-site.md to describe the post-migration workspace clone pattern.

Three commits before 9 AM. Hub deploy CI green on each. Items 1, 2, 3, 6 done, item 7 partially done. I went and made breakfast.


~10:00 AM — Breakfast burrito

Skipped lunch later (it’ll become relevant when I score the diet later in the day). Burrito was good. Sat down to read instead of work.


~11:00 AM — Back home, eyeballing the new spokes

I came back, opened both new sites, and they looked… fine. Working. Live at temporary *.pages.dev URLs since the custom domains weren’t attached yet. The dark/orange aesthetic looked competent in the abstract. I didn’t have any concrete objection.

That should have been the warning sign. “No objection” is what AI-shaped work feels like before you’ve named what’s wrong with it.

I did not name it. I moved on.

11:14 AM — Commit 95cafe1: Episode 3 podcast

In parallel with the morning code work I’d done a thing on my walk that I want on the record: I gave NotebookLM a snapshot of yesterday and asked for a coach-style pep talk about Day 2. Took the m4a back, edited the audio slightly, dropped it into the Hub’s /media collection as Episode 3 with the transcript and a generated thumbnail.

This is a parallel track that’s going to keep happening: the podcast/video media exists partly to document the build, partly to remind me the build is the point. I’m not going to mention every episode in every recap. But Episode 3 was today and the post is honest if it includes it.


~11:30 AM – 12:00 PM — The Cloudflare infrastructure adventure

The two new sites needed Cloudflare Pages projects to exist before their deploy workflows could succeed. I’d never used Wrangler (Cloudflare’s CLI) before. The agent walked me through it; I supplied the API token. The first token I pasted got rejected — wrong service entirely, turns out the prefix on it matched a different vendor I’d been using. Second token worked.

wrangler pages project create 50by50-launchcost succeeded. Same for 50by50-parent-care. Two Cloudflare Pages projects existed. The Custom Domains API attached the subdomains automatically — both immediately stuck in pending pending status because they needed DNS records that didn’t exist yet.

DNS records for both: one CNAME each, launchcost50by50-launchcost.pages.dev, parentcare50by50-parent-care.pages.dev. Proxied. I added them in the Cloudflare dashboard.

Within about a minute, both custom domains went active. Both spokes were live at their real URLs. Items 4 and 5 done.

1:09 PM — Commit 1972e78: the nanocluster pattern is now the factory rule

I’d written a longer piece during lunch about something the Day 2 podcast had named explicitly: the nanocluster (1+2) microsilo content strategy. The hosts had called it “the secret weapon for generating traffic in this sprint without triggering Google’s massive spam filters.”

The shape: every new spoke ships as one commercial page + two tightly-bound supporting pages, never more at launch. The supporting pages route attention to the commercial page above the fold AND in the closing CTA. Expansion is earned by Search Console signal, not assumed.

I dropped a templates/nanocluster-structure.md pattern doc, a CHANGELOG.md entry explaining why the pattern was adopted on Day 2 specifically, and edits to MasterPlan.md §10 and the SOPs. Both spoke launch logs got a “Content plan (nanocluster 1+2)” section naming the commercial page + the two supporting pieces before any building happened.

This commit had a downstream consequence I didn’t fully account for: the spokes were now expected to be 3 pages each, not 1. Which meant the design system that didn’t yet exist had to handle two distinct page templates, not one.

The story of Day 2’s afternoon is what happened when I noticed that.


2:00 PM – 3:15 PM — Power outage

Lost power. Sat in a dark office for about a minute trying to decide if this was a long outage or a short one, gave up and went to find my wife. We napped together while the house ran on backup batteries. The work paused. The plan didn’t move.

Power came back at 3:15. I came back to my desk with two hours less daylight than I’d planned for, a band recital coming at 6:15, and the realization that the morning’s accomplishments were going to feel like the smaller half of the day if I didn’t push hard before dinner.

This is the part of the day that should have been a slow grind. Instead it became the part that mattered.


~3:15 PM — The “AI Obvious” pushback

I opened the two new spoke sites in fresh browser tabs and looked at them with the eyes I should have used at 11 AM.

Then I told the agent: this is wrong. The dark background and the electric orange and the mono headings — this is what every AI-generated launch site looks like in 2026. It signals “developer toy” to the audience these sites are for. A 52-year-old googling “questions to ask about my mom’s home care” is not going to read this site. She’s going to close the tab.

The agent agreed faster than I expected and pushed back in the right direction: the aesthetic problem was specifically a spoke problem. The Hub’s dark/orange aesthetic was fine — Hub readers are builder-types who recognize that visual language as competence. The spokes were for entirely different audiences. The fix wasn’t to rebuild the Hub. It was to give the spokes their own visual language, designed for normal people in decision moments.

I asked the agent to give me a research prompt I could run on multiple deep-research models in parallel. Not a quick answer — a real briefing for senior product designers about what trustworthy consumer utility sites actually look like in 2026.

The prompt landed at about 3:20. I queued it on Claude Design, Perplexity, and ChatGPT. The first two came back within ten minutes. ChatGPT was slow — I waited about fifteen and then told the agent to start with the two reports we had and we’d integrate the third when it arrived.

~3:25 PM — Three reports, synthesized live

The Claude Design memo was the strongest of the three. Typeset in the system it recommended. Specific to the hex code. Eight palette families generated mechanically from OKLCH targets. Fifteen named components with concrete specs. It picked Source Serif 4 + Public Sans + IBM Plex Mono for the type system, warm cream neutrals for the foundation, and light-mode-canonical for every spoke.

The Perplexity report was a research catalog rather than a prescriptive memo — twelve reference sites studied in detail (NerdWallet, TurboTax, Wealthsimple, Wise, GoodRx, Care.com, AARP, A Place for Mom, Angi, Wirecutter, This Old House, HomeAdvisor). Most of its conclusions agreed with Claude Design’s. Where they disagreed, the disagreements were real: Perplexity surfaced Wealthsimple as a contrarian-yellow palette case study, and pushed for “real-feeling human imagery on care sites” as a trust requirement.

The ChatGPT report arrived later and refined two things meaningfully: it argued for Source Sans 3 (not Public Sans) since Adobe ships it as a designed family with Source Serif 4 — tighter cohesion. And it argued for cool accents on finance spokes, warm earth accents on care + repair spokes, with specific palettes per category. The example LaunchCost palette swapped from Claude Design’s aubergine to an ink-blue. That felt right.

I told the agent: take the strongest signals from each. Source Serif 4 + Source Sans 3 + IBM Plex Mono restricted to micro labels only. Warm cream foundation. Eight pre-vetted palette families (Ledger / Treasury / Harbor / Willow / Hearth / Workshop / Field / Signal). Light-mode canonical. Three layout shells (tool-first split, guided single column, browse-and-compare). One designed pairing, no hedging.

I didn’t ship every report’s recommendation. I shipped the one that came out the other side of all three.

3:32 PM — Commit 49c9ca1: @50by50/design-system v1

packages/design-system/ came into existence at this commit. Fifteen named Astro components (SpokeHeader, Hero, ToolFrame, Question, ResultCard, BreakdownList, TrustStrip, DisclosureBlock, BeforeYouLeaveCTA, SpokeFooter, ArticleLayout, ArticleHero, InlineToolCTA, MethodologyBox, PrintSheet). Three palette CSS files shipped for the three Week-1 spokes. One theme.css with the warm-cream neutrals + type system + spacing scale + radii. Two docs — a 200-word voice doc, a palette family taxonomy.

The components passed lint and typecheck. The package was real.

3:35 PM — Commit 3d95fb9: commercial pages rebuilt

Both spoke commercial pages got rewritten to consume the design system. LaunchCost on the Ledger palette — ink-blue accent #225F78, split-shell hero (italic-serif promise on the left, calculator ToolFrame on the right). Parent Care on the Willow palette — sage accent #58704A, guided single-column shell, 18px body type to be readable for the 55+ audience.

I previewed both. They looked like serious utility sites. The dark/orange version from this morning felt like something I’d written months ago.

3:48 PM — Commit 97b7b20: four supporting article stubs

The nanocluster pattern from the 1 PM commit meant every spoke needed two supporting pages. Per the LAUNCH_LOG.md entries that already specified them:

  • LaunchCost: /hosting-costs and /stack-tiers
  • Parent Care: /agency-questions and /independent-vs-agency

All four landed in this commit. Stub prose only — H2 sections with one STUB: paragraph each, real for routing, internal links, methodology boxes with named reviewers and source citations. Wednesday or Thursday I’ll write the real prose. The stubs exist so Search Console picks up the cluster shape the moment we launch Friday.

3:57 PM — Commit 6ede6d2: six fal.ai scenes

I had argued with myself that the spokes didn’t need imagery — that the warm typography would carry the warmth, and that AI-generated photography risked pulling us back toward “templated.” The agent and I had agreed to skip the image library.

Then I told it I wanted images anyway.

Six scenes through fal.ai’s FLUX dev model. Editorial photography style, no people, no faces, no readable text, warm color grade. Total spend: about $0.15. An open ledger book for LaunchCost’s hero, a spreadsheet for /hosting-costs, rolled blueprints for /stack-tiers. A handwritten checklist with a coffee cup for Parent Care’s hero, an open notebook for /agency-questions, two manila folders for /independent-vs-agency.

Wired all six in as banner images. Pushed.

~4:00 PM — User pushback (me, on me)

I walked the live sites and pushed back twice on what I’d just shipped.

First: the pages weren’t connected. The header on both sites linked to routes that didn’t exist (/how, /about, /check). The InlineToolCTA components in the four supporting articles linked to /calc and /check — except the calculator was on / and the checklist preview was also on /. Every supporting article’s call-to-action was a broken link. The nanocluster pattern’s central rule — “supporting pages route attention to the commercial page” — was implementation-broken on every page.

Second: the Parent Care imagery was lame. A coffee cup and a checklist on a kitchen table conveys “this is a website about checklists.” It does not convey “this site is for an adult child stressed about their aging parent.” The audience needs to see a real human moment to feel like the site is for them. My “no AI faces” position was overcautious; the uncanny-valley risk was real but smaller than the relatability cost.

The agent argued back briefly on the second point and then conceded I knew the audience better than it did.

4:09 PM — Commit 8d0043b: the connected day

This commit did two things in one push:

Imagery reshoot. Three new fal.ai scenes generated, all with real intergenerational people in frame. Adult daughter + elderly mother at a kitchen table looking at the printed checklist together for the hero. Adult woman on a phone call at a kitchen counter taking notes for /agency-questions. Adult son + elderly father across a dining table with folders between them for /independent-vs-agency. Cost: about $0.075. Documentary editorial style, real-feeling skin tones, candid composition.

The new images were obviously better. The site now reads as “this was made by someone who’s thought about your situation.” That’s exactly what it needed to read as.

Cluster wiring. Every broken internal link fixed. SpokeHeader links now point to the actual supporting-article routes (LaunchCost: “Hosting costs” + “Stack tiers”; Parent Care: “Questions to ask” + “Caregiver vs agency”). All eight InlineToolCTAs now point at /. Both commercial pages got a “Read more from this series” section near the bottom with two cards linking each supporting article. All four supporting articles got a “Also in this series” block via the ArticleLayout related slot, linking the commercial page and the sibling supporting article.

Every page in each nanocluster now reaches every other page in at most one click. The pattern’s structural promise was finally implemented.

4:17 PM — Commit 02899c1: GA4, Search Console, EOD

Final commit of the workday. A new Analytics.astro component in the design system that takes a GA4 measurement ID and a Search Console verification token as optional props — renders nothing if either is empty. Wired into both spoke Base layouts. Privacy-first defaults: anonymize_ip: true, allow_google_signals: false, no remarketing.

Roadmap.yaml updated: the LaunchCost and Parent Care notes now describe the EOD design-pivot state. The Handscript MVP entry was promoted from queued to scaffolding with the staging URL surfaced. (More on Handscript in a moment.)

day-002.md task statuses ticked: seven of eleven done, four pending. The pending four broke down as three explicitly deferred to Day 3 (TrustCore Media polish, GA4/SC for TC Media, media.50by50.dev DNS) and one awaiting an explicit decision (launchcost.dev: stay on subdomain through Week 1, decided just before dinner — $15 is trivial, the operational cost of a mid-launch domain move isn’t).

Eight commits. 5a66c3702899c1. All green on CI. All live.


5:15 PM — Pork chops, rice, broccoli

I worked while I cooked. The dinner cook ran while the EOD recap conversation with the agent was happening. It was a short cook because we had to leave for the recital at 6:00 PM and I was scoring the day at the kitchen counter.

Diet: I’d give the day a 7. Solid breakfast burrito, no lunch (which is the gap), real dinner. Water was 8 oz — half the target. Energy held at 7. The night before’s 5.5 hours of sleep was the weakest signal in the day; tomorrow needs to fix that.

~6:00 PM — Out the door

Band recital starts at 6:15. Day 2’s workday is over. Day 3’s notes are already in the day-002.md file: calculator math engine, checklist engine, real prose into the four article stubs, TrustCore Media polish.


The parallel thread: Handscript

In parallel with everything above, I had a different surface open on a different browser tab: the Handscript MVP. The Week-3 build in the roadmap.

The brief: upload a template of someone’s handwriting, run it through Claude’s vision API to extract individual glyphs, pipeline those through fontforge to generate a real downloadable .ttf font file. Free MVP first, paid tier eventually. No memorial features, no agent API, no Stripe in v0. Scoped tight.

I got the whole pipeline working today. Upload → Claude vision → fontforge → download. Stub up at handscript-trustcore-systems-projects.vercel.app.

This changes the Week-3 risk profile materially. The original plan had Handscript as a from-scratch build that week — three nontrivial integrations (vision API, fontforge subprocess, font file packaging) all coming together cold. Now the pipeline is real. Week 3 becomes a polish-and-production-ize week instead of a build-from-zero week. That’s not a small change.

The Hub’s /roadmap now reflects this — Handscript shows as scaffolding with a staging URL.


The honest scorecard

Day 2’s eleven-task plan:

  • ✅ Seven done (the scaffolds, the CF projects, the DNS, the workflows, the launch logs)
  • ❌ Three explicitly deferred to Day 3 (TrustCore Media polish, GA4/SC for TC Media specifically, media.50by50.dev DNS)
  • ❌ One decided at EOD: stay on the launchcost.50by50.dev subdomain through Week 1. If Week 1 metrics earn it (≥500 unique visitors, ≥20 calculator completions, ≥5 email signups), buy launchcost.dev in Week 2 and 301-redirect. The $15 is trivial; the operational cost of a mid-launch domain move isn’t.

Plus a complete unplanned aesthetic rebuild that became the day’s real work, four supporting article stubs in the nanocluster shape, six → nine fal.ai scenes, a GA4/SC component ready for the IDs, and a Handscript pipeline running in parallel.

The plan was honest about its eleven tasks. The day was honest about overshooting some and underdelivering on others. The visible result on the Hub at end-of-day is: two live sites on launchcost.50by50.dev and parentcare.50by50.dev, each a three-page nanocluster, both on the new warm-paper design system. Zero counted launches in the strict sense — Calc and Parent Care don’t count until their cores ship Friday — but the scaffolding for Friday is now real, not theoretical.

The day’s biggest single lesson: time pressure made the design pivot good. No time to overthink palette debates. Three reports synthesized in under an hour because the recital was coming. The 4:00 PM pushback on broken links and missing faces happened because I knew I wouldn’t have another session today. The constraint was the discipline.

Day 1 had ten hours to think. Day 2 had five hours to ship. Day 2 shipped more.


It’s 5:55 PM. The recital is in twenty minutes. Day 2 is closing on a band recital and a design system I didn’t know I was going to build this morning.

Day 3 tomorrow. Calculator math engine. Checklist engine. Real prose into four article stubs. TrustCore Media polish. The launches on Friday have to ship working tools, not just designs.

But that’s tomorrow. Right now I’m finishing this post and walking out the door.


Subscribe

Follow the build

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

Unsubscribe in one click. No selling, no sharing.