| name | content-brief |
| description | Generates a fully structured SEO content brief for a target keyword and optionally pushes it to a Notion database. Use this skill whenever the user says 'create a content brief', 'brief this keyword', 'run a content brief for', 'generate a brief', 'write a brief for [keyword]', 'content brief on [topic]', or any variation where someone needs a keyword researched and turned into a structured writing assignment with H1, H2 outline, FAQ, internal links, word count target, and writer notes. Also triggers when the user provides a keyword and asks for an SEO brief, editorial brief, or writing spec. Outputs a mandatory structured format that the text parser maps directly to Notion properties. Supports single-keyword and batch (CSV) modes. |
| metadata | null |
Content Brief — Keyword-to-Notion Brief Generator
Generates a structured SEO content brief from a target keyword. Output follows the mandatory Direction prompt format so the text_parser.py script can extract every field for Notion without manual cleanup.
Invocation Triggers
Explicit phrases (any of):
- "create a content brief for [keyword]"
- "brief this keyword: [keyword]"
- "content brief on [topic]"
- "generate a brief for [keyword]"
- "write a brief for [keyword]"
- "run the content brief skill"
Implicit signals:
- User provides a keyword and asks for an SEO spec, editorial spec, or writing assignment
- User pastes a keyword list and asks for briefs
When triggered, run immediately — no upfront intake beyond the keyword itself.
Grill-Me Intake (One Question, Optional)
Run the brief without questions when the keyword is clear.
Ask one clarifying question only when both are true:
- The target audience or client is not inferrable from context
- Audience changes the content angle meaningfully (e.g., "project management software" could target PMs or developers)
Quick clarification — who is the primary audience for "[keyword]"?
- [Inferred persona A — e.g., HR Director]
- [Inferred persona B — e.g., Operations Manager]
- Tell me
Why I'm asking: audience shapes the H1, content angle, and writer notes. One question prevents a wrong brief.
Max one question. If audience is inferable, skip and proceed.
Data Gathering (Before Writing the Brief)
Run these steps before generating the Direction prompt output:
Step 1 — Keyword Metrics
Preferred: Ahrefs MCP (keywords_explorer_overview) → volume, KD, CPC, SERP data.
Fallback (no Ahrefs MCP): Use WebSearch to estimate:
- Search
[keyword] search volume KD CPC site:ahrefs.com OR site:semrush.com OR site:moz.com
- Extract available volume/KD/CPC estimates
- If no data found, set VOLUME/CPC/DIFFICULTY to
[not available — add manually]
Step 2 — Competitor H2/H3 Analysis
- WebSearch
[keyword] → identify top 3 organic results (skip ads, maps, featured snippets)
- WebFetch each URL → extract all H2 and H3 headings
- Note: competitor structure informs the H2_OUTLINE. Do not copy — use as gap analysis.
Step 3 — Search Intent Classification
Based on keyword + SERP type, classify as one of exactly four options:
Informational — user wants to learn
Commercial — user is comparing options before buying
Transactional — user is ready to act/purchase
Navigational — user seeks a specific brand/site
Step 4 — Priority Scoring
Apply routing logic from references/routing-logic.md:
- HIGH: Volume > 200 AND KD < 40 AND intent is Commercial or Transactional
- MEDIUM: Doesn't meet HIGH criteria but has meaningful volume or strategic importance
- LOW: Low volume, high difficulty, or informational with limited conversion value
Direction Prompt Output Format (Mandatory)
This format is non-negotiable. The text_parser.py script performs label-exact extraction. If any label deviates from the format below — wrong case, extra space, missing underscore — the Notion property will arrive empty.
After data gathering, output the brief using EXACTLY this structure:
TARGET_KEYWORD: [keyword]
VOLUME: [number or "not available"]
CPC: [decimal or "not available"]
DIFFICULTY: [0-100 integer or "not available"]
SEARCH_INTENT: [Informational | Commercial | Transactional | Navigational]
AUDIENCE: [persona — job title or role]
RECOMMENDED_H1: [final proposed title]
CONTENT_ANGLE: [one paragraph describing the unique angle, why this beats competitors, what the post must do]
WORD_COUNT: [number]
SCHEMA: [schema type — e.g., FAQ, HowTo, Article, FAQ + HowTo]
PRIORITY: [HIGH | MEDIUM | LOW]
H2_OUTLINE:
- H2: [heading]
- H3: [subheading]
- H3: [subheading]
- H2: [heading]
- H3: [subheading]
FAQ:
- Q: [question the audience actually searches]
- Q: [question]
- Q: [question]
INTERNAL_LINKS:
- [anchor text] → [relative URL or page title if URL unknown]
WRITER_NOTES:
[one paragraph of specific guidance: tone, POV, what to avoid, key differentiators to emphasize, CTAs, any client-specific requirements]
Critical rules:
- Every field label must appear exactly as shown (ALL_CAPS with underscores)
- SEARCH_INTENT value must exactly match one of the four options (capitalized)
- PRIORITY value must be exactly HIGH, MEDIUM, or LOW
- H2_OUTLINE, FAQ, INTERNAL_LINKS, WRITER_NOTES are block fields — content follows on the next line(s)
- No additional text before TARGET_KEYWORD or after WRITER_NOTES block
Workflow Architecture (9 Nodes)
| Node | Role | Tool |
|---|
| 1 — Input | Accept keyword + optional client/audience context | User message |
| 2 — Keyword Metrics | Pull volume, KD, CPC, SERP type | Ahrefs MCP OR WebSearch fallback |
| 3 — SERP Scrape | Extract H2/H3 from top 3 organic results | WebFetch |
| 4 — Brief Generation | Process data through Direction prompt → structured output | Claude (this skill) |
| 5 — Text Parser | Extract labeled fields → structured variables | scripts/text_parser.py |
| 6 — Conditional Router | Route based on PRIORITY value | Routing logic |
| 7A — Notion Create (HIGH) | Create page, Status = "Briefed: Ready for Assignment" | Notion MCP |
| 7B — Notion Create (MED/LOW) | Create page, Status = "Briefed: Weekly Review Queue" | Notion MCP |
| 8A — Slack Notify (HIGH only) | Post brief summary + Notion link to channel | Slack MCP |
| 9 — Calendar Sync | Create linked entry in Content Calendar database | Notion MCP |
In Claude Code without MCP connectors: Nodes 1–5 run automatically. Nodes 6–9 produce a ready-to-paste summary and instruct the user on manual Notion entry.
Batch Processing Mode
Trigger: user provides a CSV with a Target Keyword column (optional Priority Override column).
Process:
- Confirm CSV is readable and
Target Keyword column exists
- Run each keyword through the full pipeline sequentially
- Output all briefs in sequence, separated by
---
- After all briefs: output a summary table (keyword | priority | word count | schema)
Expected throughput: 20 briefs in 20–25 minutes (60–75 seconds per brief).
If any keyword fails (no SERP data, ambiguous intent): note it in the summary table as [FAILED — reason] and continue processing remaining keywords.
Notion Push (When MCP Available)
Map parser output to Notion properties using references/notion-schema.md.
Two paths based on PRIORITY:
HIGH:
- Status → "Briefed: Ready for Assignment"
- Target Publish Date → today + 14 days
- Trigger Slack notification (Node 8A)
MEDIUM:
- Status → "Briefed: Weekly Review Queue"
- Target Publish Date → today + 28 days
LOW:
- Status → "Briefed: Weekly Review Queue"
- Target Publish Date → today + 42 days
After page creation: run Calendar Sync (Node 9) to create linked entry in Content Calendar database.
Pre-check before creating: query Notion for existing page with same TARGET_KEYWORD. If found → route to update_page instead of create_page to prevent duplicates.
Multi-Client Setup
Each client has:
- Separate Notion integration token
- Separate database ID
- Client-specific Direction prompt variant (adjust audience, tone, internal link base URLs)
Onboarding a new client: ~45–60 minutes to configure connector + test one brief end-to-end.
Output When Notion MCP Is Not Connected
If Notion MCP is not available, after generating the Direction prompt output, append:
---
NOTION PUSH: Not connected. To add this brief to Notion manually:
1. Open your Notion database
2. Create a new page
3. Paste the following field values:
[formatted summary of all extracted fields]
Or run: python scripts/text_parser.py brief.txt --output json
to get a JSON payload ready for the Notion API.
---
Validation Gate
After generating output, mentally verify:
- All 11 simple fields are present and non-empty
- SEARCH_INTENT is one of the 4 valid values
- PRIORITY is exactly HIGH, MEDIUM, or LOW
- H2_OUTLINE has at least 4 H2s each with at least 1 H3
- FAQ has at least 3 questions
- INTERNAL_LINKS has at least 2 entries
- WRITER_NOTES is a substantive paragraph (not a placeholder)
Run scripts/brief_validator.py on the output file for automated validation.
Error Handling
| Situation | Behavior |
|---|
| No keyword data available | Set numeric fields to "not available", add note in WRITER_NOTES instructing editor to verify manually |
| SERP scrape blocked (403/paywalled) | Skip scrape, note "competitor outline not available" in WRITER_NOTES, proceed with brief |
| Ambiguous search intent | Default to Informational; flag in WRITER_NOTES: "Intent ambiguous — verify before briefing writer" |
| Select value mismatch in Notion | Capitalize values exactly; Notion select is case-sensitive |
| Duplicate keyword detected | Route to update_page instead of create_page |
| >2 empty properties in parsed brief | Flag for manual review; do not push to Notion |
| Batch keyword fails | Note in summary table, continue processing |
| CSV missing Target Keyword column | Stop and ask user to confirm column name |
See references/error-handling.md for full failure-point catalog.
Tooling
| Script | Role |
|---|
scripts/text_parser.py | Extracts labeled fields from Direction prompt output → structured dict. python text_parser.py brief.txt --output json |
scripts/brief_validator.py | Validates all required fields are present, values are in allowed sets. python brief_validator.py brief.txt |
References
references/notion-schema.md — Notion database property config (names, types, allowed values)
references/routing-logic.md — Priority scoring rules and publish date calculations
references/error-handling.md — Known failure points and fixes
Anti-Patterns To Reject
- Deviating from the mandatory Direction prompt label format (breaks parser)
- Using lowercase or mixed-case field labels (TARGET_KEYWORD not Target_Keyword)
- Putting SEARCH_INTENT outside the four allowed values
- Generating a brief without first gathering keyword + SERP data
- Asking multiple intake questions before running
- Writing vague WRITER_NOTES ("write a good post about this topic")
- Fabricating keyword metrics when data is unavailable — always flag as "not available"
- Pushing to Notion when >2 fields are empty