One prompt is a bad contract
I got tired of asking a model for "a great thumbnail" and hoping.
- Sometimes the face is wrong
- Sometimes the brand is gone
- Sometimes it looks like every other AI cover on the internet
The output can be pretty. It is rarely mine, and it is rarely consistent.
So I stopped one-shotting the final image.
I compose it.
What I wanted (and what I did not)
I did not need the craziest thumbnails on the planet.
I wanted:
- Consistent look across posts
- Simple and clickable
- Crafted enough that it does not scream "fully generated"
If the cover is a little boring but on-brand, I win. Spectacle without control is just noise.
Bad one-shot covers vs materials you trust
One-shot generation asks the model to invent everything at once:
- Identity
- Layout
- Typography
- Topic cues
- Brand taste
That is too many jobs for one roll of the dice.
The other approach: only assemble from materials you already trust.
- A real face reference (restaged, not copy-pasted)
- Brand colors and type feel from the site
- Topic props that actually mean something (logo, terminal, diagram)
- Style examples as mood, not a template stamp
You are not hoping the model invents a good image.
You are giving it good pieces and asking it to put them together.
Break the big problem into steps
A "final good image" is the wrong unit of work.
I treat it like this:
-
Scope the composition
What is the article about? What should someone feel in half a second? What must show up (hook, face, one prop)? -
Gather assets separately
Face is one job. Logo is one job. Terminal / diagram / prop is one job. Each piece has a clear purpose. -
Prep the boring stuff
Clean backgrounds. Normalize sizes. Do not drag garbage into the final compose. -
Assemble last
Only now do you make the full image: brief + assets + style constraints → one composite. -
Enforce the non-negotiables
Exact canvas size for where it ships (for me: Open Graph1200x630). Letterbox pad that matches the generated scene background, not a random site token that looks "close enough".
That last mile is unsexy. It is also why the set looks consistent.
Style belongs in the process
If your style is only a vibe in your head, the agent will freestyle.
I put style into the workflow as constraints:
- Site cream / ink / terracotta accents
- Rounded display feel for hooks
- Restage the person every time (clothes, crop, pose), not a tiny mouth tweak on the same studio shot
- Vary the layout so posts do not share one silhouette
- Keep critical content inside a safe margin so social crops do not murder the hook
The style is applied while you build the image, not "fixed in Photoshop later" (I will not do that for every post).
A tiny shape of the brief
I do not start with pixel coordinates. I start with prose scope:
## Intent
- Feeling in half a second: urgent "do not install that"
- Differ from last cover: terminal prop + stop gesture, not suit/face-right
## Hook
- Axios got hijacked
- Emphasize: hijacked
## Face / avatar
- Emotion: warning
- Clothing: olive jacket (not the last hoodie)
- Pose: palm-out stop
- Placement: right
## Assets
1. Face (restaged)
2. Terminal with `npm install` + big X
That brief is the contract. Assets follow it. Assemble follows both.
Same pattern, other images
Blog thumbnails were the forcing function.
The workflow is not thumbnail-specific:
- Brief the intent and constraints
- Generate or collect trusted parts
- Compose once at the end
- Assert the delivery format
That copies to OG cards, product shots, social graphics, release art, whatever. Anywhere one-shot generation keeps lying to you.
It sits next to how I write
I already had agent skills and guides for writing posts in this repo.
The image workflow sits beside them:
- Same Git home as the site
- Same kind of skill: steps + examples + small tools
- Same idea of harness: Cursor, Claude, Codex, whatever can run skills and tool calls
People keep renting "content platforms" that do not know their brand.
I would rather keep taste, writing rules, and composition steps in the codebase that already owns the product.
Semi-automation, not magic. The repo becomes a unit: code + style + process.
Code that makes the boring part real
After assemble, I always export to the shipping canvas. Generators ignore exact pixels. The export does not:
node .cursor/skills/blog-thumbnail/scripts/normalize.mjs \
--input blog/my-post/thumbnail/raw/assemble.png \
--output blog/my-post/cover.jpg \
--cover
- Forces
1200x630(Open Graph) - Letterboxes with a pad sampled from the generated cream field
- Refuses to ship a random generator size as
cover.jpg
That is the whole joke: creativity in the steps, strictness at the boundary.
Takeaways
- One-shot images optimize for surprise. Composed images optimize for trust.
- Consistent output comes from composition steps + style constraints, not a longer prompt.
- Trusted materials beat invented everything.
- The same decompose → gather → compose loop ports beyond thumbnails.
- Put the workflow in the repo next to the writing skills. That is the semi-automation that actually survives next week.
And that is it for today. If your covers keep looking like everyone else's AI sludge, stop asking for the whole image. Ask for the pieces, then compose.



