Files & Fragment Headers
Fragments live in .frag files, parsed and validated at build time. Prefix a filename with
_ (e.g. _draft.frag) to exclude it from the build while you work on it.
One fragment per file, and the file is named after the fragment’s id: the fragment below
belongs in childhood_stray_dog.frag. npm run validate rejects a shipped file that holds
two fragments or whose name does not match. Drafts are exempt, so an underscored file is a
fine scratchpad for as many half-written scenes as you like.
Fragment header
Section titled “Fragment header”=== childhood_stray_dogphase: childhoodtitle: The Stray Dogtags: animals, empathyrequires: VIT >= 30 && !has_petEvery fragment starts with === fragment_id. Ids are snake_case and must be unique
across all files. Header fields follow, ended by the first blank line. An unknown
header field is a build error - a typo like phse: cannot slip through.
| Field | Required | Notes |
|---|---|---|
phase: | yes | childhood · youth · early-adulthood · middle-life · maturity · late-life |
title: | yes | Shown to the player above the scene |
tags: | recommended | Comma-separated. The first tag drives selection diversity - the game avoids three same-tagged fragments in a row. No tags is a build warning. |
requires: | no | Condition for the fragment to be eligible at all. Repeatable - multiple lines AND together. |
There is no author field for you to fill in. author: exists in shipped fragments, but it
is written when a submission is accepted, from the handle you registered under, and a
submitted file containing one is refused. A name you type is a claim; a name taken from
your registration is a fact, and authorship is not something that should rest on a claim.
Comments and separators
Section titled “Comments and separators”# ...- a full-line comment, ignored by the parser. Use for TODOs and notes to other authors.# ...at the end of a line - a trailing comment, on structural lines only: choices,->,@,===and anything starting with*. It needs two or more spaces before the hash. Prose never carries one, because a hash there is content.\*- alone on a line, opens a block comment; a*\alone on a line closes it.---- an optional visual separator, also ignored. Some authors place one between setup prose and choices.
Two spaces rather than one, so that > Ask about the #1 hit keeps its hash. Nobody
aligns a comment with a single space, and everybody writes a hash mid-sentence with one.
A block comment hides everything between the fences from the parser, so a commented-out
choice does not count as a choice and a commented-out *endif closes nothing. It works
anywhere: above the first fragment, between fragments, inside a header, inside a choice
body, inside an *if block.
\*Kevin's whole arc needs rethinking. Parking the old versionhere until youth has more fragments to hang it on.*\Each fence needs its own line: \* a short note *\ is refused rather than printed, and a
*\ with nothing above it is refused too. Leaving a block open is a build error that names
the line it opened on. A prose line starting with * still escapes the usual way, as
\*text - only a bare \* reads as a fence.
Whitespace
Section titled “Whitespace”Indentation is purely cosmetic, everywhere. Nesting comes from markers (> vs >>,
*if…*endif, @), never from spacing. Indent however reads best to you.
If a prose line genuinely needs to start with a keyword (*if, *endif, *set: …),
escape it with a leading backslash:
\if only you had known.