Files
ttrpg-tools/.agents/skills/tttk-authoring/SKILL.md
T
hyper ae36125af0 docs(skill): add rules-writing conventions
Add rules.md covering document structure, theme/players/time header, icon-first mentions, veteran-first prose, and a closing timestamp. Link it from SKILL.md.
2026-10-24 16:51:59 +08:00

7.2 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-print, :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.
  • To print a rules document, use :md-print[./rules.md] (or the yaml role=tag form). It paginates into A4 landscape sheets holding two A5 pages, each with columns columns (default 2). See reference.md for the attributes and rules.md for how to write the rules text itself.
  • 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.
  • rules.md — conventions for writing rules documents: the five-part structure, the theme/players/time header, icon-first mentions, veteran-first prose with details boxed in alerts, and a timestamp.
  • markdown.md — GitHub alerts and mermaid diagrams.
  • examples/adventure.md and examples/encounters.csv — a complete minimal document and its data file.