IAN'S AI THOUGHTSTREAM THOUGHTSTREAM / #pipeline
Tag

#pipeline

3 posts

2026·07·20 16:28 / 5 MIN

Building a Hacker Sticker Pipeline

Last week I made a series of hacker stickers. Not to pass off machine art as my own, but to build a thing I've wanted for years with less friction. Crash Override holding up the floppy disk in Hackers while the Plague fetches it on a skateboard. Lex in Jurassic Park saying "this is Unix, I know this." I finally sat down and built a pipeline that turns film stills into die-cut stickers, and it settled on 26 designs I actually like. They're online here, at cost, 0% markup.

Redbubble product grid displaying "Hacker" sticker designs featuring illustrated character portraits and text phrases
Redbubble product grid displaying "Hacker" sticker designs featuring illustrated character portraits and text phrases

Two things matter to me up front.

I'm never trying to create art with AI and pass it off as human-made. The store is openly AI-assisted, and since none of it is my original work, charging a markup doesn't feel right. Cost only.

And the taste stays human. Our squishy brains still control the direction. The whole reason I had Claude generate multiple variations of each sticker was so I could pick, the way you'd work with a real designer instead of accepting the first comp.

Start with good source material

The naive move is to hand a model one picture and say "make a sticker." That's not what this was.

The first job was finding high-quality stills of each character, from IMDb, from the films themselves, from careful screenshots. A 247×369 crop of Zero Cool's face fought me for four rounds because there simply wasn't enough face in it to reconstruct. Small sources got upscaled with Lanczos before anything else touched them. Garbage in, garbage sticker.

The pipeline, in plain English

The image model does one expensive, non-deterministic thing: isolate the subject, complete anything the film frame cropped off, restyle it, and drop it on a flat magenta field. That render gets cached.

Everything after that is ImageMagick, deterministic and free. It keys the magenta to transparent with a corner flood-fill (not an RGB threshold, which eats interior detail), adds a white kiss-cut border, and composites a checkerboard preview. Because the split between the expensive stage and the cheap stage is cached at the boundary, twelve rounds of border and caption tweaking cost nothing. No API calls to nudge a keyline 4 pixels.

The model was gemini-3-pro-image-preview, about $0.13 an image. Total spend across roughly 125 renders came to around $16. Bun and TypeScript for the orchestration.

Have the agent build you a way to look

The most useful thing I asked Claude for wasn't the stickers. It was a review tool.

A little local web server on port 4330, one card per subject, verdict buttons, free-text notes. Below each image, a version stepper. I could walk v7 next to v11 and decide whether a "fix" had actually improved anything or just moved the damage somewhere else.

Interface showing eight character sticker designs from a hacker-themed comic with evaluation options to keep, discuss, or discard each illustration
Interface showing eight character sticker designs from a hacker-themed comic with evaluation options to keep, discuss, or discard each illustration

That stepper only works because of one rule I gave Claude and never relaxed: never delete or replace intermediate work. Every version is snapshotted, append-only, deduped by hash. It saved the project when an accidental full pipeline run overwrote 30 finished stickers. Nothing was lost, because nothing is ever overwritten without a copy landing in the archive first. Build that before you need it.

The style chose itself

I assumed these would be clean photographic cutouts of each character. Claude would isolate the subject, and that'd be that.

Then one variation came back as halftone comic-book pop art, bold black ink outlines and Ben-Day dots, and I loved it immediately. Every sticker is comic now.

It turned out to be the correct call for a technical reason I didn't see coming. Photorealistic renders have soft, wispy, semi-transparent hair edges, and a chroma key can't resolve those. They shattered into floating fragments. Bold black outlines produce a solid, connected, opaque silhouette, which is exactly what a chroma key wants and exactly what reads at two inches. The style that looked best also cut cleanest. I'd love to say I planned that.

Edit, don't reroll

The single biggest lesson. For the first five rounds, fixing one defect meant re-rendering from the source with a correction note. That fixed the shirt and broke the face. Fix the face, break the crop. Subjects oscillated instead of converging.

The fix was to hand the model its own current artwork, name exactly one change, and tell it to preserve everything else. Once a sticker was 90% right, editing kept the 90% and only touched the 10%. Switching to edit-by-default earlier would have roughly halved the whole thing.

A related trick for completing a head the film frame chopped flat: don't say "reconstruct the top of his head," which the model reads as license to redraw the entire hairstyle. Instead, pad the canvas with magenta and say "fill only that gap." Giving the model physical room turns an abstract request into a bounded inpainting task.

The mistakes were mostly mine

More than once the model produced "the wrong person" and I escalated the prompt in capital letters. The Plague came back wrong for four rounds. The actual problem: my manifest described him in wraparound sunglasses from a different scene. In this still his eyes are visible. The model was faithfully following a bad instruction the whole time.

Same story with Lisbeth's hair. I wrote "spiked," got spikes, and it's a floppy mohawk. When a model keeps giving you the wrong thing, re-read your own prompt against the source before you start yelling at it.

Adding capital letters is not iteration. Changing the information you give it is.

2026·07·15 19:05 / 2 MIN

Betterpost Is Live

Betterpost is live, and it's now an MCP server you add to Claude or GPT. Tell it the topic you want to follow, and it scours hundreds of articles, ranks them for relevance, and writes you a newsletter or blog post that reads like a person wrote it. It's free to start with 100 credits.

BetterPost website homepage displaying AI writing tool features, example newsletter about green energy, and chatbot integration options
BetterPost website homepage displaying AI writing tool features, example newsletter about green energy, and chatbot integration options

The thing I actually built

About a year ago I wanted to stay current on a few narrow topics: AI coding, type 1 diabetes science, and celiac science. The last two were for family members. The reading was more than I could keep up with, so I built a system to collect sources, find the articles worth reading inside them, and assemble email newsletters I'd actually want to open.

That system became Betterpost. It's been powering my own mailing lists for a year now, over 1,200 subscribers and open rates near 40%. The newsletters aren't slop. They're the ones I read first.

Why this works for LLMs

The job here is summarizing, not reasoning. That distinction matters. Models are good at pulling the three most important points out of an article and grabbing the quote that earns its place. They're much worse at drawing novel conclusions, and Betterpost never asks them to.

The pipeline fans out across hundreds of articles, runs them through summarizer prompts, and uses different models for different steps to keep cost and time in check. Each summary gets embedded, and those embeddings are scored against a fanned-out list of relevance criteria. So when you ask Betterpost for a newsletter on a subject, it's matching the freshest, most on-topic material before it writes a word.

By the way, Claude wrote all the prompts. I haven't written one by hand in a year.

A year of learning to write like a human

Betterpost has also spent a year figuring out how to write in a way that doesn't read as typical AI. This isn't about disguise. The output is openly machine-assisted. It's about being light, interesting, and human instead of the usual flat summarizer voice.

All of it is adjustable, and projects are unlimited. If you have a newsletter or a blog post you want to send, point Betterpost at it.

The UI is gone

When I built this for myself, it had an extensive interface: tables, technical readouts, all the knobs I wanted. That's all gone now.

Betterpost is entirely an MCP server. You add it to your favorite chatbot, name the project you want to make content for, and go. No dashboard, no menu. It genuinely feels like magic, which is a strange thing to say about a tool I understand the internals of completely.

2026·05·20 21:02 / 3 MIN

Consistent AI Images Across Pages

Generating AI images for a marketing site is easy. Keeping them visually consistent across months of blog posts and landing pages is the hard part. The trick that's working for us: check the style into the repo as a structured JSON document, then have Claude assemble per-image prompts on top of it.

Person working on laptops at desks with coffee cups, croissants, and plants in bright natural light settings
Person working on laptops at desks with coffee cups, croissants, and plants in bright natural light settings

The setup

A new work site needs a lot of imagery to break up dense technical copy. We wanted the images to be light-hearted and obviously AI-generated, goofy on purpose, but goofy in a coherent way. Different pages written weeks apart still need to feel like they came from the same magazine.

Capture the style once

The first move was to take a single reference image we liked and ask Claude (Opus) to describe it as a reusable prompt fragment for other image models. Not prose. A JSON object with fields for medium, lighting, camera, color palette with hex codes, composition, textures, and mood.

{
  "medium": "macro product photography",
  "art_style": "hyperrealistic still life with editorial magazine aesthetic, crisp detail and natural materials",
  "lighting": {
    "type": "soft window light with gentle bounce fill",
    "direction": "key light from upper right window, soft fill from white card on left, subtle backlight separation",
    "color_temperature": "consistent warm daylight (5200K) with slight golden hour tint",
    "intensity": "soft and even with gentle falloff into shadow"
  },
  "camera": {
    "lens": "50mm equivalent, slight wide-angle feel",
    "aperture": "f/2.8",
    "angle": "slight low-angle three-quarter front view",
    "depth_of_field": "shallow with soft background blur and atmospheric haze"
  },
  "color_palette": {
    "warm_cream": "#F2E8D5",
    "muted_sage": "#A8B89E",
    "terracotta": "#C97B5A",
    "soft_taupe": "#8A7968",
    "deep_olive": "#4A5240",
    "linen_white": "#EFEAE0",
    "espresso": "#2B221A"
  },
  "composition": "off-center subject following rule of thirds, negative space on left, layered foreground and background elements creating depth",
  "textures": "raw linen weave, hand-thrown ceramic with subtle glaze pooling, weathered oak grain, condensation droplets, fine paper fiber, matte natural finishes",
  "mood": "calm, considered, artisanal, slow-living editorial warmth with quiet sophistication"
}

That file gets checked into the repo. It is the source of truth for what the site looks like.

Wrap it in a script and a skill

A small image-generation script reads the JSON, takes a per-image subject description, and assembles the final prompt. The actual generation goes through Gemini's nano-banana-pro, which has been the most consistent and best-looking option for this style in our testing.

On top of that sits a Claude skill. The skill knows where the style file lives, knows how to call the script, and knows the conventions for where images land in the repo. From inside Claude Code I can say "add an AI image to this section" or "create a hero image for this blog post" and it reads the surrounding page context, writes a subject prompt that fits, merges it with the style JSON, and drops the image in place.

Why this holds up

The style and the subject are separated. Editing the palette or the lighting later means changing one file and regenerating, not re-prompting from scratch. The model gets a long, specific, machine-readable spec instead of vibes, which is what the consistency was missing every other time I'd tried this.