Install
$ agentstack add skill-karenspinner-article-thumbnail-skill-article-thumbnail ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Article Thumbnail Skill (Claude Code)
Generate brand-consistent still thumbnails for written articles. The thumbnail is a single image showing whatever the user's brand calls for — the recurring character(s), prop(s), composition, and constraints are all defined by the user in the BRAND BLOCK below.
> This skill is designed for Claude Code only. It uses Bash to invoke generate.js, a small zero-dependency Node script that lives in the user's writing project directory (the cwd where Claude Code is running). Claude Desktop does not have Bash and cannot drive this skill.
When to use this skill
Activate when the user:
- Pastes or links an article and asks for a thumbnail / cover / hero image / social preview
- Says "make a thumbnail for this post"
- Asks for a cover image to go with a draft
Don't use this for animated content, video covers, photo-realistic imagery, or thumbnails that require extensive legible text.
Prerequisites
Before this skill can run, the user must have completed these one-time setup steps:
- A Gemini API key with billing enabled — stored in
.env(withGOOGLE_AI_API_KEY=...) in the cwd, OR exported in their shell rc. generate.jsin the cwd — a small zero-dependency Node script that calls the Gemini API.- Node.js 18+ installed.
- BRAND BLOCK filled in below — every
[FILL IN ...]marker replaced. The skill cannot work without this.
If the BRAND BLOCK still has [FILL IN] markers, stop and tell the user the skill isn't customized yet — they need to edit ~/.claude/skills/article-thumbnail/SKILL.md to replace those markers. If generate.js is missing or the API key isn't set, the script's own error message will tell the user the specific problem when invoked.
BRAND BLOCK (user customizes this — every field below)
> Replace each [FILL IN ...] placeholder with your own details. Once filled in, this section is the source of truth for every thumbnail. Don't change it per-article; only change it when your brand visual identity changes.
Characters
Primary character description: [FILL IN — Describe in 1-3 sentences. Include: gender/age range, distinctive physical features, what they're wearing or carrying, and the rendering style they're drawn in.]
Secondary character description (optional): [FILL IN — Describe similarly, or leave blank if you don't have a recurring second character.]
Reference image paths:
- Primary character ref:
[FILL IN — absolute path] - Secondary character ref (if applicable):
[FILL IN — absolute path or leave blank] - Style anchor (an image that exemplifies the desired illustration style):
[FILL IN — absolute path]
Output
Aspect ratio: [FILL IN — e.g. 16:9, 4:3, 1:1, 3:2]
Pixel size: [FILL IN — e.g. 1456x816, 1200x630, 1080x1080]
Output directory: [FILL IN — absolute path where generated thumbnails should be saved, e.g. /Users/you/Pictures/thumbnails/]
Composition policies
These are YOUR aesthetic rules. They drive every scene plan.
Illustration style: [FILL IN — Describe the visual style in concrete terms: line weight (thin/medium/heavy), color treatment (flat colors / soft shading / gradients / watercolor / photo-real), palette (saturated / muted / pastel / monochrome), level of detail. The more specific, the better Gemini will match it.]
Background policy: [FILL IN — describe the background convention. Examples: "Pure white, no environment" / "A subtly blurred environment that hints at the article's domain (kitchen, office, garden)" / "Abstract gradient in brand colors" / "Whatever fits the article tone — figures-on-plain-background or scenic both fine".]
Element count: [FILL IN — typical maximum number of distinct elements (figures + props). Examples: "3 max — primary + secondary + 1 prop" / "5-6 elements OK" / "no fixed limit, judge per article".]
Environment policy: [FILL IN — when (if ever) is an environment/setting allowed? Examples: "Never — figures sit on plain background" / "Always — figures inhabit a scene relevant to the article" / "Optional based on article tone".]
Text in image: [FILL IN — your policy on words/letters/numbers in the image. Examples: "Forbidden anywhere" / "Title text in lower third allowed" / "Labels on objects allowed when they're integral (clock numbers, signage)" / "No constraint".]
Prop selection style: [FILL IN — describe how you pick props. Examples: "Domain-native — only objects the article's actual subjects would touch in real life" / "Symbolic icons — use recognizable visual metaphors (trophy = win, clock = time)" / "Abstract / geometric forms" / "Photographic real-world objects". This is one of the most important brand decisions; be specific.]
Banned visual elements (optional): [FILL IN — list specific elements you never want, or leave blank. Examples: "no charts/graphs/data viz" / "no gift wrapping or rhinestones" / "no children" / "no real-world brand logos".]
Workflow
When the user gives you an article and asks for a thumbnail:
Step 1 — Read the article carefully
Identify:
- Core finding: the one cause-effect or insight the article is arguing. Not the topic — the finding. ("Flattery makes a model skip planning" is a finding; "AI politeness research" is just a topic.)
- Tone: confident, skeptical, alarmed, hopeful, technical-dry, etc.
- Concrete domain objects: physical/visual things that appear in the article's actual subject. Cooking → ingredients, utensils. Coding → terminals, code. Carpentry → lumber, tools. These are candidate props.
Step 2 — Design the scene per the BRAND BLOCK policies
Output a single coherent scene plan. The BRAND BLOCK composition policies (background, element count, environment, text, prop style, banned elements) are constraints — design WITHIN them, not around them.
Use this structure:
SCENE PLAN
- Core finding (1 sentence): ...
- Composition:
- Prop:
- Action / state shown:
- Why this works:
Step 3 — Confirm with user
Each call to generate.js is a paid API call. Plan iteration in text is free (just Claude tokens). Before generating anything, show the SCENE PLAN to the user and ask if they want to proceed or iterate.
If the article has more than one strong angle, you can offer the user choices:
- Multiple SCENE PLAN variants — propose 2-3 different framings of the article (e.g., the cause, the effect, the surprise, the human element, the takeaway), let the user pick which to render. Cheapest path: only one image generation.
- Multiple image variants of ONE scene plan — Gemini produces different visual interpretations from the same prompt. Useful when the plan is right but you want to compare a few rendered versions and pick the most on-brand one. Run
generate.jsN times with the same prompt and refs, varying only the--outputfilename. - Both — pick a plan first, then render multiple variants of it.
Don't decide for the user how many images to render — this is their cost decision. Tell them the per-image cost for the model they're using (look it up at https://ai.google.dev/gemini-api/docs/pricing — pricing varies by model and shifts over time, so don't quote a hardcoded number) and ask how many they want. Some users want one shot; others want 3-5 variants to compare.
Step 4 — Generate via Bash
Build the full image prompt using the PROMPT TEMPLATE below, then call generate.js from the cwd:
node generate.js \
--prompt="" \
--refs=",," \
--output="/-YYYY-MM-DD.png"
The --refs argument is a comma-separated list of absolute paths from the BRAND BLOCK. Skip secondary character if blank.
If the user asked for multiple variants of the same scene (Step 3), call generate.js once per variant with the same --prompt and --refs but a different --output filename. Run them sequentially (not parallel) to avoid rate-limit issues. Suffix outputs like -v1.png, -v2.png, -v3.png. Each call is a separate API call.
On success, the script prints OK: to stdout.
If the script returns "GOOGLEAIAPI_KEY is not set", the user hasn't created a .env file in the cwd yet. Tell them to run echo 'GOOGLE_AI_API_KEY=your-key' > .env (with their actual key) in this directory, then retry.
Step 5 — View and critique
Use the Read tool to view the generated PNG. Check it against the BRAND BLOCK policies AND the universal best practices (next section):
- ✓/✗ Background follows the brand background policy?
- ✓/✗ Element count within the brand max?
- ✓/✗ Environment matches the brand environment policy?
- ✓/✗ Text policy honored?
- ✓/✗ Prop matches the brand propselectionstyle?
- ✓/✗ No banned elements present?
- ✓/✗ Characters look like the brand references?
- ✓/✗ Aspect ratio matches the brand canvas?
If any check fails, propose a targeted edit (next step).
Step 6 — Iterate via edit, not regenerate
When the user wants changes, prefer editing the existing image:
node generate.js \
--input="" \
--prompt="" \
--output=""
Editing preserves character/style/composition between iterations. Regenerating produces a fresh image that may differ in unwanted ways. Each edit is its own paid API call at the model's current per-image rate (see https://ai.google.dev/gemini-api/docs/pricing).
State explicitly what to change AND what to preserve in the edit prompt. Vague instructions like "make it better" don't work.
Universal best practices (apply regardless of brand)
These are aesthetic patterns that hold across most editorial illustration styles. They complement (don't override) the BRAND BLOCK.
- One coherent scene, not a collage. Whatever the brand background policy, all elements should look like they belong together — same lighting, same scale relationships, same illustration style. Avoid the "transparent PNG cutouts pasted on a background" look unless the brand explicitly wants it.
- Characters must match brand references. Always pass the brand's reference images via
--refs. Even with refs there will be slight drift; describe the characters specifically in the prompt to reinforce.
- The prop should ENACT the article's finding, not just symbolize it. Whatever prop style the brand uses (domain-native, symbolic, abstract), the prop should do something that conveys the article's cause-effect, not sit there inert. A wilting plant tells more story than a healthy plant; a stack of paperwork shrinking tells more than a static stack.
- Specificity beats vagueness in prompts. "A stack of papers" is vague; "a tall stack of yellow sticky notes that visibly shrinks" is specific. The more concrete the description (size, color, count, what's happening to it), the more on-target the result.
- Two-element comparison is one slot. When an article hinges on a comparison (honest vs gamed, before vs after, version A vs version B), it's acceptable to use a tightly-coupled prop pair — two instances of the same kind of object differing in the dimension the article is about. Counts as one prop slot for element-count purposes.
PROMPT TEMPLATE (for the --prompt argument)
Build the prompt using this skeleton — substitute values from the article and the BRAND BLOCK:
Generate a single illustrated frame in the EXACT style of the reference images, featuring the EXACT characters from the references.
Scene to render:
Style and constraints (violating any = wrong output):
- Illustration style:
- Background:
- Aspect ratio:
- Primary character must look identical to the first reference image
-
- Match the style anchor's line weights, palette, and shading exactly
- Text in image:
- Element count: stay within
- Banned elements:
Pass the references via --refs in this order: primary character, secondary character (if any), style anchor.
COMMON PITFALLS
- Environment leak. Even with explicit "no environment" rules, Gemini sometimes adds a desk, bookshelf, floor, or window. If the brand background policy forbids this, edit it out: re-run with
--input=and prompt "Remove the [specific environment element]. Background should be . Keep everything else identical."
- Text bleed-through. Even with "no text" rules, Gemini sometimes renders text on paper, signs, screens, or labels. If the brand text policy forbids this, edit it out: "Remove all text, words, letters, and numbers from . Replace with abstract handwriting-like squiggles or blank texture. Keep everything else identical."
- Character drift. Gemini's character consistency from references is good but not perfect. Slight face-shape, hair-color, or proportion drift is normal. If the drift is severe, regenerate from scratch (don't edit — editing won't fix identity). Adding more specific physical-feature description in the prompt also helps.
- Aspect ratio ignored. Gemini sometimes ignores aspect ratio if not stated forcefully. State it twice in the prompt if needed.
- "Subtle" or "atmospheric" effects produce environment as a side effect. If the brand background policy is plain, avoid these adjectives. Stick to concrete physical descriptions of what's actually visible.
- Editing prompts that delete more than intended. "Remove the red marks" can sometimes remove the object the marks were on. Always state what to PRESERVE alongside what to remove.
Cost notes
Each call to generate.js is one API call to the configured model, billed at that model's per-image rate. Pricing varies significantly by model — gemini-2.5-flash-image is cheaper than gemini-3-pro-image-preview by an order of magnitude or more.
When the user is making a cost-sensitive decision (number of variants to render, which model to use, whether to iterate via edit vs. regenerate), look up the current per-image price for their chosen model at https://ai.google.dev/gemini-api/docs/pricing and quote the actual current rate. Do not rely on hardcoded numbers in this skill or in the README — pricing changes over time and varies by model. Tell the user the current real cost so they can decide.
Plan iteration (text-only conversation about the SCENE PLAN) is free. Image generation and editing each cost one API call. The user decides how many calls to make.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: KarenSpinner
- Source: KarenSpinner/article-thumbnail-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.