I'm writing a fiction series on the side — four books, a fairly elaborate setting, the usual problem of keeping it all straight. The first version of my "canon" was a wiki: pages and pages of facts. Names, places, magic rules, organizations. It rotted in the way wikis rot. Two facts on different pages contradicted each other. A third page assumed a rule that had been quietly retired. Drafting a new chapter meant ten minutes of grep before I could write a sentence.

The version I use now looks much more like a small relational system than a wiki. Two markdown files do most of the work — one defining a generative pipeline, one defining the lookup tables it draws from — plus a handful of per-volume blueprints and a JSON schema validator for narrative structure. The total is under two thousand lines. It carries an entire fictional world without needing a search bar.

The pipeline, not the encyclopedia

The core insight is the one any database person would find obvious: don't store facts that can be derived. The canon defines seven layers, each of which filters the next.

cosmology → world → society → infrastructure → life → objects → narrative

Cosmology produces magic and moons. The world layer adds geography and the magical substrate. Society produces states, cultures, institutions, factions. Infrastructure produces materials, transport, communication, medicine. Life is the ecology. Objects fall out of the cascade. Narrative obeys a small set of structural invariants.

The constraint that does the actual work: nothing in a lower layer may contradict a higher one. If the cosmology says there are five moons with named emotional baselines, the society layer cannot invent a sixth moon. If a faction maps to two moons, those two moons must exist. The pipeline is not a description of the world; it is a constraint system that the world has to satisfy.

Normalized data tables

Everything enumerable lives in a single data module — moons, schools of magic, tiers of practice, institutions, factions, ethnicities, biomes, materials, transport systems, military unit types, contamination grades. Every row has a stable ID.

| id            | name      | emotional_baseline       |
|---------------|-----------|--------------------------|
| moon_velquor  | Velquor   | analytical detachment    |
| moon_namaris  | Namaris   | aggression tolerance     |
| moon_orrivane | Orrivane  | emotional contagion      |
| moon_saelura  | Saelura   | ritual stabilization     |
| moon_threnis  | Threnis   | relational sensitivity   |

Other tables reference these IDs. A faction row points at one or more moon_* IDs. A character points at a faction. Renaming a moon is a single edit at the source; every reference inherits the change. This is not a feature so much as the absence of a problem — the wiki version had four spellings of one moon name across six pages, and I only noticed because a beta reader emailed me about it.

Object generation as a cascade

The reason I stopped writing object descriptions by hand was the realization that almost every object in a scene is a function of where the scene is set. A toy on a windowsill in a frontier mining town under a particular moon, owned by a household at a particular wealth tier, in a particular cultural tradition — that object is almost determined before I describe it.

So objects are generated by passing a base noun through a fixed cascade of filters: moon, biome, state, culture, faction, institution, wealth tier, ethnicity, material. The filters refine progressively. The output is a sentence or two of prose that fits the scene by construction.

base:        toy soldier
moon:        Threnis (relational sensitivity)
state:       Chizhou
culture:     frontier mining
institution: Crown garrison
faction:     Militarist
wealth:      peripheral
material:    lacquered wood

result:      a chipped lacquer toy soldier with red paint
             worn smooth by small hands

This works because the filters are doing what filters should do — narrowing a search space. The cascade is deterministic enough to be repeatable and loose enough to leave room for prose.

The Volume Blueprint as a per-book artifact

A book-length project needs more than the pipeline. The canon describes what is true. A given book describes what happens — in what order, through whose perception, at what pace. That is the job of a Volume Blueprint.

Each book gets one. It is a structured document with seven required sections: series position (state handoff from the prior book), vocal signatures (how each POV sounds in this book), chapter map, chapter-by-chapter entries, trajectories, drafting rules, cross-volume notes. The Blueprint is the bridge from the abstract canon to actual prose.

The Blueprint is generated in a fixed order: spine first, trajectories assigned, POVs rotated across chapters, word targets distributed, scenes drafted at entry level, vocal signatures refined, validated. Every step depends on the previous one. Skipping a step produces a Blueprint that the validator will reject.

Monotonic trajectories

This is the part of the system that earns its weight. Across a book, certain numeric quantities trend in one direction — death count, operational delay, physiological gap, substrate thinning. Each trajectory is a small table mapping chapter numbers to values. The rule is simple: numbers do not reverse within a volume unless transformation has been achieved.

trajectory: death_count
direction:  ascending
chapters:   1:  97
            7:  99
            14: 101
            22: 103
terminal:   triage classification becomes
            lethal under node surge

The validator checks this. If chapter 18 mentions the count went from 102 to 100, the validator flags it. The number doing the emotional work is the same number doing the structural work, and it cannot drift without somebody noticing.

The non-numeric trajectories use the same shape with descriptive states instead of values — a scar that hurts, then stops hurting, then becomes warm. The progression is monotonic in register even when it is not numeric. The table format is the same.

The validator

The story spine for each book is a JSON document validated against a schema. The schema enforces that every spine has a beat sequence, a cast, declared trajectories, an uncontrollable event per beat, and a documented cost structure. Beats must escalate. Costs must persist. Resolution must be partial. The validator is a couple hundred lines and catches roughly nine of every ten structural mistakes I would otherwise make in a draft.

What it does not catch is whether the prose is any good. That is still my job, and I have not figured out how to delegate it.

What I deliberately don't build

  • A character database. Characters are written in prose at the chapter level and only their canonical attributes — affiliation, magic school, ethnicity — point at IDs in the data tables. There is no characters collection with rows. The temptation to build one fades the moment you realize you would still write the prose by hand.
  • A timeline graph. Cross-book continuity lives in the Volume Blueprint's "series position" section. A graph would be more impressive and less useful, because the questions I ask of continuity are local — what was true at the end of book two — not global.
  • A canonical map. The geography is described in prose at the locations it appears. A frozen map would freeze decisions I might want to keep loose.

Why this works for fiction in particular

The pipeline is small because fiction does not need exhaustive coverage. It needs consistent coverage of the things the prose actually touches. The wiki version failed because it tried to document everything, including the regions I never wrote about. The pipeline succeeds because it generates only what the current scene asks for, from rules that fit on a few pages.

The unexpected payoff is that the constraints have made me a better drafter. A scene that cannot be filled in from the pipeline is a scene I have not thought through. The pipeline rejecting an object is more useful than the pipeline producing one — it tells me the layer above is missing something I did not know I needed.

The smallest canon that the work does not contradict is the right size. Anything larger is a wiki, and a wiki is the absence of a system.