A content agent is a prompt pipeline. The plan is the input, the platform template is the spec, the model writes the draft, and the template's checklist is the oracle. Chapter 6 ships the plan and seven templates; this page runs their rules on a QA post.
One planning sheet, seven platform templates and a README. No code.
7
Platform templates
YouTube, Reel, Instagram post, carousel, Medium, blog, LinkedIn.
11
Banned phrases
From the universal voice rules, checked in every template.
8
Final-gate checks
Run on the plan before any platform template is opened.
01A content agent is a prompt pipeline
Chapter 6 has no code. It is nine Markdown files: a planning sheet, seven platform templates and a README with the voice rules. Read them as a tester and they are a pipeline you already know: an input, a spec, a generator and an oracle.
Pipeline part
In this chapter
What a tester checks
Input
One filled 00_Hook_Story_Offer_Planning.md: idea, hook, story, offer
The plan's own Final gate: 8 checks before any template is opened
Spec
One platform template (01 to 07): format, voice rules, skeleton
Every rule with a number in it is testable: words, slides, characters, hashtags
Generator
Any LLM, given the plan and the template
Nothing yet. Model output is untrusted until checked
Oracle
The template's pre-publish checklist and the README's banned phrases
Run it on every draft, by hand or with a script like the demo below
flowchart LR
I["Idea"] --> P["00 plan"]
P --> G{"Final gate"}
G -->|fail| P
G -->|pass| T["Plan + template"]
T --> L["LLM writes"]
L --> D["Draft"]
D --> C{"Checklist"}
C -->|fail| L
C -->|pass| S["Publish"]
The chapter's routine as a pipeline. The Final gate checks the plan (8 checks); the template's checklist checks the draft. Those two decisions are where the tester sits.
The README gives the one instruction the model needs, after you paste the filled plan and a template: "Write the [platform] piece using this plan and these template rules. Follow the format exactly. No banned phrases." Its summary: the template is the spec; the plan is the content.
02Hook, Story, Offer
The planning sheet reduces every post to three moves, in its own words:
00_Hook_Story_Offer_Planning.md (lines 3-7)
Every piece of content is three moves: **stop them (Hook), take them somewhere (Story), ask for
something (Offer).** Get these three right on paper and the platform formats become copy work.
Get them wrong and no amount of editing saves the post.
Fill this out **once per idea.** Everything else in this chapter pulls from it.
Hook: six patterns, each with an example
00_Hook_Story_Offer_Planning.md (lines 28-37)
### Hook patterns that work
| Pattern | Shape | Example |
|---------|-------|---------|
| **Blunt declarative** | A flat, confident claim that dares disagreement | "Your 5,000 tests are not an asset. They're a liability." |
| **Unpopular opinion** | Name the consensus, then break it | "Unpopular opinion: more coverage is making your suite worse." |
| **The reader's own thought** | Say the thing they're already half-thinking | "AI assistants get dumber after a few hours. You've noticed too." |
| **Cold-open story** | Drop them mid-scene | "A candidate walked into my interview yesterday and…" |
| **The reversal** | Set an expectation, snap it | "I automated everything. Then I deleted half of it." |
| **The number** | A specific, surprising figure (must be real) | "We cut flaky reruns 80% by changing one line." |
The hook rules: write five versions and keep the sharpest; no statistic as the opener unless the statistic is the shock; never a table of contents such as "In this post I'll show you"; cut every word that delays the punch.
Story: Problem, Tension, Turn, Proof
00_Hook_Story_Offer_Planning.md (lines 65-70)
```
PROBLEM (their pain, their words): ___________________
TENSION (why the easy answer fails): _________________
TURN (your insight / method): _________________
PROOF (number, demo, story, code): _________________
```
One core idea per piece; side ideas become future posts. Specifics over adjectives: "Reduced runtime from 41s to 12s" beats "much faster". Add one screenshot-worthy line and one honest caveat that cuts against your own interest.
Offer: exactly one ask, lightest rung first
Rung
Offer
Example or mechanic
1
Engagement
A binary or specific question. Never "what do you think?"
2
Save / share
"Save this for your next sprint."
3
Lead magnet
Comment a keyword and an auto-DM sends a checklist, PDF or repo link
4
Destination
Read the full article, watch the video, open the repo
5
Product
The course or tool. Sparingly and mentor-framed, never salesy
00_Hook_Story_Offer_Planning.md (lines 104-107)
### Offer rules
- Match the platform: LinkedIn hides body links (put links in the first comment); Instagram
uses comment-keyword DMs; YouTube wants a one-word comment + subscribe.
- The CTA should feel like a favor to the reader, not a favor to you.
03Live demo: plan a QA post and lint it
The plan starts filled with a sample QA topic. Change the hook pattern to load the repo's example line for it, edit any field, and watch the Final gate. Then generate a draft for LinkedIn or Instagram and edit it: the pre-publish checks rerun on every keystroke. Try the offer rungs too: the LinkedIn template wants the post to end on a specific PS question, so rungs 2 to 5 fail that one check there, while the Instagram caption takes any single CTA.
Post planner: Hook, Story, Offer, then lint the draftNo API key needed
1. The plan (00_Hook_Story_Offer_Planning.md)Final gate: 0 / 8
No model runs here. The draft is assembled from the plan by the repurpose map, and every check is a text rule taken from the templates (word counts, arrows, hashtags, the 11 banned phrases). That is the point: these checks are cheap, deterministic and worth running on whatever an LLM writes. The proof line is the planning sheet's own example of a specific number; in a real post, use your own real numbers.
04Plan once, repurpose everywhere
The chapter README's rule: you do not write seven things, you write one Hook, Story and Offer and bend it into seven formats.
flowchart TD
P["00 Hook, Story, Offer: plan the idea once"] --> YT["01 YouTube"]
P --> RE["02 IG Reel"]
P --> PO["03 IG Post"]
P --> CA["04 Carousel"]
P --> ME["05 Medium"]
P --> BL["06 Blog"]
P --> LI["07 LinkedIn"]
The README's workflow: one plan feeds every platform template.
The repurpose map says where each part of the plan lands on each platform:
00_Hook_Story_Offer_Planning.md (lines 111-120)
## The repurpose map
Once Hook · Story · Offer is locked, here's where each piece lands:
| Plan element | YouTube | IG Reel | IG Post | Carousel | Medium | Blog | LinkedIn |
|---|---|---|---|---|---|---|---|
| **Hook** | 0–15s hook | Slide-1 text + first spoken line | First caption line | Slide 1 | Title + bold subtitle | H1 + intro | First 2 lines |
| **Story** | Body beats | 2–4 quick beats | Caption body | Slides 2…N-1 | ## sections | ## sections | → arrow lines |
| **Proof** | On-screen demo/code | Screen-record snippet | The image | A code/stat slide | Code blocks + sources | Code + data | One stat line |
| **Offer** | One-word comment + subscribe | Comment-keyword DM | Caption CTA | Final slide CTA | Italic CTA | Inline + end CTA | First-comment link |
The LinkedIn column of the map, drawn as a post. The demo's generator builds exactly this shape.
05Format rules you can check
Most template rules are numbers or patterns, which makes them testable. These are the ones a script can check; the rest (voice, honesty, whether the idea is worth posting) still need a person.
Template
Checks you can automate
07 LinkedIn
First 2 lines are the hook and not a statistic; → arrows, never bullets or numbered lists; under 280 words (sweet spot 220 to 260, a short cut of 140 to 200); a specific PS question, never "what do you think?"; 5 to 7 hashtags; no link in the body
03 Instagram post
Headline on the image 8 words or fewer; caption line 1 works alone; one CTA; 5 to 10 hashtags; the same comment keyword across a Reel, Carousel and Post set
02 Instagram Reel
15 to 45 s at 9:16 (1080×1920), 15 to 30 s target; on-screen hook of 3 to 6 words in frame 1; spoken hook inside 3 s; 2 to 4 beats; subtitles on
04 Carousel
7 to 9 slides at 4:5 (1080×1350); slide 1 headline 8 words or fewer; one idea per slide; at least one proof slide; final slide = thesis + comment-keyword CTA
01 YouTube
Hook in 0:00 to 0:15, about 50 words at most; intro done by 0:45; a one-word comment CTA in the outro; thumbnail text of 3 to 5 words
05 Medium
1,500 to 3,500 words; title of 8 to 15 words; a bold subtitle with 3 to 5 real numbers; ## The Honest Caveats and ## The Bottom Line present; 5 tags
06 Blog
Title tag 60 characters or fewer; meta description 155 or fewer; keyword in the title tag, H1, slug, first 100 words and at least one H2; 2 to 4 internal links and 1 or 2 outbound
Every template
None of the 11 banned phrases; no emojis (1 or 2 at most); no fabricated numbers
README.md (lines 57-59): the banned phrases
- **Banned phrases** (never use): *game-changer, leverage, dive deep, in today's fast-paced
world, it's no secret, unleash, revolutionize, cutting-edge, synergy, supercharge,
unlock the power.*
06The files, and how to run the routine
Everything is in chapter_06_AI_Social_Media_Content_Creation. The top-level README's requirements for this chapter: nothing but a Markdown editor and any LLM.
File
What it holds
Its built-in check
README.md
The workflow, the template index, the universal voice rules and how to use the templates with an AI assistant
The 3-question sanity check
00_Hook_Story_Offer_Planning.md
One-line idea, 6 hook patterns, the story spine, the offer ladder, the repurpose map
Final gate (8 checks)
01_YouTube_Video_Template.md
Timing table, title options, hook, intro, beats with visual notes, outro, thumbnail
Pre-publish checklist
02_Instagram_Reel_Template.md
Reel anatomy by the second, on-screen text, caption, production notes
Pre-publish checklist
03_Instagram_Post_Template.md
Three image types, headline, caption skeleton and rules
Pre-publish checklist
04_Instagram_Carousel_Template.md
Slide map, keyword auto-DM block, design spec
Pre-publish checklist
05_Medium_Article_Template.md
A 10-part structure with mandatory Honest Caveats
Pre-publish checklist
06_Blog_Post_Template.md
Keyword and intent, an 11-part SEO structure
On-page SEO checklist
07_LinkedIn_Post_Template.md
Format rules, hook patterns, skeleton, how to publish for reach
Pre-publish checklist
prompt to paste into any LLM
[paste your filled 00_Hook_Story_Offer_Planning.md]
[paste 07_LinkedIn_Post_Template.md, or another platform template]
Write the LinkedIn piece using this plan and these template rules.
Follow the format exactly. No banned phrases.
00_Hook_Story_Offer_Planning.md (lines 124-135)
## Final gate (before you open any platform template)
- [ ] Idea fits in one sentence
- [ ] Hook stops the scroll in 3 seconds (and it's not a stat)
- [ ] Exactly one core idea
- [ ] At least one real proof point (number / code / demo)
- [ ] One screenshot-worthy line
- [ ] One honest caveat
- [ ] Exactly one primary offer
- [ ] No banned phrases
Pass all eight → go to the platform templates.
07What to watch
There is no expected output in the repo. The chapter ships templates, not generated posts. Judge a model's draft by the checklists, never by "it reads well".
Numbers must be real. The README: never fabricate a statistic; if a claim needs a source you do not have, cut it. The template examples ("41s to 12s", "80%") show the shape of a hook or proof, not facts to reuse.
A model will still use banned phrases. Saying "no banned phrases" lowers the rate; it does not make it zero. A ten-line check like the demo's catches what slips through.
Run the sanity check before shipping. Does it sound like a senior colleague over chai? Would a serious professional nod or wince? Will the audience use it, or is it clickbait? All three must pass.
Match the offer to the platform. LinkedIn hides body links (the link goes in the first comment), Instagram uses comment-keyword DMs, YouTube asks for a one-word comment and a subscribe.
Keep one keyword per set. A Reel, a Carousel and a Post that go out together reuse the same new comment keyword.
The brand-voice file is elsewhere. The Testing Academy voice guide used by the n8n content workflow lives in chapter 4 (skillfile_content_generation/brand-voice.md), not in this folder.
DDrills for the chapter
Drills 1 to 6 use the templates in chapter_06_AI_Social_Media_Content_Creation. Drills 7 to 9 automate the planner on this page: every control has a data-testid (turn on Show locator badges to see them).
Name the hook pattern
Match each hook to its pattern: (a) "I automated everything. Then I deleted half of it." (b) "AI assistants get dumber after a few hours. You've noticed too." (c) "Your 5,000 tests are not an asset. They're a liability."
Expected result
(a) The reversal, (b) The reader's own thought, (c) Blunt declarative. They are the planning sheet's own examples.
Lint a LinkedIn draft by hand
A draft opens "In today's fast-paced world...", lists its points with "-" bullets, has a link in the body, ends "What do you think?" and carries 12 hashtags. List every rule it breaks.
Expected result
Five: a banned phrase; bullets instead of → arrows; a link in the body (it goes in the first comment); the PS must be a specific or binary question; hashtags must be 5 to 7.
Place the proof
Your plan's proof is "Reduced runtime from 41s to 12s". Where does it land on a Carousel and on LinkedIn?
Hint
The Proof row of the repurpose map.
Expected result
Carousel: a code or stat slide (slide 6, "CODE / PROOF", in the carousel's fill-in template). LinkedIn: one stat line.
Write the blog metadata
Write a title tag and a meta description for the keyword "flaky test quarantine".
Expected result
A title tag of 60 characters or fewer with the keyword near the front, and a meta description of 155 or fewer with a promise and a reason to click. The keyword must also be in the H1, the URL slug, the first 100 words and at least one H2.
Ship a set
A Reel, a Carousel and a Post go out together. What must match across them?
Expected result
The comment keyword: the Reel checklist and the Post caption rules both say to reuse the same new keyword across the set.
Fix a Medium section
A Medium draft argues its point in five bullets and has no section on limitations. Fix it.
Expected result
Rewrite the bullets as paragraphs (bullets only for tutorial step headers: "Bullets are where arguments go to die") and add ## The Honest Caveats with 3 to 5 limitations, at least one against your own interest.
Pass the gate, then the checksPlaywright
Write a Playwright test: assert the sample plan's gate score, tick the one-idea box, generate the LinkedIn draft and assert the checks.
Hint
Locators: ct-gate-score, ct-gate-one-idea (data-state), ct-one-idea (a checkbox), ct-generate, ct-draft, ct-lint-score.
Expected result
The gate goes from 7 / 8 to 8 / 8; the draft starts with "Your 5,000 tests are not an asset." on its own line; the checks show 8 / 8.
Open with a statisticPlaywright
Pick the hook pattern "The number" and assert what the gate says.
Hint
ct-pattern value number fills ct-hook; the row is ct-gate-hook.
Expected result
The hook becomes "We cut flaky reruns 80% by changing one line.", ct-gate-hook has data-state="fail" and the gate drops to 6 / 8 (the one-idea box is still unticked).
Break the voice rulesPlaywright
Generate the LinkedIn draft, append the line "- This is a game-changer." and assert the checks.
Hint
Append with fill(await draft.inputValue() + ...). Rows: ct-lint-banned, ct-lint-arrows.
Expected result
Both rows fail (the banned row names game-changer) and ct-lint-score drops to 6 / 8.
SSolutions: the planner test and the template rules
The Playwright spec for the planner, then the template blocks the demo's rules come from, verbatim from the repo.
tests/content-agents-demo.spec.ts
import { test, expect } from'@playwright/test';
const URL = 'https://app.thetestingacademy.com/ai/blueprint/learn/content-agents.html';
test('the sample plan passes the gate and its LinkedIn draft passes every check', async ({ page }) => {
await page.goto(URL);
awaitexpect(page.getByTestId('ct-gate-score')).toHaveText('7 / 8');
awaitexpect(page.getByTestId('ct-gate-one-idea')).toHaveAttribute('data-state', 'fail');
await page.getByTestId('ct-one-idea').check();
awaitexpect(page.getByTestId('ct-gate-score')).toHaveText('8 / 8');
await page.getByTestId('ct-generate').click();
awaitexpect(page.getByTestId('ct-draft')).toHaveValue(/^Your 5,000 tests are not an asset\.\n/);
awaitexpect(page.getByTestId('ct-lint-score')).toHaveText('8 / 8');
});
test('a statistic as the hook fails the final gate', async ({ page }) => {
await page.goto(URL);
await page.getByTestId('ct-pattern').selectOption('number');
awaitexpect(page.getByTestId('ct-hook')).toHaveValue('We cut flaky reruns 80% by changing one line.');
awaitexpect(page.getByTestId('ct-gate-hook')).toHaveAttribute('data-state', 'fail');
awaitexpect(page.getByTestId('ct-gate-score')).toHaveText('6 / 8');
});
test('a banned phrase and a bullet fail the LinkedIn checks', async ({ page }) => {
await page.goto(URL);
await page.getByTestId('ct-generate').click();
const draft = page.getByTestId('ct-draft');
await draft.fill((await draft.inputValue()) + '\n- This is a game-changer.');
awaitexpect(page.getByTestId('ct-lint-banned')).toHaveAttribute('data-state', 'fail');
awaitexpect(page.getByTestId('ct-lint-banned')).toContainText('game-changer');
awaitexpect(page.getByTestId('ct-lint-arrows')).toHaveAttribute('data-state', 'fail');
awaitexpect(page.getByTestId('ct-lint-score')).toHaveText('6 / 8');
});
00_Hook_Story_Offer_Planning.md (lines 11-19)
## The one-line idea
> Write your idea as a single sentence. If you can't, it's not ready.
```
IDEA: ________________________________________________
WHO IT'S FOR: ________________________________________
WHY NOW: _____________________________________________ (what makes it timely / urgent)
```
00_Hook_Story_Offer_Planning.md (lines 98-102)
```
PRIMARY OFFER (exactly one): _________________________
CTA WORDING (specific, not generic): _________________
LEAD MAGNET (if any): ________________________________
```
00_Hook_Story_Offer_Planning.md (lines 111-120)
## The repurpose map
Once Hook · Story · Offer is locked, here's where each piece lands:
| Plan element | YouTube | IG Reel | IG Post | Carousel | Medium | Blog | LinkedIn |
|---|---|---|---|---|---|---|---|
| **Hook** | 0–15s hook | Slide-1 text + first spoken line | First caption line | Slide 1 | Title + bold subtitle | H1 + intro | First 2 lines |
| **Story** | Body beats | 2–4 quick beats | Caption body | Slides 2…N-1 | ## sections | ## sections | → arrow lines |
| **Proof** | On-screen demo/code | Screen-record snippet | The image | A code/stat slide | Code blocks + sources | Code + data | One stat line |
| **Offer** | One-word comment + subscribe | Comment-keyword DM | Caption CTA | Final slide CTA | Italic CTA | Inline + end CTA | First-comment link |
00_Hook_Story_Offer_Planning.md (lines 124-135)
## Final gate (before you open any platform template)
- [ ] Idea fits in one sentence
- [ ] Hook stops the scroll in 3 seconds (and it's not a stat)
- [ ] Exactly one core idea
- [ ] At least one real proof point (number / code / demo)
- [ ] One screenshot-worthy line
- [ ] One honest caveat
- [ ] Exactly one primary offer
- [ ] No banned phrases
Pass all eight → go to the platform templates.
07_LinkedIn_Post_Template.md (lines 27-32)
### Hook patterns
- "It is happening in [field] right now."
- "Unpopular opinion."
- A question they already think ("AI assistants get dumber after a few hours. Noticed?")
- An interview/story cold-open ("A candidate came to my interview yesterday…")
- A blunt reversal ("Your 5,000 tests are not an asset. They're a liability.")
07_LinkedIn_Post_Template.md (lines 58-60)
## How to actually publish it (this is half the result)
1. **No links in the post body.** LinkedIn suppresses reach on posts with outbound body links.
03_Instagram_Post_Template.md (lines 64-72)
## Pre-publish checklist
- [ ] Image stops the scroll and states the idea in 3 seconds
- [ ] Headline on image ≤ 8 words, readable at 30% zoom
- [ ] Caption first line works as a standalone hook
- [ ] Exactly one idea, one CTA
- [ ] Screenshot-worthy line present
- [ ] 5–10 relevant hashtags
- [ ] Handle/watermark on image, bottom-right
- [ ] No banned phrases, no fabricated numbers
02_Instagram_Reel_Template.md (lines 75-83)
## Pre-publish checklist
- [ ] On-screen text hook readable on mute in frame 1
- [ ] Spoken hook lands inside 3 seconds
- [ ] Exactly one micro-idea, 2–4 beats
- [ ] Subtitles burned in / enabled
- [ ] Payoff line is quotable
- [ ] One comment-keyword CTA (matches the [Carousel](04_Instagram_Carousel_Template.md)/[Post](03_Instagram_Post_Template.md) keyword if part of a set)
- [ ] 9:16, subtitles on, cover frame readable
- [ ] No banned phrases, no fabricated numbers
04_Instagram_Carousel_Template.md (lines 66-78)
## Design spec (consistent set, all slides)
```
- Ratio: 4:5 (1080×1350) per slide
- Background: deep navy #0a0a1a + subtle grid texture
- Colors: gold/amber #f59e0b headers · red #ef4444 problems/warnings ·
green #22c55e solutions · white body
- Fonts: monospace (JetBrains Mono) for code/numbers · bold sans (Inter) for labels
- Flat vector, no 3D, readable at 30% zoom
- Handle/watermark: small, muted gray, bottom-right
- Tooling: Ideogram / DAL·E for text-heavy slides, or build in Figma/Canva for perfect text.
If a generator garbles text after 2–3 tries, switch to Figma/Canva.
```
04_Instagram_Carousel_Template.md (lines 88-96)
## Pre-publish checklist
- [ ] Slide 1 hook stops the scroll on its own
- [ ] One idea per slide, 7–9 slides
- [ ] At least one proof slide (code snippet or real number)
- [ ] Final slide = payoff thesis + comment-keyword CTA
- [ ] NEW, unused 1-word ManyChat keyword + auto-DM copy written
- [ ] Consistent design across all slides, watermark present
- [ ] Readable at 30% zoom
- [ ] No banned phrases, no fabricated numbers
05_Medium_Article_Template.md (lines 99-108)
## Pre-publish checklist
- [ ] Title 8–15 words, specific (number or transformation)
- [ ] Bold subtitle contains full thesis + 3–5 real numbers + the promise, stands alone
- [ ] Opens with a moment/contrarian line, not a stat
- [ ] Paragraphs, not bullets (except tutorial step-headers)
- [ ] Every statistic has a source; nothing fabricated
- [ ] "## The Honest Caveats" present, with at least one self-critical point
- [ ] "## The Bottom Line" present
- [ ] Italic CTA at the very end + tags line
- [ ] No banned phrases
06_Blog_Post_Template.md (lines 103-112)
## On-page SEO checklist
- [ ] Primary keyword in: title tag, H1, URL slug, first 100 words, ≥1 H2
- [ ] Title tag ≤ 60 chars, meta description ≤ 155 chars with a clear promise
- [ ] One H1 only; logical H2/H3 hierarchy
- [ ] At least one image with descriptive `alt` text
- [ ] Internal links (2–4) + outbound links to credible sources (1–2)
- [ ] Key Takeaways block (snippet bait) + FAQ (long-tail + schema)
- [ ] Readable: short paragraphs, real examples, no keyword stuffing
- [ ] Mobile-readable, fast-loading images
- [ ] No banned phrases, no fabricated numbers