Files
ttrpg-tools/.agents/skills/tttk-authoring/SKILL.md
T
hyper 322287da29 docs(reference): cover bare dice and tilde fences
Add the bare d-form (d20) to the dice notation table, and note that role fences accept backticks or tildes with hyphen-capable attribute keys. Regenerate both reference copies from known.ts and mirror the notes in the skill and markdown docs.
2026-09-12 23:56:12 +08:00

6.7 KiB

name, description
name description
tttk-authoring Author and edit TTRPG game design documents for the tttk (Tabletop Toolkit) CLI. Use when writing or modifying markdown content that uses tttk custom elements (:md-dice, :md-table, :md-deck, :md-pins, etc.), custom fenced code blocks (role=spark-table / declare / file / tag), companion CSV data files, or when previewing content with `tttk serve` and validating it with `tttk check`.

Authoring tttk game design documents

tttk (Tabletop Toolkit) renders a folder of markdown into an interactive TTRPG web app. A game design document is ordinary GFM markdown plus exactly two extensions:

  1. Custom elements written with marked-directive syntax: :name[content]{attrs}.
  2. Custom fenced code blocks whose info string carries a role= attribute.

Everything else — headings, lists, tables, blockquotes, alerts, mermaid — is standard markdown. Do not invent element names, props, or roles; check reference.md when unsure. Deeper topics have their own files: yaml-tag.md (deck config), csv.md (data files), layout.md (columns), and markdown.md (alerts and mermaid).

Workflow

  • Content lives in a directory (commonly content/). Preview with hot reload: npx tttk serve ./content (default port 3000, override with -p 8080).
  • Validate after every edit: npx tttk check ./content. It exits 1 when there are errors and prints file:line diagnostics. Use --json for machine-readable output and --quiet for errors only. This is the primary verification loop: write → check → fix.
  • The scanner picks up .md, .csv, .yarn, and .svg files.
  • All paths in directives are relative to the current markdown file (./data.csv, ../shared/npcs.csv, ./images/map.png).
  • A typical game/adventure folder:
    my-adventure/
    ├── design.md        # design notes (plain markdown)
    ├── adventure.md     # the document players/GM read
    ├── locations.csv    # data referenced by :md-table
    ├── cast.csv
    └── route.csv
    

Directive syntax

:name[content]{key="value" .class #id}
  • [content] is the directive body — a path, dice formula, color, etc.
  • {key="value"} sets attributes. {.class} and {#id} are shorthands.
  • Container directives use ::: name … :::; nest deeper with ::::, :::::.

Use the registered element names: :md-dice, not :dice. The full list is in reference.md.

Code block roles

Fenced blocks are dispatched by the role= attribute in the info string. Both backtick and tilde (~~~) fences work; the closing fence must reuse the opening marker, and fence attribute keys may contain hyphens (e.g. data-foo=bar):

Info string Behavior
```csv role=spark-table Body is CSV; replaced with :md-table[./csv_<hash>]. First column header must be a dice formula (d6, 2d6+1, …).
```markdown role=spark-table Body is a GFM pipe table; converted to CSV, then same as above.
```yaml role=declare YAML vars: / tags: maps defining reactive variables and tag modifiers. Block is stripped.
```<lang> role=file Body stored as text content, block stripped, referenced by its derived id.
```yaml role=tag Kept intact; rendered as a custom element from YAML (tag:, body:, …).
```<lang> (no role) Rendered as a normal visible code block.
unknown role Warned about and stripped.

Rules that prevent broken output

  • Quote any attribute value containing spaces or ": {pins="A:30,40 B:10,30"}.
  • In CSV, wrap fields containing ,, ", or a newline in double quotes and escape " as "". Lines starting with # are comments.
  • label and body are the conventional CSV columns. Put titles inside body as markdown headings; use bold labels for sub-fields, not headings.
  • A group column in a table CSV automatically produces group tabs — no attribute needed.
  • Reference each CSV once per document; don't repeat the same :md-table.
  • For card decks, use the yaml role=tag form with tag: md-deck (see yaml-tag.md). The :md-deck[...]{...} directive is legacy and can't express template layers or card backs.
  • Keep CSV files clean — header row plus data. Put deck config and templates in the YAML block's data-config, not in CSV front matter (see csv.md).
  • {{prop}} in a CSV body interpolates another column (or front-matter key) from the same row; with {remix} it pulls from a random row instead.

Validation

npx tttk check ./content validates against the same content registry the app uses, so a clean check means the app resolves the content too. Errors exit 1:

Code Meaning
TTTK-S002 container directive ::: never closed
TTTK-D001 unknown :md-* element name
TTTK-D002 malformed attribute block (e.g. an unquoted value with a space)
TTTK-R001 unknown code-block role= (the block is silently dropped)
TTTK-R003 role=declare failed to parse
TTTK-R005 role=tag YAML is invalid
TTTK-R006 role=tag missing or naming an unknown element
TTTK-C001 content reference does not resolve
TTTK-C004 :md-embed cycle
TTTK-L001 link target file does not exist
TTTK-V001 CSV failed to parse (e.g. an unclosed quote)

Warnings are usually real too:

Code Meaning
TTTK-R002 spark-table first header is not a dice formula
TTTK-R004 role=declare block declares nothing
TTTK-C002 reference resolves to an unexpected file type
TTTK-L002 #section matches no heading
TTTK-A001 icon missing under assets/
TTTK-A002 image missing
TTTK-V002 CSV row column count differs from the header
TTTK-V003 duplicate label values
TTTK-V004 {{prop}} is not a CSV column or front-matter key
TTTK-V005 spark-table roll value is not a number or range

TTTK-C003 (info) flags the same CSV referenced twice by :md-table in one document. Icon checks assume no assets/ directory exists above the checked directory. The full code catalog lives in reference.md.

Reference

  • reference.md — generated catalog of every custom element, inline directive, code block role, and dice notation. Do not edit by hand; regenerate from the repo with npm run gen:skill-reference.
  • yaml-tag.md — role=tag blocks, data-config layers, card backs, and the legacy :md-deck layer syntax.
  • csv.md — CSV authoring: columns, {{prop}} interpolation, quoting, and the discouraged front-matter form.
  • layout.md — column layout markers.
  • markdown.md — GitHub alerts and mermaid diagrams.
  • examples/adventure.md and examples/encounters.csv — a complete minimal document and its data file.