Illustrate Series Three: 50 portraits, 100 faces, per-card pages - #11
Merged
Conversation
Series Three shipped as a roster with no art. This renders the whole set and turns on its card pages. The pipeline is scripts/security-pros.mjs, a sibling of the Series Two one, with one deliberate difference: `all` runs portraits -> render -> publish and does NOT run `enhance`. On Series Two that image-to-image finish pass rewrote text on the card faces despite the prompt forbidding it — fabricated quotes attributed to living people, invented stat panels that were not on the card, and a misspelled name. No OCR step exists to catch it. This set's premise is documented, sourced history, so an invented quote is the worst defect it can carry. `enhance` now refuses to run without ENHANCE_I_WILL_CHECK_EVERY_FACE=1, and all 100 faces here are the text-accurate HTML render. Two template changes follow from the same finding: - The curator's note renders as a labelled panel, not wrapped in quote marks. On Series Two backs the quoted note reads as something the subject said; the field is editorial voice. - The front's portrait window is 72% rather than 58%. At 58% the caption left a dead third of black — visible on the first render, and exactly the kind of empty region the finish pass fills with invented text. Also fixed: `src/data/hacking.ts` and `security.ts` import "./roster.ts" with an explicit extension. My earlier refactor onto the shared module left an extensionless specifier, which Node's type stripping cannot resolve — that broke `node scripts/hacking-legends.mjs` for Series Two as well as the new pipeline. tsconfig gains allowImportingTsExtensions, legal because noEmit is set. The 50 source portraits are committed under assets/portraits/security-pros/, losslessly recompressed 82MB -> 30MB, so `pnpm security render` regenerates every face with no API calls. Adds /security-professionals/<slug> pages with 1200x630 OG composites, `pnpm security` scripts, and the sitemap entries the art unlocks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014htrUgbnoKQt9iT4G7hUpy
| <> | ||
| <script | ||
| type="application/ld+json" | ||
| dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} |
ThreatCrush Security Scan4 finding(s) MEDIUM: 4
Snippets are redacted; ThreatCrush never prints matched credential material. |
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.
Series Three shipped in #10 as a roster with no art. This renders the whole set and turns on its card pages.
Every face on
/security-professionalsis now a real card, and each of the 50 has a page at/security-professionals/<slug>with a 1200x630 OG composite.The pipeline, and why it skips
enhancescripts/security-pros.mjsis a sibling of the Series Two pipeline, with one deliberate difference:allrunsportraits -> render -> publishand does not runenhance.On Series Two that image-to-image "premium finish" pass rewrote text on the card faces despite the prompt forbidding it — it fabricated quotes attributed to living people, invented stat panels that were not on the card, and misspelled a name. Nothing in the pipeline catches that, because there is no OCR step. This set's whole premise is documented, sourced history, so an invented quote attributed to a real person is the worst defect it can carry.
enhancenow refuses to run unlessENHANCE_I_WILL_CHECK_EVERY_FACE=1is set. All 100 faces in this PR are the text-accurate HTML render.Template changes, from the same finding
notefield in quote marks, which on the printed back reads as something the subject said. It is editorial voice.Bug fixed along the way
src/data/hacking.tsandsecurity.tsnow import"./roster.ts"with an explicit extension. My refactor in #10 onto the shared roster module left an extensionless specifier, which Node's type stripping cannot resolve — that brokenode scripts/hacking-legends.mjsfor Series Two as well as the new pipeline.tsconfiggainsallowImportingTsExtensions, legal becausenoEmitis set. Both pipelines validate again.Also
assets/portraits/security-pros/, losslessly recompressed 82MB -> 30MB, sopnpm security renderregenerates every face with no API calls (the Series Two precedent, and the thing that makes a text-accurate re-render free).pnpm security/security:validate/security:renderscripts.Verified
npx tsc --noEmitclean;pnpm buildcleannode scripts/security-pros.mjs validateandhacking-legends.mjs validateboth pass🤖 Generated with Claude Code
https://claude.ai/code/session_014htrUgbnoKQt9iT4G7hUpy