Social: rebuild the daily card with real type, real map, and provenance - #12
Merged
Conversation
The card the daily poster attaches to every weekday tweet had four defects, three of them silent. satori was given one font file (Inter-Regular, weight 400) while the layout asked for fontWeight 700 and 800 on the wordmark, title and stat values, and fontFamily "monospace" on the numbers. satori cannot synthesize weights or substitute a family it was never given, so all of it rendered as Inter 400. Nothing errored; the card just looked flat, and had since it shipped. The frame also used justify-content: space-between with two children on a 630px canvas, leaving roughly 300px of dead space through the middle, and it showed no chart, no as-of date and no source. For a product whose claim is "tracked with sourced numbers", a card that shows three numbers with no date and no provenance argues against itself. Changes: - server/og-card.ts owns layout, fonts and the map. routes.ts only gathers data. asOf and source are required fields on OgCard, so a card physically cannot ship without saying when it was measured and where it came from. A missing date prints "AS OF —" rather than quietly substituting today. - Registers Inter-Bold and JetBrainsMono-Bold (both OFL, same licence as the Inter already bundled). Stat values now render in the brand mono. - Each weekday template gets a visual built from the same data as its tweet: Monday the 235-cluster US map, Tuesday the GPU price ladder, Wednesday the spotlight cluster located on the map, Thursday the queue breakdown, Friday the energy mix. - server/us-map.ts is generated by scripts/generate-map-path.mjs and carries the outline plus closed-form Albers constants, so the server projects with plain arithmetic. Importing d3-geo would have meant require()-ing an ESM-only module from the CJS bundle, which throws on older Node, inside a try/catch that would have degraded it to silently image-less tweets. d3-geo is now a devDependency used by the generator and a parity test that pins the arithmetic to d3's own output. - Fixes Virginia in client/src/data/us-states.geo.json, whose outer ring was wound backwards. d3 reads that as the whole sphere minus Virginia, which put the continental bounds at [[-180,-90],[180,90]]. geoAlbersUsa's clipping hid it, so the homepage map has been fitting to a global extent and rendering ~18% undersized and off-centre (scale 329.7 vs 402.0). - scripts/preview-cards.ts renders every template to .card-preview/ for eyeballing. It posts nothing. Tests cover the two silent failures directly: a missing font face now fails the suite, and a truncated outline path fails assertMapPathIntact. satori silently truncates large inline SVG, which is why the outline must stay a single concatenated path. 300 tests pass, tsc clean on server, server bundle verified to contain no d3-geo reference.
This was referenced Aug 4, 2026
Owner
Author
|
Verified against current
Checked the deployment risk on the font loading specifically:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The image attached to every weekday tweet was ugly for four reasons, three of which failed silently.
Before / after are attached in the conversation; the short version:
The silent failures
satoriwas given one font file (Inter-Regular.ttf, weight 400) while the layout asked forfontWeight: 700/800andfontFamily: "monospace". satori cannot synthesize weights or substitute an unregistered family, so every "bold" heading and every stat number rendered as Inter 400. No error, ever.satorisilently truncates large inline SVG. Splitting the US outline into per-state<path>elements rendered a country missing 44 of 49 states, with no error. The outline must stay one concatenated path;assertMapPathIntact()guards it.us-states.geo.jsonis wound backwards. d3 reads that as the whole sphere minus Virginia, putting continental bounds at[[-180,-90],[180,90]].geoAlbersUsa's clipping hid it, so the homepage map has been fitting to a global extent and rendering ~18% undersized and off-centre (scale 329.7 vs 402.0). Fixed as a one-line diff.Provenance is now structural
asOfandsourceare required fields onOgCard. A card cannot ship without saying when it was measured and where it came from. A missing date printsAS OF —rather than quietly substituting today. The Monday card reports235/235 entries sourcedcomputed from the data, not asserted.This also surfaces staleness honestly: the Thursday card currently prints
AS OF 20 MAY 2026becauseinterconnection-queue.jsonreally is that old.No new runtime dependency
Projecting cluster coordinates would have meant importing
d3-geo, which is ESM-only. The server ships as a CJS bundle with all deps external, sorequire("d3-geo")throwsERR_REQUIRE_ESMon Node < 22 — inside thetry/catcharound media upload, which would have degraded to silently image-less tweets forever.Instead
scripts/generate-map-path.mjsbakes closed-form Albers constants intoserver/us-map.tsand the server projects with plain arithmetic.d3-geois a devDependency used only by the generator and a parity test that pins the arithmetic to d3's own output (worst drift 3e-13 px over 1,400 sample points). Verified: the built server bundle contains zero references tod3-geo.Verification
npm test— 300 pass, 0 failnpx tsc --noEmit— clean onserver/npx tsx scripts/preview-cards.tsThe client build currently fails locally on
framer-motionand@visx/*. Both are declared inpackage.jsonandpackage-lock.jsonbut missing from the localnode_modules; that is a stale local install, not a regression from this branch.Note on scope
This branch is cut from
origin/main, which already replaced the hand-drawnPowerMapDiagramwithRealUSMap. The local checkout at~/gridtiltis behind and still has the fabricated blob.