Learn-skills.dev blog-persona

install
source · Clone the upstream repo
git clone https://github.com/NeverSight/learn-skills.dev
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/agricidaniel/claude-blog/blog-persona" ~/.claude/skills/neversight-learn-skills-dev-blog-persona && rm -rf "$T"
manifest: data/skills-md/agricidaniel/claude-blog/blog-persona/SKILL.md
source content

Blog Persona - Writing Voice Management

Create, store, and enforce writing personas based on the NNGroup 4-dimension tone framework and CMI Brand Voice Chart. Personas ensure consistent voice across all blog content produced by blog-write and blog-rewrite.

Commands

CommandPurpose
/blog persona create
Interactive interview to build a new persona
/blog persona list
Show all saved personas
/blog persona use <name>
Set active persona for current session
/blog persona show <name>
Display full persona profile

Create Workflow

Run the 6-step interactive interview. Ask each step, wait for response, then proceed.

Step 1: Brand Basics

Ask the user for:

  • Brand name - company or personal brand
  • Industry - primary sector (e.g., SaaS, health, finance, education)
  • Target audience - who reads the blog (role, experience level, goals)
  • One-sentence brand mission - what the brand helps people do

Step 2: Tone Dimensions (NNGroup Framework)

Present each dimension as a 0.0 to 1.0 slider. Explain both ends with examples.

Dimension0.0 End1.0 EndExample at 0.0Example at 1.0
funny_seriousFunnySerious"Let's be real, nobody reads Terms of Service""Understanding legal agreements protects your business"
formal_casualFormalCasual"We are pleased to announce""Guess what - we shipped it!"
respectful_irreverentRespectfulIrreverent"We appreciate your patience""Yeah, that old way was broken"
enthusiastic_matter_of_factEnthusiasticMatter-of-fact"This changes everything!""Here are the results."

Defaults if user is unsure:

[0.6, 0.5, 0.3, 0.5]
(slightly serious, balanced formality, respectful, balanced enthusiasm).

Step 3: Writing Rules

Ask the user to pick a vocabulary tier first, then auto-suggest the matching readability band (user can override).

SettingWhat to AskDefault
Vocabulary tierConsumer, Professional, or TechnicalProfessional
Readability bandAuto-filled from tier (see table below)Grade 8-10
Sentence length meanAverage words per sentence18
Sentence length stdVariation in sentence length6
Contraction frequency0.0 (never) to 1.0 (always)0.6
Max passive voicePercentage cap on passive constructions10%

Step 4: Do's and Don'ts (CMI Brand Voice Chart)

Ask for 3-5 items in each list. Provide starter examples based on the tone dimensions.

Example Do's: "Use data to back claims", "Address the reader as you", "Open with a question or stat"

Example Don'ts: "Don't use jargon without defining it", "Don't start sentences with There is/There are", "Don't use cliches like game-changer"

Step 5: Summary Label Preference

The label used for summary/takeaway boxes in blog posts. Ask user to pick one:

  • Key Takeaways (default)
  • The Bottom Line
  • What You'll Learn
  • TL;DR
  • Quick Summary
  • In a Nutshell
  • Custom label

Step 6: Voice Samples (Optional)

Ask if the user has 1-3 URLs of existing content that exemplifies the desired voice. Store URLs in the persona for future reference. If provided, read each URL and extract:

  • Average sentence length
  • Contraction frequency
  • Tone dimension estimates
  • Vocabulary level

Compare extracted values with the persona settings and flag any mismatches.

Save

Write the completed persona as JSON to:

skills/blog/references/personas/<name>.json

Use kebab-case for the filename (e.g.,

acme-saas.json
).

Persona Profile Schema

{
  "name": "acme-saas",
  "description": "Professional SaaS voice for B2B marketing content",
  "brand": "Acme Corp",
  "industry": "SaaS",
  "audience": "Marketing managers at mid-market companies",
  "mission": "Help marketing teams automate reporting",
  "tone_dimensions": {
    "funny_serious": 0.7,
    "formal_casual": 0.4,
    "respectful_irreverent": 0.2,
    "enthusiastic_matter_of_fact": 0.5
  },
  "readability": {
    "flesch_grade_min": 8,
    "flesch_grade_max": 10,
    "flesch_ease_min": 50,
    "flesch_ease_max": 60
  },
  "style": {
    "sentence_length_mean": 18,
    "sentence_length_std": 6,
    "contraction_frequency": 0.6,
    "passive_voice_max_pct": 10,
    "vocabulary_tier": "professional",
    "summary_label": "Key Takeaways"
  },
  "voice_samples": [],
  "do": [
    "Use data to back every major claim",
    "Address the reader directly as you",
    "Lead sections with actionable insight"
  ],
  "dont": [
    "Don't use buzzwords without context",
    "Don't write sentences longer than 30 words",
    "Don't open with We at Acme"
  ]
}

Readability Bands by Vocabulary Tier

TierFlesch GradeFlesch EaseTypical Use
Consumer6-860-80Health, lifestyle, personal finance
Professional8-1050-60B2B, marketing, management
Technical10-1230-50Engineering, medical, legal

When the user picks a tier, auto-fill the readability fields. Let them override if they want a non-standard combination (e.g., technical vocabulary at consumer readability for explainer content).

Integration with blog-write and blog-rewrite

When a persona is active (via

/blog persona use <name>
), the writer agent loads the persona JSON and enforces these constraints during generation:

  1. Pre-generation - Load persona, inject tone dimensions and style rules into the system prompt for the blog-writer agent.
  2. During generation - Writer follows do/dont rules, targets sentence length mean/std, uses contractions at specified frequency.
  3. Post-generation validation - Check the output against persona constraints:
    • Sentence length distribution within 1 std of target mean
    • Readability score within the specified grade band
    • Passive voice percentage under the max
    • No violations of "dont" rules found via pattern matching

If validation fails, flag the specific violations and suggest edits.

List Command

Glob

skills/blog/references/personas/*.json
and display a table:

PersonaIndustryAudienceVocabulary
acme-saasSaaSMarketing managersProfessional

If no personas exist, prompt the user to create one.

Show Command

Read the specified persona JSON and display it as a formatted summary with all tone dimensions, style rules, and do/dont lists.

Use Command

Read the persona JSON and confirm activation. Print a summary of the key constraints that will be enforced. The persona stays active for the current conversation session. Blog-write and blog-rewrite check for the active persona before generating content.

Error Handling

  • Invalid tone values: If a user provides values outside 0.0-1.0, clamp to the nearest valid bound and warn
  • Unreachable voice samples: If a URL in voice_samples returns an error, skip it and note in the profile that the sample was unavailable
  • Empty personas directory: When running list or show with no personas saved, prompt the user to create one first
  • Name conflicts: If a persona name already exists during create, ask whether to overwrite or choose a different name
  • Malformed JSON: If a persona file is corrupted, report the error and offer to recreate it from the interview