HooklineHeadline / Ad-Copy Generator
What it does for you
One brief in, dozens of channel-fitted headlines out, each scored with reasons and paired for A/B tests, with an optional Claude mode graded by the same scorer.

Screenshots

In more detail
Hookline turns one short brief into dozens of headlines and ad lines that already fit each channel's character limits. Every line gets a score, a reason for the score, and a suggested A/B partner. It works fully offline with a local engine, and there is an optional Claude mode that goes through the same scoring.
Honest limits
Claude mode was not run against the live API. No key was used in this build. It follows the documented request shape and is covered by parser tests and a bundled sample response, but that is not the same as a real call. The local engine and scorer are tested. The copy quality has not been judged against real campaigns.
How I built it
One of the parallel Claude Code builders from the September 19 one-shot night. I directed the scope: local first, real channel limits (Google Search headlines at 30 characters, Meta at 40, and so on across six channels), explain every score, pair lines for A/B tests, and treat Claude as an upgrade, not a dependency. Claude Code wrote the core (copy.js), 217 assertions, the UI, and the server across two short sessions. The first was interrupted, the second finished and re-verified. Logged time was about half an hour.
I kept one rule firm: if the fit engine has to cut a line mid-phrase, that line gets flagged and hidden by default instead of being passed off as finished copy.
What I learned
- Character limits are a writing problem, not a truncation problem. On the 30-character Google headline, 42 of 55 generated lines needed a mid-phrase cut. The fix was not a smarter cutter. It was a family of compact frameworks built on a short form of the benefit, so tight channels get lines written for the budget.
- Cutting at sentence punctuation breaks on decimals and abbreviations. "Rated 4.8" and "vs." both looked like sentence ends. Requiring a space after the period and rejecting lines that end on a dangling word fixed it, and both cases are tests now.
- Word-overlap distance is enough to make uniqueness and A/B pairing work. Pairing on wording distance plus score, with a bonus for different framework families, gives pairs that test an idea rather than a synonym.
- A readability formula is only as good as its syllable counter. Short punchy headlines scored as hard to read until silent "e" and "-ed" endings were handled.
- Grading Claude output with the same tested scorer as the local engine keeps the comparison honest.
What carried forward
Same backbone as the rest of the night: a DOM-free core that the page and verify.mjs share, the standard serve.mjs, and demo and theme flags for screenshots. Like #25 and #30, the test file had a literal em dash inside its own no-em-dash check, and it got replaced with a character code. The defensive JSON parser for model output (strip code fences, find the array inside prose, dedupe) is an idea #30 also used the same night: never trust the model to hand back clean JSON.
If I took it further
I would run Claude mode against the live API before calling it done, then feed the scorer's weakest measures back so the model revises its own lines. I would also let the fit engine swap a long word for a short one before it ever cuts.
#029 Built with Claude Code September 20, 2026 217 automated checks