# 04 · Thumbnails and checks *From Adam Schoenfeld (adamgtm.com). Part of a kit for beehiiv builders at https://adamgtm.com/design-process/. True as of October 23, 2026.* Two things made the redesign hold up: one thumbnail design for every issue, made by a builder that refuses bad output, and measuring every page instead of eyeballing it. ## The lead card One 1200x630 image does two jobs. It opens the deep dive in the email, and it's the post's thumbnail on the web and in social shares. Every issue gets one, so the home page, the archive and a shared link all read as one publication. Three boxes and the logo: - **Center card:** the headline with one highlighted phrase, and the strongest stat in the piece: a big number, a small denominator, a one-line label, and a mono line with the window or source. The strongest stat is the one a reader would repeat. - **Left card, tilted:** a real visual from the story. A screenshot or photo beats a chart. Crop it; never retouch it. A short title and a mono "who · when" caption. - **Right card, ink, tilted:** my sharpest line from the piece, word for word, about the thesis rather than one company. Signed "Adam · Oct 22". - **On top:** my icon and "Adam's GTM Report", centered. A partner's logo joins it only on a piece I co-produced with that partner. Sponsors never go here. - **Light only.** No dark versions. ## One builder, a short spec, checks that fail the build The look lives in one script. Each issue is a short JSON spec, so a new card starts at the approved bar and only the content changes. Mine, for the Oct 22 issue: ```json { "date_label": "Oct 22", "headline": {"text": "AI SDR’s Second Wave", "highlight": "Second Wave", "lines": ["AI SDR’s", "Second Wave"]}, "partner": null, "stat": {"number": "79", "small": "of 197", "label": "AI and cloud leaders are still hiring human SDRs", "subline": "Live SDR postings, Oct 21, 2026", "layout": "stack"}, "left": {"type": "image", "title": "“Today we’re taking it back.”", "image": "images/left.png", "crop": [136, 370, 890, 897], "caption": "Artisan CEO · Aug 2026"}, "right": {"quote": "So the first wave didn’t deliver.\nThis time it’s INBOUND-focused.", "signoff": "Adam · Oct 22"}, "variants": [{"suffix": "quote-B", "right": {"quote": "Cold outbound is an entirely different beast."}}] } ``` The builder renders HTML to a 2x PNG in a headless browser, plus a square crop and one PNG per variant. It exits with an error, and writes a report of what failed, when: - any text overflows its box; - the headline needs more than two lines at its smallest allowed size (it shrinks to a floor, then stops); - the quote won't fit at its floor size; - the stat number is wider than the center card's inner box (in the stacked layout, seven characters fit and eight don't); - a label runs past three lines, or a caption or sign-off runs past its card; - a tilted card, shadow included, reaches into the center square (below); - a card falls off the canvas, or the center content runs past the bottom edge. When a check fails, cut words. Don't fight the floors. Variants are how I choose between two quotes: everything else stays fixed. Rules for the content: - The number must appear in the post exactly as written: same rounding, same units. Never compute a new one. One exception: a plain count whose parts the post names (five vendors it lists, shown as "5"), with the parts in the subline. If a number can't be traced to its source, it stays off the card. - The headline is the published title. If it can't fit two lines at the floor, use a contiguous part of it that still says the idea, and flag the cut for the human. - The quote is copied character for character from the published post, curly quotes and all. One line break between two sentences is the only change allowed. - Every image and logo is a local file. The builder refuses URLs, so nothing is hotlinked. ## Where beehiiv crops thumbnails It depends on the card template. On the advanced builder, every post card's image has an `aspectRatio` and an `objectFit`. With `cover`, the image fills that ratio and the rest is cut off. - My old archive used square cards. A 1200x630 thumbnail showed only its centered 630px square, from x 285 to 915. - My redesigned home, archive and tag pages set the ratio to the card's own (1200 / 630 ≈ 1.905), so the whole card shows. I measured it on the live pages. Design for both. The center square has to work alone: the logo, the headline and the stat. The two tilted cards sit outside it, and the builder fails if either one reaches in. Then check the square at about 300px wide, and the whole card at 600px (email width): the headline, number, label and quote must still read. ## Setting the thumbnails - `edit_post` with `thumbnail_image_url` set to a public image URL. beehiiv downloads it to its own CDN. - On a published post this is live right away: the archive and the share image change without a publish. My home page feed caught up after its cache. - Before changing a published post, save its old thumbnail URL, so you can put it back. ## Backfilling the archive I rebuilt the card for every older issue, so the archive reads as one series. How: 1. **A shared brief** for the drafting agents: the card rules, two finished examples, and each post's published text and images. 2. **Agents drafted the cards,** a few posts each, from each post's own words, numbers and images. 3. **A scripted gate:** quotes verbatim, the stat present in the post exactly as written (or a flagged count of named parts), the title exact (or a flagged cut), the date right, the crop inside the image, and a clean rerun of the builder. 4. **An independent editor pass,** by an agent that didn't draft them. It looked at every card at 600px and every square at 300px, and caught what the gate can't: a left card that turns into a gray smear when small, neighbors in the archive that look alike, a quote that repeats the headline. It also caught numbers that didn't trace; those were withheld. 5. **One review page for me:** the whole archive wall, a panel per card, and a few calls at the top. Nothing went up until I approved it. ## Measuring pages Measure, don't eyeball. Most layout bugs are invisible in the code and obvious on a phone. - **Check the widths people use.** 390 (phone), 768 (tablet), 1440 (desktop). On beehiiv, add the band just above 768, where the desktop navbar takes over, and 360 for small phones. - **Fits the screen:** the page's `scrollWidth` equals the viewport width. If it's wider, find the elements that stick out past the right edge. - **Hidden things count.** A tooltip hidden with `opacity: 0` still takes up room, so the page runs wider than the phone and the browser quietly zooms out. - **No text under 11px** that the reader needs. - **Use a real viewport.** Headless Chrome's `--window-size` won't go below 500px wide and makes 390 look broken. Playwright's viewport setting gives a true 390. - **Long pages:** full-page screenshots repeat after 16,384 device pixels. Capture in segments. - **Click and type in every form.** A screenshot of a form proves nothing. My byline signup looked right and didn't work (`03-site-builder.md`, gotcha 12). - **Check the draft, then the live site.** Measure through the draft preview before publishing. After publishing, measure again in a new browser context without the preview cookie, on a fresh load, because cached pages lag. - **If two sites share a header, compare edges, not pictures.** Measure each element's left and right edge on both sites at the same widths. My House Style Kit has a script that does the width, overflow and small-text checks and saves screenshots at each width: https://github.com/adamgtm/house-style-kit/blob/main/scripts/check_page.py (raw: https://raw.githubusercontent.com/adamgtm/house-style-kit/main/scripts/check_page.py). It needs Playwright and a browser.