One image per prospect, rendered from HTML, attached to the outreach email and shown on screen during the Loom. It exists for one reason: to prove AL looked at their business before asking for anything. Canva was retired on 09/08/2026, the render takes 3.2 seconds.
Everything lives in DD/byForja/Templates-Lancement/loom-mockups/ on AL's disk. Fonts are base64 baked into the master, so the render never touches the network and comes out byte identical on any machine.
master.template.html the layout. Edit here, every prospect inherits. build-master.js bakes the woff2 fonts in. Run after editing the template. render.js splices a config into the master and screenshots it. configs/<slug>.js one file per prospect. Everything specific lives here. configs/archive/ superseded configs, kept. out/ the PNGs. node build-master.js master.template.html fonts loom-mockup-master.html node render.js configs/buckleather.js one prospect node render.js every config in the folder
| Field | Required | What it does |
|---|---|---|
company founder craft city | yes | Header and title. founder is never guessed: if no name appears on their own pages, open on the business name instead. |
scope | no | The pill on the right. Says which surface the proposal covers. Defaults to "social media". Set it whenever the offer is not purely social. |
observed.eyebrow | no | Label above the left panel. Defaults to "What the site does today". Set it when the left panel observes something other than the website, so the panel and the scope pill agree. |
observed.source | no | What was actually opened, printed in the "Observed on" line. Defaults to the site. Same reason: cite the surface being judged. |
observed.headline observed.points[] | yes | One factual sentence, then 2 to 4 short observations. Never sneering: the problem is never their craft, it is the plumbing around it. |
evidence.items[] | yes | Max 3 tiles in the browser mock. {type:"broken"} draws an empty frame, {type:"note",text} draws a label. |
palette[] | yes | 5 entries, derived from their real site. ink is "light" or "dark" and drives the text colour on the tile. |
cells[] | yes | Exactly 9. Roughly 4 Reels, 4 Photos, 1 Carousel, across about 6 recurring categories. |
deliverables[] | no | The "what you get" rail. Max 4 lines, under about 21 characters each. Facts of delivery only, never results. Absent field means no rail and no layout shift. |
promise footNote | yes | The closing line and its small print. No invented numbers. |
The prospect sees the attachment name in their inbox, so it carries the brand. render.js derives it from company: casing preserved, accents folded.
Buckleather-content-plan-byForja.png My-Sweet-Sweet-World-content-plan-byForja.png Mlles-Gateaux-content-plan-byForja.png
A copy is still written as out/<slug>.png, because the Mockup column in the prospects DB and other scripts point at it. Superseded versions keep a suffix: buckleather-v1-website.png, buckleather-v2-content.png. Never overwrite a version AL has seen.
The .glow layer is position:absolute; inset:0 and paints byForja blue over everything below it in the stacking order. The grid cells escape it because they are positioned; the palette chips were not, so every chip rendered with a 24 percent blue film and showed colours that were not the prospect's, one row under a line promising them their own palette. Found 09/08/2026 on all 11 mockups. Any new element that carries a client colour needs position:relative.
Outfit is subsetted to a unicode range that includes U+2191 and U+2193 but not U+2192. A literal right arrow silently falls back to a system font. Arrows are drawn in CSS.
A render that exits 0 proves nothing. Open the PNG and check: fonts loaded and not fallback, palette chips exact against the config, founder name spelled right, nothing clipped, no internal vocabulary. Two of the three defects above survived a successful render.
Step 04 of the acquisition staircase, A.2 on the architecture page. It comes after qualification and pricing, before the Loom script, and the script must be written on the same surface the mockup proposes. Doctrine lives in Grammar 02 on Notion; this page is the operating manual.