Skip to content
Documenting a Tag
AutoXXS (320px)XS (375px)SM (640px)MD (768px)LG (1024px)XL (1280px)XXL (1536px)
SketchMaterialiOSTamagui
DataInjectionKeyPatternsServiceTransactionProcessResearchProductQualityPerformanceSpecDomainFunctionTechnologyArchitectureConfigMiddlewareDataDatabaseDrizzleMigrationModelop-sqliteSchemaSQLState ManagementDraftKeystoneMergePatchPatchesPersistenceReactiveRedoStoreUndoTestingDeviceFactoryIsolationTypeScriptZodTopicsCommunicationBidsNVCDesignDesign ImplicationsEducationPedagogyFoundationsPsychologyAttachmentFloodingRelatingAuthentic RelatingUIEditorReact Native

Documenting a Tag

Workflow Documenting a Tag
tags
instructionworkflow

What is a .tag.mdoc file?

Every StarSpec Markdoc tag has a corresponding reference document in instructions/tag/{tagname}.tag.mdoc. These files are compiled by the tag processor into both a public documentation page (under /starspec/tag/{tagname}) and an agent bundle. They are the single source of truth for a tag’s schema, parent/child relationships, naming rules, and usage examples.

File structure

A tag document has three layers: frontmatter, a root {% tag %} block, and an optional prose appendix outside the root tag.

1. Frontmatter

---
type: tag
id: action # bare tag name — must match the tag's id attribute
title: "{% action %}" # display title in delimiters
status: ready # draft | ready
tags: []
context: []
---
  • type is always tag.
  • id matches the tag name exactly (e.g. action, flow, requirement).
  • title uses the {% name %} convention so it renders recognisably in the sidebar and search.

2. Root {% tag %} block

The {% tag %} root declares the tag’s identity, parentage, and allowed children:

\{% tag id="action" parents="api" children="property[*] explanation[*]" %}
\{% property name="name" type="string" required=true description="..." /%}
Free-form prose describing the tag's purpose and behaviour.
\{% example id="..." summary="..." tags="..." %}
...
\{% /example %}
\{% rule id="..." force="must" tags="..." %}
...
\{% /rule %}
\{% /tag %}

id — the tag name

The bare tag name as used in Markdoc source files (e.g. action, step, policy).

parents — where this tag may appear

Space-separated list of parent tag names. An empty string means the tag is a root document tag (top-level in a .{type}.mdoc file). Examples:

parents valueMeaning
"" (empty)Root document tag — appears at top level
"api"Only valid inside \{% api %}
"blueprint domain manifest"Valid inside any of those three

children — what may appear inside

Space-separated child declarations using multiplicity notation:

NotationMeaning
name[*]Zero or more
name[+]One or more
name[?]Zero or one
name[N]Exactly N (e.g. tldr[1])

Example: children="tldr[1] explanation[*] property[*] rule[*] example[*]"

3. Inside the root {% tag %} block

The following children are recognised and rendered into the public page:

ChildPurpose
\{% property %}Declares one attribute the tag accepts. Rendered as an Attributes table.
\{% rule %}Declares a naming convention or structural constraint. Rendered as a Rules table.
\{% example %}A Markdoc usage example with summary. Rendered as an example card.
\{% explanation %}Hint or detail block. Rendered near the top of the page.
\{% tldr %}One-line summary used in sidebar, search, and agent context. Place before \{% tag %}.
Free proseParagraphs, headings, code fences — rendered as the tag’s main documentation body.

4. Optional prose appendix

Content placed after \{% /tag %} (outside the root block) is still rendered on the public page. Use this for supplementary reference tables (e.g. child tag quick-reference) that don’t belong inside the structured \{% tag %} block.

The {% property %} tag

Each attribute the tag accepts is declared with a self-closing \{% property %}:

\{% property name="id" type="string" required=true description="Unique kebab-case identifier" /%}
AttributeRequiredDescription
nameyesAttribute name as written in Markdoc
typeyesType label — string, boolean, enum, or a descriptive union like hint | details
requirednotrue or false (default: false)
descriptionnoOne-line description shown in the Attributes table

Convention: list required=true properties first, then optional ones.

The {% rule %} tag

Rules declare constraints that the compiler validates or that authors must follow:

\{% rule id="action-names-kebab-case" force="must" tags="convention naming" %}
Action names use plain kebab-case — no type prefix.
\{% /rule %}
AttributeRequiredDescription
idyesKebab-case rule id, unique within this document
forceyesmust or should — constraint strength
refnoQualified reference to a motivating spec item (e.g. manifest/product#response-time)
realmnoglobal | spec | impl — scope of the rule
tagsnoSpace-separated labels for filtering and discovery

Use force="must" for rules enforced by the compiler. Use force="should" for conventions enforced by review.

Rule id convention: {tagname}-{constraint} in kebab-case — no -tag- segment (unlike example ids). E.g. asset-no-autoplay, article-scope-public-only, cite-key-must-resolve.

The {% example %} tag

Examples show the tag in use within a realistic Markdoc snippet:

\{% example id="action-tag-with-properties" summary="Action with property children" tags="tag action" %}
\`\`\`markdoc
\{% action name="add-bookmark" %}
Saves a new bookmark to the user's library.
\{% property name="url" type="string" required=true /%}
\{% /action %}
\`\`\`
\{% /example %}

Conventions:

  • Use a markdoc language fence for the code block.
  • Include at least one realistic example per tag document.
  • Example id: use {tagname}-tag-{scenario} — the -tag- segment is required to prevent collisions with examples in domain and feature documents (e.g. action-tag-with-properties, domain-tag-basic, carousel-tag-autoplay).
  • Example tags: always start with "tag" as the first token, then the tag name(s) the example demonstrates (e.g. tags="tag action property", tags="tag carousel slide article"). This makes tag-doc examples filterable as a group in the Examples Gallery.

Agent bundle shape (optional section)

For tags whose extracted data shape is not obvious from the attributes alone, include an “Agent bundle shape” section showing the JSON structure that appears in the TOON bundle. Place this inside the \{% tag %} block, after examples and rules:

## Agent bundle shape
\`\`\`json
{
"explanations": [
{ "type": "hint", "audience": "backend", "body": "..." }
]
}
\`\`\`

This is especially valuable for container tags that collect children into arrays.

Article-type tags: {% article %} and its child tags ({% quote %}, {% atom %}, {% asset %}, etc.) produce no agent bundle — the agent pass skips all article documents entirely. Do not add an “Agent bundle shape” section to these tag docs. Instead, document the scope="public" restriction as a {% rule %} so the constraint is discoverable.

Rendered output

The tag processor renders the following sections on the public page (in order):

  1. TLDR — summary quote
  2. Explanations — any hint or detail blocks
  3. Attributes — table from \{% property %} children
  4. Valid Children — table from the children attribute, linked to each child’s tag doc page
  5. Valid Parent Contexts — links from the parents attribute
  6. Rules — table from \{% rule %} children
  7. Free prose — paragraphs and headings from the body
  8. Examples — rendered example cards
  9. Tag Tree — interactive tree view (only for root tags with empty parents)

Checklist for writing a new tag document

  1. Create instructions/tag/{tagname}.tag.mdoc
  2. Add frontmatter with type: tag, id: {tagname}, title: "{% {tagname} %}"
  3. Write a \{% tldr %} before the root \{% tag %}
  4. Add the \{% tag %} root with correct id, parents, and children
  5. Declare every attribute with \{% property %} — required attributes first
  6. Write prose explaining the tag’s purpose and key semantics
  7. Add at least one \{% example %} with a realistic markdoc fence
  8. Add \{% rule %} entries for any naming conventions or structural constraints the compiler validates
  9. If the agent bundle shape is non-obvious, add an “Agent bundle shape” section
  10. Update instructions/fragments/tags/inventory.mdoc — add the tag to the appropriate table
  11. Run pnpm compile — verify the tag doc renders at /starspec/tag/{tagname}