Seven-skill presentation system: ingest talks into a rhetoric vault, run interactive clarification, generate a speaker profile, create presentations that match your documented patterns, produce the deck illustrations + thumbnail visual layer, create and publish talk-content Agent Skills with talk pages to a Jekyll shownotes site, and verify a recorded screencast against its storyboard. Includes a 113-entry Presentation Patterns taxonomy (83 observable: 64 patterns + 19 antipatterns; 30 unobservable: 21 patterns + 9 antipatterns) for scoring, brainstorming, and go-live preparation.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Reference for Step 7 (thumbnail) in SKILL.md. The
thumbnail-generation-rules steering rule is auto-loaded — apply it, don't
restate it.
Before any thumbnail work, confirm the inputs:
speaker-profile.json — publishing_process.thumbnail config and
visual_style_history.secrets.json — Gemini API key.presentation-spec.md — talk slug, metadata.outline.yaml — slide references; the
style_anchor block (if present) feeds --portrait-style.config.python_path for the
mutation in Sub-step 10. Missing or invalid config stops this flow and invokes
Skill(skill: "vault-ingress") at Step 1.Set host_python to the current host's explicit absolute interpreter path (not
a PATH lookup). The sole interpreter-bootstrap exception is one stdlib-only
owner read:
"{host_python}" "{speaker_toolkit_root}/skills/vault-ingress/scripts/read-tracking-database.py" \
"~/.claude/rhetoric-knowledge-vault/tracking-database.json"Resolve vault_root and python_path from that report, then immediately repeat
the read with "{python_path}" against the resolved database and require the
same database bytes/SHA-256. The unconfigured host_python is authorized only for the first
owner-reader invocation. Every command below uses the configured interpreter;
never fall back to a PATH interpreter.
Read tracking-database.json through the vault path used by
presentation-creator. Selection and composition may read the generations in the
owner compatibility contract
without mutation. Before copying the approved thumbnail or writing tracking
state, require the owner-current database, current independent records, and talk
schema 8. Invoke Skill(skill: "vault-ingress") for legacy generations and stop
this run. Unknown future generations are no usable prior state. Preserve every
schema field and use the presentation-creator exact-generation atomic-write
contract.
If shownotes are needed too (Step 7.2 in presentation-creator) and don't exist yet, STOP and ask before generating the thumbnail.
Scan the outline for high-impact slides. Suggest 3–5 candidates ranked by visual engagement:
Avoid: bio slides, shownotes URL slides, bullet-heavy slides, generic titles.
Present candidates to the speaker with slide numbers and brief descriptions. The speaker picks one — never auto-select.
Resolution chain:
illustrations/ for
slide-{NN}.* matching the chosen slide."{python_path}" "{speaker_toolkit_root}/skills/illustrations/scripts/generate-thumbnail.py" \
--extract-slide deck.pptx 15 --output slide-15.pngResolution order:
publishing_process.thumbnail.speaker_photo_path from speaker profile.The photo must be a real photograph — never AI-generated. Expression should convey engagement and energy, not a neutral corporate headshot.
NOT the full talk title. A 3–5 word hook designed for thumbnail readability at small sizes.
Walk the precedence chain (thumbnail-generation-rules Rule 7):
publishing_process.thumbnail.aesthetic_preference — explicit speaker
preference ("photo" or "comic_book"). Honor it and stop.visual_style_history.default_illustration_style — fuzzy-match against
the comic-book family (comic_book / comic-book / halftone /
illustrated / cartoon / caricature) → recommend comic_book.
Documented styles outside that set (retro_tech_manual, watercolor,
etc.) → out-of-scope; ask the speaker before generating.visual_style_history.confirmed_visual_intents — same fuzzy-match
against each entry's pattern and rule fields.photo.Lead with the recommended aesthetic. Offer a two-candidate side-by-side only when the speaker is genuinely undecided — not as a default. Comic-book is high-variance: when it works, CTR rises significantly; when it misses, it looks off-brand.
If outline.yaml has a style_anchor block (with full / imgtxt anchor
paragraphs), pass the matching format's anchor paragraph to
generate-thumbnail.py via --portrait-style "<anchor>". The script
pre-stylizes the speaker photo
into the anchor's medium (sepia tech-manual, watercolor, pen-and-ink, etc.)
before composition, so the output palette matches the deck. Without this pass-through, photographic skin tones beside
an illustrated background produce a jarring two-medium composite even when
the aesthetic is otherwise correct.
If Phase 2 didn't produce a style anchor (stock-image-only deck), omit
--portrait-style.
# Single recommended candidate (the precedence-chain winner)
"{python_path}" "{speaker_toolkit_root}/skills/illustrations/scripts/generate-thumbnail.py" \
--slide-image illustrations/slide-15.png \
--speaker-photo ~/photos/headshot.jpg \
--title "JUDGMENT DAY" \
--subtitle "DevNexus 2026" \
--vault ~/.claude/rhetoric-knowledge-vault \
--aesthetic <photo|comic_book> \
--style slide_dominant \
--title-position top \
--brand-colors "#5B2C6F,#C0392B" \
--output thumbnail.png
# Anchor-matched (when the deck has a style_anchor block)
"{python_path}" "{speaker_toolkit_root}/skills/illustrations/scripts/generate-thumbnail.py" \
--slide-image illustrations/slide-15.png \
--speaker-photo ~/photos/headshot.jpg \
--title "JUDGMENT DAY" \
--aesthetic photo \
--portrait-style "<full anchor paragraph>" \
--output thumbnail-anchored.pngApply other speaker preferences from publishing_process.thumbnail:
style_preference → --styletitle_position → --title-positionbrand_colors → --brand-colorsaesthetic_preference is consumed at Sub-step 5 — don't re-apply it.
The script (per invocation, runs once per --aesthetic):
thumbnail.png in the
illustrations dir).Present the generated thumbnail. If rejected, iterate — never regenerate from scratch:
--title-position.If publishing_process.shownotes.enabled is true, the SSG template expects
the thumbnail at a specific path relative to the shownotes site root —
otherwise the live page falls back to a placeholder with no warning.
Resolve the destination using publishing_process.shownotes:
{shownotes.source.path_or_url}/{shownotes.thumbnail_path_template}with {slug} substituted from the Presentation Spec. For Jekyll-based
shownotes the default template is
assets/images/thumbnails/{slug}-thumbnail.png — the nested thumbnails/
subdirectory AND the -thumbnail suffix are both mandatory. Do not strip
either.
Create the thumbnails/ directory if it doesn't exist, then copy (don't
move) the generated thumbnail. The local copy in illustrations/thumbnail.png
stays with the talk's working directory for tracking.
If shownotes.ssg_template_pointer is set, read that file after a site
redesign to re-derive the path convention. Don't reinvent it from folklore.
Prepare this complete thumbnails[] record:
{
"schema_version": 1,
"talk_slug": "judgment-day",
"youtube_url": "https://youtube.com/watch?v=...",
"source_slide_num": 15,
"speaker_photo_used": "/path/to/headshot.jpg",
"thumbnail_path": "illustrations/thumbnail.png",
"shownotes_thumbnail_path": "assets/images/thumbnails/judgment-day-thumbnail.png",
"dimensions": "1280x720",
"file_size_kb": 185,
"created_at": "2026-04-20",
"approved": true
}Persist it with the ingress owner's upsert_thumbnail mutation, expecting the
exact existing record for the slug or {"$missing": true}. In the same plan, use
update_talk_publishing to set thumbnail_generated: true on the exact talk
filename, expecting its current value. Dry-run the whole plan, review it, apply
against the reported input SHA, and re-read as specified by the
owner mutation contract.
Keep that talk at schema_version: 8. illustrations is an authorized writer of
current thumbnail and talk records; vault-ingress remains their schema owner.
Never rewrite tracking-database.json directly.
.tessl-plugin
rules
skills
illustrations
presentation-creator
references
patterns
build
deliver
prepare
scripts
screencast-recorder
shownotes-publisher
vault-clarification
vault-ingress
references
scripts
vault-profile