deck3d
SkillDocs & knowledgeLets your agent turn a Markdown outline into a self-contained offline 3D presentation.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the deck3d skill
About this capability
Build a self-contained 3D presentation from a Markdown outline, parse, tune via `overrides`, render to one offline deck.html. Use on "make a 3D deck from this outline", "build a presentation from these notes", "deck3d this markdown", "turn this talk into a 3D deck".
What this skill tells your AI
The instructions your AI receives, as published by blackbelttechnology/pi-agent-dashboard in packages/deck3d/.pi/skills/deck3d/SKILL.md and read by ahel’s review.
Turn a Markdown outline into one self-contained, offline deck.html: extruded 3D
titles, harvested mermaid diagrams built as 3D objects, animated backgrounds, and
an optional glTF prop. The converter code is deterministic; you tune the result
by writing overrides in deck.json, never by editing the HTML.
When to use
- The user has a Markdown outline (headings + bullets + ```mermaid blocks) and wants a presentation they can open offline in a browser.
- You need to tune placement, legibility, mode, effects or props of an existing
deck.json.
Markdown grammar
---front-matter: deck defaults (mode,palette,material,quality,transition, …).# Titlestarts a slide. Zero headings ⇒ one slide idslide.- The first paragraph after the heading (before bullets) is the subtitle.
- bulletlines are body bullets.- A fenced ```mermaid
flowchart/sequenceDiagramblock becomes the slide's diagram (harvested in headless chromium). Any other diagram type ⇒ warn + no diagram. <!-- deck3d: {...} -->inline overrides win overdeck.jsonand warn on clobber.- Pin a slide id with
# Final {#outro}so renames never orphan tuning.
The tune loop
deck3d parse talk.md→talk.json(derived IR + emptyoverrides).deck3d validate talk.json→ schema + derived-edit + orphan/prop warnings.deck3d build talk.md -o talk.html→talk.json+talk.html; runscheck.- Read the
checkfindings. Fix only the suggested key (e.g.overrides.slides["arch"].diagram.scale), then re-run step 3. deck3d snapshot talk.html --slide 5 -o s5.pngto eyeball one slide.- Repeat until
checkis clean (or only acceptable contrast warnings remain).
Tune by writing deck.json's overrides only:
overrides: {
deck: { ...defaults knobs... },
effects: [{ id, params? }],
props: [{ source, id, licence, author, sha256, slide, role, size?, count?, restyle?, anim? }],
slides: { "<slideId>": { mode?, palette?, material?, scene?, quality?,
diagram: { scale?, offset? }, camera: { distance? }, labels: { size? },
check: { ignore? }, effects? } },
nodes: { "<slideId>/<nodeId>": { shape?, label?, position?, size?, material? } },
edges: { "<slideId>/<edgeId>": { kind?, material? } }
}
Objects deep-merge; arrays replace (an effects/props list is the whole list).
Full field list: reference/ir-fields.md.
Styling with effects
deck3d fx list [--kind k] [--tag t] [--json] prints the catalogue;
reference/effects.md has params and licences.
parseassigns deterministic defaults (title→swarm, flowchart→tokens, sequence→rings, security→glyph-rain, data→data-columns).- Replace them with
overrides.slides["<id>"].effects = [{ id, params? }]. - Conflicts fail
render; mode-incompatible effects are skipped with a warning; the summedcostwarns over the quality budget (low6 /medium12 /high20).
Props (content illustrations)
deck3d props search <keywords> → candidate table (vendored first, then Poly Pizza).
You pick by relevance then style — code never picks. Then:
- Prefer one pack per deck and
restyle: "palette". deck3d props fetch <source> <id>→ prints theoverrides.props[]entry (with thesha256) and caches it in.deck3d/props/.- Add the entry to
overrides.props(roles:hero,illustration,ambient,node:<id>), thenbuild/snapshot.
Licences: CC0 needs no credits; CC-BY (and any non-CC0, non-generated) produces a
last credits slide at render. Never fetch a model whose licence you cannot name.
Forbidden edits
- Never edit
deck.html— it is regenerated; tunedeck.jsonoverrides. - Never edit derived fields (
slides[]and below) —validatewarnsedited outside overrides; the nextparseloses the change. - If you need a knob that does not exist, propose a schema field — do not hack the HTML.
Pitfalls
parseof a deck with mermaid needs chromium; missing ⇒npx playwright install chromium.render/validatenever need a browser.- Every three.js
typeface.jsonhas corruptő ű Ő Űglyphs; deck3d uses a real Poppins TTF through opentype.js — do not swap in a typeface.json. - Extruded small text blooms and is unreadable; diagram labels are flat canvas
planes with a background-colour outline. Tune
labels.size, not the material. - The mermaid engine is pinned exactly; a bump is a deliberate change and the harvest fixtures will fail if the rendered id scheme moves.
- Headless/background tabs stall
requestAnimationFrame; the loop falls back tosetTimeoutso snapshots capture a finished frame.
Contributing an effect
Development-time procedure on the package (distinct from the deck tune loop):
- Search a source; check its licence against the allow-list: MIT, Zlib, BSD-2/3-Clause, CC0-1.0, Apache-2.0, OFL-1.1. LYGIA (Prosperity) and Shadertoy content (default CC BY-NC-SA) are inspiration only — never port them verbatim.
- Port to the module interface:
create(ctx, params) → { object?, pass?, material?, tick?, dispose() }. - Write the card
src/fx/<id>.meta.json(kind, tags, cost, modes, params schema, conflicts,sourceURL,licence). deck3d fx preview <id>→ check the PNG is not black.npm run gen:effects→ regeneratereference/effects.md.npm test→ the corpus test validates every card and the catalogue hash.
Signals
- GitHub stars
- 292
- Forks
- 44
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
deck3d- Source
- github.com/blackbelttechnology/pi-agent-dashboard