
For the folks who prefer not to read and just want to feed Claude:
First of all, shame! But I get it. Black Friday is three weeks out, so this one is about volume: how we're turning a brand's proven winners into 100 Black Friday ads without testing a single new idea. You can grab the whole workflow (scripts, prompts, six layout starters and the rules we check every batch against) right here:
Hey all, and happy Friday,
Halloween on a Saturday is a gift, and we took full advantage. We went full Sesame Street this year (well, full is prob a bit of an exaggeration). James wore his net new Elmo costume; after a little kicking and screaming at the start, he ended up thrilled about it (or at least indifferent, but I am rationalizing that he was thrilled). It was very cute, and he carried his two little pumpkin baskets around like they were his job. I was Oscar the Grouch: an Oscar T-shirt, green pants, a green jacket I forgot I owned, surprisingly green sneakers, and a colander on my head. Maddie was Cookie Monster: Cookie Monster T-shirt, blue jacket, blue jeans. Low effort on the parents' front. High effort on the colander (tbh I was pretty proud of that one… I even added a string!).
We started at a block party where some kids were playing basketball, and James is obv obsessed with balls, so he spent most of it running around kicking theirs. Our friends came with their infant, who was dressed as a tiny biker from that Tim Robinson show, complete with little tattoo sleeves. I haven't seen the show, but the sleeves were incredible.
It wasn’t long before James discovered trick-or-treating—on his own, I might add—at the block party. Calling it trick-or-treating is also a stretch. He walked straight up to a woman handing out Hershey's Kisses and started putting them directly into his mouth, one after another, tin foil and all, while she fished them back out. It took us an embarrassingly long time to notice what was happening (free-range parents! Lol). From there, we did some actual trick-or-treating, which James adored, and then the famous 7th Avenue parade in Park Slope, ordered pizza, and by the time we got James was …completely wired. Then, within about 30 seconds, he crashed harder than I have ever seen a human crash. Little dude ate so much candy.
Sunday was the marathon, and also daylight savings. He was so tired from Halloween that the clock change didn't touch him on Sunday. Though I will say it touched him every other day this week 🙃. We went to our usual spot on 4th Avenue and Union, where a solid Grateful Dead cover band plays every year, and we danced and cheered on the runners. It was one of the first years I didn't really know anyone running, which is crazy. I've run it twice, and I honestly don't know if I'll run it again. We'll see.
Sunday evening we spent a long time at the Harmony Playground, where James invented a game: he pretends he's about to lick the playground bars, I say "no," and he collapses into a full laughing attack. Repeat forty times. Also, because the house is now full of Halloween candy, he walks around every night saying "pumpkin, pumpkin, pumpkin," because he knows the little pumpkin is where the candy lives. He gets one piece, and he negotiates for a second every single night like he's done this before.
And Linus, since a few of you keep emailing to ask: he's doing great. He was also the victim of a brazen daylight robbery in the park this week. Another dog took his ball, and the dog's owner looked me dead in the eye and claimed it as their own. I could have taken it further. I chose peace, mostly because it was 7 am and I had a toddler and a dog in tow. Linus has since been fully restocked, and he's had a bit of a chip on his shoulder ever since, which honestly suits him.
Anywhooo.
Yesterday I built the first version of this workflow. It made 64 Black Friday ads in about 25 seconds.
I was very proud of myself for roughly the same amount of time.
Then I actually looked at them. Every one was a winning ad with a sale banner slapped across it. My review, in full: "those ads look very very bad."
The version that works took the rest of the day and four rounds of a second Claude grading the first one's homework. The scores went from 61, 44 and 56 to 86, 80 and 88. Here's that version, and every mistake I made on the way to it.
Now is not the time to test new people
Every November teams brief a whole new batch for Black Friday. New audience, new angle, something "festive." It feels like the big moment deserves big new ideas.
It doesn't. Black Friday traffic costs more than any other week of the year, and a lot of the people seeing your ads were going to buy anyway. That's the worst possible week to find out whether a brand new person cares about your product. Test new ICPs in January, when it's cheap.
So the rule for this batch is simple: only the people who are already buying, only the ads that already sold them, rebuilt for Black Friday and stretched into more shapes.
The math

10 winners rebuilt for Black Friday, plus 3 format alts for each of 5 ICPs. 25 ads, 4 promo phases each. 100 ads, nothing untested.
Take your top 10 ads and rebuild each one for Black Friday. Then take the 5 people those winners sell to and give each one 3 new formats of the same message, for 25 ads in all.
Every one of them comes out in each of your promo phases. Ours were Black Friday, ends tonight, extended and Cyber Monday. 25 times 4 is 100.

Pull the winners, read them, rebuild the photo, set the type in code, add format alts, then have a second Claude grade it.
Step 1: Claude pulls your winners straight from Meta
The first script in the kit goes into your ad account through the Meta API, ranks every ad on ROAS (or cost per purchase) over the last 90 days, keeps the ones that spent enough to trust, and downloads the actual image and video files. It also grabs last Black Friday's best ads, since those already passed this exact test once.
You need a Meta token and your ad account number. (The README walks through the token. It takes five minutes and one mildly confusing settings page, which is about par for Meta.)
Step 2: read what it pulled (this is where it gets good)
I ran it on a toothbrush brand we work with. It pulled 12 winners. Of the 6 statics, 3 were Labor Day sale ads.
Two of them were set at the beach. (Nothing says Black Friday like a beach.) My first instinct was to drop them. That's backwards. Those ads won because the photo, the person and the layout work. The only thing wrong with them is the holiday. So Claude reads every winner (who it's for, what it says word for word, how it's laid out, what's dated) and every dated one gets rebuilt instead of thrown out.
Step 3: rebuild the photo, keep everything that won
This is the part my first version skipped: rebuilding the ad instead of stamping a banner on it.
Each winner goes into GPT Image on fal as a reference, together with photos of what the brand sells now. What comes back is the same moment with no words in it: the same hand holding the brush up at the car window, the same framing, now in late November, now holding this year's Black Friday exclusive instead of last season's brush. (I don't fully understand how it keeps the same hand. I've stopped asking.)
Then Claude sets every word in code, copying the winner's layout: the same serif and brush script, the same offer rows, the same hand-drawn marker notes. The offers come straight from the brand's own promo calendar, word for word.

Three Labor Day winners, rebuilt for Black Friday. Same layouts, same hooks, today's products.
Because the offer lives in code, each ad comes out in every phase with zero extra work. "Black Friday sale" becomes "Black Friday ends tonight" becomes "Cyber Monday," and the free gift changes with it.

One rebuilt winner in all four promo phases. Only the offer changes.
Step 4: 3 format alts for every ICP
This is what gets you from 10 to 25. (It sounds like a spreadsheet exercise. It's the step I'd keep if I could only keep one.)
For each person the winners sell to, Claude takes the winning ad's own words plus real reviews and rebuilds them in new shapes: a Notes post, a text thread, old way vs new. For the "I hate brushing my teeth" crowd, all three come from a single real customer review ("I absolutely hate brushing my teeth... my mouth feels so clean like I just left the dentist office!") and the brand's verified claims. Nothing gets invented, and that's the rule I'd tattoo on the batch if I could. If an alt needs a new claim to work, it's a new concept, and new concepts wait until January. Every word on these came from a customer or from a claim the brand already makes.

One ICP, one real review, three new formats. Same offer bar on all of them.
Why bother if the message is the same? Because people stop seeing a format long before they stop caring about the message. The person who scrolled past your review card for the ninth time might stop for a text thread that says "ok so i absolutely hate brushing my teeth."
Videos get an end card with the offer, one version per phase, which is the same idea with a lot less work.
Step 5: let a second Claude grade the first one
Here's the step my first version didn't have, and the reason the ads stopped looking very very bad.
After every render, a fresh Claude grades each rebuild against its original, out of 100, with exact fixes. Fresh means a new session with no context: it sees the original winner, the rebuild, the real product photo and a scoring rubric, and nothing about how hard I worked on it. (The rubric and the prompt are in the kit.) Then a brand new grader does it again. Round one came back 61, 44 and 56. Some of what the graders caught over the four rounds:
The image model gave the dragon brush the lion's ear. A little beige nub from the old product, carried over onto the new one. I would have shipped that.
The brush stood in front of a box of whitening strips, so the box read "hitening trips." The small print on a foam bottle came out garbled, which is an automatic fail.
One sticker said "52% off, ends tonight" without the "up to." That's an overclaim on a sale ad.
The hand-drawn marker notes came out looking like perfect vector shapes, which kills the whole point of hand-drawn.

The image model carried the old product's ear onto the new one. A grader that never saw the work caught it.
Four rounds later the same three ads scored 86, 80 and 88. The bar is 90, so they're still getting a last pass before they go to the client. (The most useful thing Claude did all week was tell Claude it was wrong.)

Four rounds of a fresh grader: 61, 44, 56 became 86, 80, 88.
Inside the kit
1_top_ads.py. Pulls your top ads from Meta and downloads the files, plus last Black Friday's winners. Nothing to install beyond Python.
2_plates.mjs. Rebuilds each winner's photo for Black Friday with today's products and no words in it. It also cuts out product photos.
Six starters. The layouts from this issue, cleaned of the brand: a serif and brush-script sale ad, a centered sale line with oval stickers, hand-drawn marker notes, plus the Notes post, the text thread and old way vs new.
3_render.mjs and 4_videos.mjs. Every ad in every phase, with contact sheets and a launch list. End cards for the videos.
The prompts, step by step, including the grader.
The BFCM rules. The 18 we check every batch against.

The six rules that matter most this month.
TLDR
Black Friday is the worst week to test new people. Spend on what's already selling.
Claude pulls your winners from Meta, including last Black Friday's.
Don't drop a winner because it's dated, and don't slap a banner on it. Rebuild it: same photo moment, same layout, today's product, the real offer.
Every ICP gets 3 format alts in the winner's own words. 25 ads in 4 phases is 100.
Have a second Claude grade the first one. Ours went from 61 to 86.
Have a great weekend,
Will
P.S. If your Black Friday offer still isn't final (several of our clients were still deciding in mid-October), do steps 1 through 4 now. The offer is the last thing that changes, and with this setup it's one file.