🌍 ChapterWise Codex Format V1.3
The ChapterWise Codex Format is a perfectly recursive specification designed for complex storytelling projects, universe-scale world-building, and cross-media narratives. Every part of a codex can become its own standalone file, creating a beautiful fractal structure where the same format works at every level.
Version: 1.3 — Content width system and spreadsheet integration Status: Stable Date: January 2025
Table of Contents
- Introduction
- Design Philosophy
- File Formats
- Analysis Files
- Basic Structure
- Metadata Object
- Node Fields
- Content Structures
- Spreadsheet Content Type
- Attributes Array
- Relations Array
- Children Array
- Include Directives
- Media Handling
- Tagging System
- Complete Examples
- Best Practices
- Working with Git Projects
- Migration from Legacy Formats
- Validation
- JSON Format Examples
- Technical Specification
Introduction
Purpose
The ChapterWise Codex Format provides a unified structure for representing complex storytelling content, from individual characters to entire fictional universes. The key innovation of V1.0 is perfect recursion — any slice of a codex can become its own standalone file.
Key Features
- Perfect Recursion: Identical structure at all hierarchy levels
- No Data Wrapper: Content lives directly at root level
- Metadata Consolidation: All format information in one object
- Include Support: Compose files from multiple sources
- Maximum Flexibility: Only one required field (
metadata.formatVersion) - Media-Aware: Built-in support for images and rich media
Design Philosophy
Perfect Recursion
The defining feature of V1.0 is perfect recursion: any slice of a codex can become a standalone codex file. There's no special "wrapper" or "envelope" — just nodes all the way down. A character's skill can use the same format as the entire universe.
Core Principles
- Identical structure everywhere — Root, child, grandchild all use the same keys
- No data wrapper — Content lives directly at root level
- Metadata consolidation — All format info in one
metadataobject - Include directives — Embed external files at any level
- Maximum flexibility — Only
metadata.formatVersionis required - Media-aware — Built-in support for images, galleries, and rich media
Fractal Beauty
Universe (codex)
├── Epoch (codex)
│ ├── Book (codex)
│ │ ├── Chapter (codex)
│ │ └── Character (codex)
│ │ ├── Arc (codex)
│ │ └── Skill (codex)
Each node is a full codex — you can extract any piece and it's a valid standalone file.
Design Goals
- Simplicity: Minimize required fields, maximize flexibility
- Composability: Enable file inclusion and modular design
- Extensibility: Support arbitrary attributes and relations
- Human-Friendly: Optimize for YAML readability
- Machine-Parseable: Clean JSON representation
File Formats
YAML Format (Recommended)
.codex.yaml or .codex files are the preferred format:
- ✅ Human-readable and editable
- ✅ Native multiline text blocks (
|and>) - ✅ Comments for documentation (
#) - ✅ Natural list and object syntax
- ✅ Better version control diffs
- ✅ Markdown-friendly content
JSON Format
.codex.json files are supported for:
- API integration and programmatic access
- Legacy system compatibility
- Machine processing pipelines
- High-performance parsing
YAML and JSON are semantically equivalent. Parsers support both formats and allow conversion between them.
File Extensions
- YAML:
.codex.yaml,.codex,.yaml - JSON:
.codex.json,.json
Character Encoding
- UTF-8 encoding required
- BOM (Byte Order Mark) optional
- Line endings: LF (
\n) recommended, CRLF (\r\n) acceptable
Analysis Files
Analysis results are stored in sibling files using JSON format for fast parsing:
| Source File | Analysis File |
|---|---|
story.codex.yaml |
story.analysis.json |
chapters/ch1.codex.md |
chapters/ch1.analysis.json |
Analysis files use JSON (not YAML) for 5-30x faster parsing, but follow the same codex structure with metadata, children, attributes, and body fields.
For full details, see Analysis Files.
Basic Structure
Minimal Codex
The absolute minimum codex file:
metadata:
formatVersion: "1.0"
That's it! Everything else is optional.
Simple Character
metadata:
formatVersion: "1.0"
documentVersion: "1.0.0"
created: "2025-10-25T12:00:00Z"
author: "Author Name"
id: "char-livia-uuid"
type: character
name: "Livia Mercuria"
summary: "Roman noblewoman turned rebel leader"
Character with Background
metadata:
formatVersion: "1.0"
documentVersion: "1.2.0"
author: "Author Name"
license: "CC BY-SA 4.0"
id: "char-livia-uuid"
type: character
name: "Livia Mercuria"
summary: "Roman noblewoman turned rebel leader"
body: |
Born into privilege in 75 BCE, Livia discovered her past-life
memories at age sixteen. Her awakening sparked a transformation
that would shake the foundations of the Roman Republic.
attributes:
- key: house
name: "Noble House"
value: "Mercuria"
- key: strength
name: "Strength"
value: 18
dataType: int
tags:
- protagonist
- roman-era
- awakened
No Data Wrapper
Unlike legacy formats, V1.0 has no data wrapper. Content lives directly at the root level:
# ❌ Legacy format (NOT V1.0)
data:
id: "uuid"
name: "Character"
# ✅ V1.0 format
id: "uuid"
name: "Character"
Metadata Object
The metadata object consolidates all format and document information. It MUST appear at the root level of every codex file.
Required Field
formatVersion—string(REQUIRED) Must be"1.3"for this specification (V1.0, V1.1, and V1.2 are also supported for backwards compatibility)
metadata:
formatVersion: "1.3" # ✅ Correct (latest)
formatVersion: "1.2" # ✅ Also valid (backwards compatible)
formatVersion: "1.1" # ✅ Also valid (backwards compatible)
formatVersion: "1.0" # ✅ Also valid (backwards compatible)
formatVersion: 1.3 # ❌ Wrong (must be string)
formatVersion: "1" # ❌ Wrong (must be "1.0", "1.1", "1.2", or "1.3")
Optional Fields
-
documentVersion—stringSemantic version of this document (e.g.,"1.2.3") -
created—stringISO-8601 timestamp of creation (e.g.,"2025-10-25T15:30:00Z") -
updated—stringISO-8601 timestamp of last update -
author—stringorarrayAuthor name(s) — can be a single string or array of strings -
license—stringLicense identifier (e.g.,"CC BY-SA 4.0","All Rights Reserved") -
tags—arrayDocument-level tags for organization -
iconset—stringIcon library to use:"phosphor","fontawesome", or"lucide"
Example Metadata
Minimal:
metadata:
formatVersion: "1.2"
Full:
metadata:
formatVersion: "1.2"
documentVersion: "2.1.0"
created: "2025-01-15T00:00:00Z"
updated: "2025-11-30T00:00:00Z"
author: "Anson Phong"
license: "CC BY-SA 4.0"
tags:
- 11-lives
- epoch-02
- canon
iconset: "phosphor"
Multiple Authors:
metadata:
formatVersion: "1.2"
author:
- "Author One"
- "Author Two"
- "Editor Name"
Node Fields
All these fields are optional and can appear at any level (root, child, grandchild):
Identity
id—string— Unique identifier (UUID v4 recommended)type—string— Node type classification (e.g.,"character","location","chapter")name—string— Primary name/identifiertitle—string— Display title (optional alternative to name)key—string— Human-readable slug for cross-references
Content
summary—string— Brief description or taglinebody—string— Main content body (supports markdown)content—array— Structured content objects (see below)
Organization
tags—array— Node-level tags for cross-referencingattributes—array— Key-value metadata pairsrelations—array— Links to other nodeschildren—array— Child nodes (RECURSIVE!)
Publishing
status—string— Publishing status:"private","draft","finished", or"published"(default:"private")featured—boolean— Highlight this node in Featured sections (default:false)
Media
image—string— Primary image URLimages—array— Image galleryexternal_url—string— External reference URLanimation_url—string— Animation/video URL
Presentation
display—object— Visual presentation settings (see Display Settings)
Display Settings
The display field controls visual presentation at any hierarchy level. Settings automatically cascade to all descendants, and children can override parent settings.
Fields
breadcrumb—boolean— Show parent breadcrumb in title (default:true)icon—boolean— Show type icon (default:true)type—boolean— Show type badge (default:true)
Inheritance
Display settings cascade automatically to all descendants (children, grandchildren, etc.). Child settings override parent settings for that specific property.
Examples
Hide breadcrumb for a list and all its children:
id: shot-list
type: shot-list
name: Shot List
display:
breadcrumb: false
children:
- id: core-anchors
type: shot-category
name: Core Anchors
# Inherits: breadcrumb=false, icon=true, type=true
- id: work-beats
type: shot-category
name: Work Beats
# Inherits: breadcrumb=false, icon=true, type=true
Override specific settings in a child:
id: parent-section
type: section
name: Parent Section
display:
breadcrumb: false
icon: true
type: false
children:
- id: child-section
type: section
name: Child Section
# Inherits: breadcrumb=false, type=false
# But overrides icon
display:
icon: false
# Final: breadcrumb=false, icon=false, type=false
Clean list presentation:
id: checklist
type: checklist
name: Pre-Flight Checklist
display:
icon: false
type: false
breadcrumb: false
children:
- id: item-1
type: checklist-item
name: Check fuel levels
# All display elements hidden by inheritance
Publishing Settings
The status and featured fields control how codex nodes appear in Git project views and public-facing pages.
Status Field
Controls visibility of the node in public views:
| Value | Description |
|---|---|
private |
Default. Only visible to project owner in Files view |
draft |
Work in progress. Same as private but indicates active editing |
finished |
Complete and locked for release; still private until published |
published |
Publicly visible. Appears in Published view for all users |
Important: Status defaults to private. You must explicitly set status: published for content to appear in public views.
Featured Field
A boolean flag that highlights important nodes:
featured: true— Node appears prominently in Featured sectionsfeatured: false— Normal display (default)
Featured items display with rich cards (thumbnail, summary, word count, last updated).
Examples
Published character (public):
metadata:
formatVersion: "1.2"
id: "char-hero-uuid"
type: character
name: "The Hero"
summary: "A legendary warrior destined for greatness"
status: published # Visible to everyone
featured: true # Highlighted in Featured section
body: |
The hero's journey began...
Draft chapter (private, work in progress):
metadata:
formatVersion: "1.2"
id: "chapter-03-uuid"
type: chapter
name: "Chapter 3: The Revelation"
status: draft # Only owner sees this
featured: false
body: |
[Work in progress - not ready for publication]
Private notes (never public):
metadata:
formatVersion: "1.2"
id: "notes-plot-uuid"
type: notes
name: "Plot Notes"
status: private # Always hidden from public
body: |
Secret plot twists that readers shouldn't see...
Inheritance
Unlike display settings, status does NOT inherit to children. Each node must explicitly set its own status. This prevents accidentally publishing private child content.
id: world-uuid
type: world
name: "My World"
status: published # World is public
children:
- id: char-public
type: character
name: "Public Hero"
status: published # Must explicitly set - doesn't inherit
- id: char-secret
type: character
name: "Secret Villain"
# status not set = defaults to private (not visible publicly)
Viewing Published Content
When you connect a Git repository to ChapterWise, your project page has two views:
Published Tab (default for visitors):
- Shows only codex files with status: published
- Displays content in a visual masonry grid layout
- Featured items (featured: true) appear at the top with rich cards showing thumbnails, summaries, and word counts
- Regular published items appear as compact cards
- Sorted by most recently updated (based on Git commits)
Files Tab (for project owners): - Shows the complete file tree of your repository - Private and draft items are visible but marked with a badge - Full access to all files regardless of status
Who sees what:
| Viewer | Published Tab | Files Tab |
|---|---|---|
| Project owner | All published items | All files (private items marked) |
| Logged-in user | Published items only | Published items only |
| Anonymous visitor | Published items only | Published items only |
How Publishing Works
- Add
status: publishedto any codex file you want to share publicly - Commit and push your changes to GitHub
- Sync your project in ChapterWise (automatic via webhook or manual sync button)
- ChapterWise scans all codex files and caches published items
- Published content appears in the Published tab immediately
Tip: Use featured: true on your most important content to highlight it at the top of the Published view with rich cards that include thumbnails and summaries.
Content Structures
The Body Field
The body field is a markdown-formatted text block that can appear at any hierarchy level. It's rendered prominently and supports full markdown formatting.
Usage
id: "char-aya-uuid"
type: character
name: "Aya"
summary: "Atlantean priestess with prophetic sight"
body: |
# Background
Born under the constellation of the Eternal Flame, Aya was marked
from birth with the silver crescent upon her brow—a sign recognized
by the Druids as divine blessing.
## The Awakening
At sixteen, during the ritual of Temporal Resonance, Aya alone
remained conscious as the Great Pyramid's crystal matrix overloaded.
The experience granted her **temporal sight**—the ability to perceive
probability streams.
### Key Relationships
- **Thoth**: Her mentor who concealed her true parentage
- **Marcus**: Her companion across lifetimes
- **The Council**: Those who fear her power
Rendering
The body field is rendered:
* Below summary and attributes
* Above content sections and children
* With full markdown support (headers, lists, bold, italic, links, code, blockquotes)
* Using consistent typography across all levels
The Content Array
For structured content (like screenplay beats or game moves), use the content array:
id: "beat-pyramid-meltdown-uuid"
type: beat
name: "The Pyramid Meltdown"
content:
- key: visual
name: "Visual"
value: |
The crystal matrix begins to glow with unstable light.
Aya stands at the center, her silver crescent blazing.
- key: narration
name: "Narration"
value: |
As the others fall unconscious, Aya alone sees the threads
of time itself—past and future converging in this moment.
- key: audio
name: "Audio"
value: "Resonant crystal tones building to crescendo"
- key: duration
name: "Duration"
value: "02:30"
Content Item Fields
Each content item can have:
* key — Machine-readable identifier (required)
* name — Display label (optional)
* value — Content (string, supports multiline with |) (required for text types)
* type — Content type: text (default), blockquote, spreadsheet, diagram
* width — Layout width: 1/1 (full), 1/2 (half), 1/3 (third). Default: 1/2
* id — Optional unique ID
* include — File path for external content (CSV, spreadsheet.yaml, .mermaid, .mmd)
Width System
The width field controls how content items flow in the layout using flexbox:
| Value | Description | Behavior |
|---|---|---|
1/1 |
Full width | Takes entire row |
1/2 |
Half width (default) | Two items per row |
1/3 |
Third width | Three items per row |
Items flow left-to-right and wrap to new rows. YAML order is preserved:
content:
- key: hero-image
type: image
width: 1/1 # Full width - own row
value: /images/hero.jpg
- key: visual
width: 1/2 # Half width - left side
value: |
Scene opens with...
- key: audio
width: 1/2 # Half width - right side
value: |
Ambient forest sounds...
- key: note-a
width: 1/3 # Third width
value: "First note"
- key: note-b
width: 1/3 # Third width
value: "Second note"
- key: note-c
width: 1/3 # Third width - completes row
value: "Third note"
Spreadsheet Content Type
The spreadsheet content type renders interactive data tables with formula support using Jspreadsheet CE.
Basic Usage
Inline CSV:
content:
- key: budget
name: "Production Budget"
type: spreadsheet
width: 1/1
value: |
Category,Budget,Spent,Remaining
Talent,50000,12000,=B2-C2
Equipment,25000,8000,=B3-C3
Post,15000,0,=B4-C4
External CSV file (via include):
content:
- key: budget
type: spreadsheet
width: 1/1
include: /data/budget.csv
Excel file (converted automatically):
content:
- key: budget
type: spreadsheet
width: 1/1
include: /data/budget.xlsx
Self-contained spreadsheet with config:
content:
- key: budget
type: spreadsheet
width: 1/1
include: /data/budget.spreadsheet.yaml
Formula Syntax
Formulas use standard Excel-style cell references for maximum compatibility:
| Formula | Description |
|---|---|
=A1+B1 |
Add two cells |
=B2-C2 |
Subtract cells |
=SUM(B2:B10) |
Sum a range |
=AVERAGE(C2:C10) |
Average a range |
=IF(A1>0,"Yes","No") |
Conditional |
=A1*1.1 |
Multiply by constant |
Supported functions: SUM, AVERAGE, MIN, MAX, COUNT, IF, AND, OR, NOT, CONCATENATE, UPPER, LOWER, ROUND, ABS, and more.
Auto-Detection Rules
When loading spreadsheet content:
- If
valueexists → Parse as inline CSV - If
includeends with.spreadsheet.yaml→ Load as self-contained spreadsheet - If
includeends with.xlsx→ Convert Excel to CSV via openpyxl - If
includeends with.csv→ Load as plain CSV data - If
includeis other path → Attempt to load as CSV
Data Format Comparison
| Format | Formulas | Column Config | Styling | Best For |
|---|---|---|---|---|
| Inline CSV | ✅ | ❌ | ❌ | Quick data tables |
| External .csv | ✅ | ❌ | ❌ | Existing CSV files |
| .xlsx (Excel) | Values only | ❌ | ❌ | Importing existing Excel files |
| .spreadsheet.yaml | ✅ | ✅ | ✅ | Full control |
Diagram Content Type
The diagram content type renders visual diagrams using Mermaid.js — an open-source library supporting 23 diagram types including flowcharts, sequence diagrams, ER diagrams, Gantt charts, and more.
Basic Usage
Inline Mermaid syntax:
content:
- key: system-flow
name: "System Architecture"
type: diagram
width: 1/1
value: |
graph LR
A[Upload] --> B[Parse]
B --> C[Analyze]
C --> D[Render]
External .mermaid file (via include):
content:
- key: er-diagram
name: "Database Schema"
type: diagram
width: 1/1
include: /diagrams/schema.mermaid
Standalone diagram node (entire node is a diagram):
name: "Release Timeline"
type: diagram
body: |
gantt
title Release Schedule
dateFormat YYYY-MM-DD
section Phase 1
Design :a1, 2026-01-01, 30d
Build :a2, after a1, 45d
Supported Diagram Types
| Type | Mermaid Keyword | Description |
|---|---|---|
| Flowchart | graph / flowchart |
Process flows and decision trees |
| Sequence | sequenceDiagram |
Interaction between actors |
| Class | classDiagram |
OOP class relationships |
| State | stateDiagram-v2 |
State machines |
| ER Diagram | erDiagram |
Entity relationships |
| Gantt | gantt |
Project timelines |
| Pie Chart | pie |
Proportional data |
| Git Graph | gitGraph |
Branch and commit visualization |
| Mindmap | mindmap |
Hierarchical idea maps |
| Timeline | timeline |
Chronological events |
| User Journey | journey |
User experience flows |
| Sankey | sankey-beta |
Flow quantities |
| XY Chart | xychart-beta |
Bar and line charts |
File Formats
| Extension | Description |
|---|---|
.mermaid |
Standard Mermaid diagram file |
.mmd |
Short Mermaid file extension |
Include Behavior
When loading diagram content:
- If
valueexists → Use as inline Mermaid source - If
includeends with.mermaidor.mmd→ Load as diagram source - The loaded content is stored in
_diagram_dataand rendered client-side
Dark Mode
Diagrams automatically switch between Mermaid's default and dark themes when the page theme changes. No configuration needed.
Body Shortcodes
The body field supports embedding diagrams and spreadsheets inline with prose using standard markdown syntax.
Fenced Block Syntax
Use fenced code blocks with special language hints:
body: |
Here's the architecture:
```mermaid
graph LR
A[Upload] --> B[Parse] --> C[Render]
```
And the budget:
```spreadsheet
Item,Cost
Camera,5000
Lens,2000
```
Supported language hints: mermaid (diagrams), spreadsheet and csv (interactive tables). All other language hints (e.g., python, yaml) render as syntax-highlighted code blocks as usual.
Image-Style File Includes
Reference external files using markdown image syntax:
body: |



File extension determines rendering: .mermaid/.mmd → diagram, .csv/.xlsx → spreadsheet, .jpg/.png/etc. → normal image.
See the Body Shortcodes documentation for complete details.
Attributes Array
Attributes store key-value metadata. They're flexible and extensible:
attributes:
- key: house
name: "Noble House"
value: "Mercuria"
- key: strength
name: "Strength"
value: 18
dataType: int
- key: special_abilities
name: "Special Abilities"
value:
- temporal-sight
- empathic-healing
- dream-walking
dataType: array
- key: soul_archetype
name: "Soul Archetype"
value: "Aya-Prime"
tags:
- core-identity
- reincarnation
Attribute Fields
key—string(required) — Machine-readable identifiername—string— Human-readable labelvalue—any(required) — The actual value (string, number, boolean, array, object)dataType—string— Type hint:"int","float","boolean","array","date","url","markdown", etc.tags—array— Classification tags for this attribute
Data Types
Common dataType values:
int— Integer numberfloat— Decimal numberboolean— True/false valuestring— Text stringarray— List of valuesobject— Complex objectdate— ISO-8601 date/timestampurl— Web URLmarkdown— Markdown-formatted text
Relations Array
Relations create graph connections between nodes:
relations:
- targetId: "char-aya-epoch01-uuid"
kind: "reincarnation-of"
strength: 0.95
attributes:
- key: soul_continuity
name: "Soul Continuity"
value: 0.95
- key: memory_retention
name: "Memory Retention"
value: 0.2
- targetId: "char-marcus-uuid"
kind: "loves"
strength: 1.0
reciprocal: true
Relation Fields
targetId—string(required) — UUID of target nodetargetKey—string— Human-readable key of targetkind—string(required) — Relationship typestrength—number— Intensity (0.0 to 1.0)reciprocal—boolean— Whether to create reverse relationattributes—array— Metadata about this specific relationship
Common Relation Kinds
Hierarchical:
* parent / child
* contains / contained-by
* part-of / has-part
Narrative:
* ally / enemy
* loves / loved-by
* mentors / student-of
* reincarnation-of / reincarnates-as
Temporal:
* precedes / follows
* causes / caused-by
* concurrent-with
Cross-Media:
* appears-in
* referenced-in
* variant-of
Reverse Relations
When reciprocal: true, the system creates the inverse relation automatically:
# Node A
relations:
- targetId: "node-b-uuid"
kind: "loves"
reciprocal: true
# System automatically creates in Node B:
# relations:
# - targetId: "node-a-uuid"
# kind: "loved-by"
Children Array
Children create the recursive hierarchy — the heart of V1.0:
id: "universe-atlantis-uuid"
type: universe
name: "Atlantis Chronicles"
children:
- id: "epoch-01-uuid"
type: epoch
name: "Epoch 01: Atlantis"
summary: "The golden age before the flood"
children:
- id: "char-aya-uuid"
type: character
name: "Aya"
summary: "Atlantean priestess"
children:
- id: "arc-awakening-uuid"
type: arc
name: "The Awakening"
children:
- id: "beat-pyramid-uuid"
type: beat
name: "Pyramid Meltdown"
Each child uses the exact same structure — that's the beauty of perfect recursion!
Standalone Children
Any child can have its own metadata and become a standalone codex:
children:
- metadata:
formatVersion: "1.0"
documentVersion: "1.0.0"
author: "Different Author"
id: "skill-uuid"
type: skill
name: "Blade Dance"
Order Preservation
The order of children is significant and preserved:
children:
- type: preface
name: "Preface" # Position 0
- type: chapter
name: "Chapter 1" # Position 1
- type: chapter
name: "Chapter 2" # Position 2
- type: epilogue
name: "Epilogue" # Position 3
Include Directives
The include field lets you embed external codex files with full or selective content inclusion.
Simple Include (Full Content)
Include the entire file using string syntax (backwards compatible):
id: "party-main-uuid"
type: group
name: "The Adventuring Party"
children:
- include: "/Characters/Aya.codex.yaml"
- include: "/Characters/Marcus.codex.yaml"
- include: "/Characters/Thoth.codex.yaml"
Referenced file (/Characters/Aya.codex.yaml):
metadata:
formatVersion: "1.1"
id: "char-aya-uuid"
type: character
name: "Aya"
summary: "Atlantean priestess with prophetic sight"
body: |
Born under the constellation of the Eternal Flame...
When parsed, the included file is embedded in place as if it were written inline.
Selective Include (Specific Fields)
New in V1.1: Include only specific fields from a file using object syntax:
children:
- include:
file: "/Characters/Aya.codex.yaml"
fields: ["summary", "image", "attributes"]
This includes only the summary, image, and attributes fields from Aya's file, ignoring everything else.
Path Resolution Rules
Absolute Project Paths (start with /):
* Resolved relative to Git project root
* Example: /E02/characters/Aya.codex.yaml
Relative Paths (no slash or starts with ./):
* Resolved relative to current file's directory
* characters/Aya.codex.yaml is same as ./characters/Aya.codex.yaml
* Parent directory: ../characters/Aya.codex.yaml
Examples:
If parent file is /E02/scenes/Scene-01.codex.yaml:
* beats/Beat-01.codex.yaml → /E02/scenes/beats/Beat-01.codex.yaml
* ./beats/Beat-01.codex.yaml → /E02/scenes/beats/Beat-01.codex.yaml
* ../characters/Aya.codex.yaml → /E02/characters/Aya.codex.yaml
* /E02/locations/Rome.codex.yaml → /E02/locations/Rome.codex.yaml
Field Specifications
Simple Fields:
fields: ["summary", "body", "image", "tags"]
Nested Attributes (filter by key):
fields: ["attributes.duration", "attributes.location"]
# Returns only attributes where key="duration" or key="location"
Array Fields (entire array):
fields: ["images", "relations", "content"]
# Includes all items in the array
All Children:
fields: ["children"]
# Includes all children from the file
Specific Child by ID:
fields: ["children.id:char-uuid-123"]
# Includes only the child with id="char-uuid-123"
Complete Examples
Mixed Syntax in Same Array:
children:
# Full include (string syntax)
- include: "/Characters/Aya.codex.yaml"
# Summary only (selective)
- include:
file: "/Characters/Marcus.codex.yaml"
fields: ["summary"]
# Specific attributes from beats
- include:
file: "beats/Beat-01.codex.yaml"
fields: ["name", "summary", "attributes.duration", "content"]
Relative Path Example:
# In file: /E02/scenes/Scene-01.codex.yaml
children:
# Relative to current directory
- include:
file: "beats/Beat-01.codex.yaml"
fields: ["summary", "content"]
# Parent directory
- include:
file: "../characters/Aya.codex.yaml"
fields: ["summary", "image"]
# Absolute project path
- include:
file: "/E02/locations/Rome.codex.yaml"
fields: ["summary"]
Screenplay Beat References:
# In: /Project/Acts/Act-01.codex.yaml
children:
- include:
file: "../Beats/Opening.codex.yaml"
fields: ["summary", "attributes.duration", "content"]
- include:
file: "../Beats/Inciting.codex.yaml"
fields: ["summary", "attributes.duration", "content"]
Include Rules
- Path Format: Absolute (
/path) or relative (pathor./path) - File Extension: Typically
.codex.yamlor.codex.json - Valid Codex: Included file must be valid V1.0+ codex
- Recursive: Included files can contain their own includes
- Circular Detection: Circular includes are detected and prevented
- Security: Paths cannot escape project directory
Resolution Process
When parser encounters an include:
- Detect Syntax: String (full) or object (selective)
- Resolve Path: Apply path resolution rules
- Load: Read the referenced file
- Parse: Parse as V1.0+ codex
- Filter (selective only): Extract specified fields
- Embed: Replace include directive with content
- Recurse: Process any includes in embedded content
Media Handling
Simple Image
image: "/images/characters/livia-portrait.jpg"
Image Gallery
images:
- url: "/images/livia/portrait-01.jpg"
caption: "Official portrait in senatorial robes"
- url: "/images/livia/sketch-02.jpg"
caption: "Early concept sketch"
- url: "https://example.com/reference.jpg"
caption: "Historical reference"
Image Item Structure:
* url — string (required) — Image URL
* caption — string — Display caption
* alt — string — Alt text for accessibility
* featured — boolean — Mark as featured
Media Array (Advanced)
media:
- source_type: "url"
source: "/images/livia/portrait.jpg"
media_type: "image"
featured: true
caption: "Character portrait"
- source_type: "url"
source: "/video/livia-intro.mp4"
media_type: "video"
caption: "Character introduction"
Path Resolution
Image paths in Git-based projects:
Relative Paths (start with /):
* /images/file.jpg → Resolved relative to Git project root
* App converts to: /projects/{project-id}/files/images/file.jpg
Absolute URLs:
* https://example.com/image.jpg → Used as-is
* ipfs://bafy.../image.jpg → Used as-is
Tagging System
Tags can be stored in two formats: simple (array of strings) or detailed (array of objects with counts). Both formats are valid and can be used at any level. New in V1.2: The renderer now fully supports both formats with weighted display for counted tags.
Simple Format (Strings)
The most common format — an array of tag strings:
tags:
- 11-lives # Series identifier
- epoch-02 # Time period
- protagonist # Narrative function
- reincarnation # Special property
- roman-era # Historical context
Detailed Format (Objects with Counts)
For auto-generated tags or when frequency matters, use objects with name and count:
tags:
- name: Roman
count: 15
- name: Awakening
count: 8
- name: Senate Chamber
count: 5
- name: Memory
count: 4
Detailed Tag Fields:
* name — string (required) — The tag text
* count — number (optional) — Frequency/weight of this tag
Mixed Format
You can mix both formats in the same array (though not recommended for consistency):
tags:
- protagonist # Simple string
- name: Roman # Detailed object
count: 15
- roman-era # Simple string
Node-Level Tags
Tags at the node level for cross-referencing and filtering:
id: char-livia-uuid
type: character
name: "Livia Mercuria"
tags:
- protagonist
- awakened
- roman-era
Attribute-Level Tags
Tags can also be applied to individual attributes:
attributes:
- key: strength
name: "Strength"
value: 18
dataType: int
tags:
- stat
- physical
- core-attribute
Document-Level Tags (in Metadata)
Tags in the metadata section apply to the entire document:
metadata:
formatVersion: "1.1"
tags:
- draft
- needs-review
- canon
Auto-Generated Tags
The ChapterWise Codex VS Code extension can automatically generate tags from body content using the Generate Tags command. This uses NLP-based extraction with:
- Unigram and bigram (phrase) detection
- Stopword filtering
- Heading text boosting
- Minimum frequency thresholds
Generated tags can be output in either simple or detailed format.
Weighted Tag Display (V1.2)
When tags include count values, the ChapterWise renderer displays them with weighted sizing — tags with higher counts appear larger, creating a visual tag cloud effect:
- Simple tags (strings): Displayed uniformly with standard size
- Weighted tags (objects with
count): Displayed with variable sizes based on relative frequency - Mixed arrays: Both formats render correctly in the same tag section
The size calculation uses the minimum and maximum counts in the array to normalize tag sizes, ensuring visual consistency across different count ranges.
Complete Examples
Complete Character Example
Here's a full V1.2 codex showing all features:
metadata:
formatVersion: "1.2"
documentVersion: "2.1.0"
created: "2025-01-15T00:00:00Z"
updated: "2025-11-30T15:30:00Z"
author: "Anson Phong"
license: "CC BY-SA 4.0"
tags:
- 11-lives
- epoch-02
- canon
id: "char-livia-11l02-uuid"
type: character
name: "Livia Mercuria"
title: "Livia Mercuria, The Rebel Senator"
summary: "Roman noblewoman who became a rebel leader after awakening to past-life memories"
body: |
# Background
Born in 75 BCE into the wealthy Mercuria merchant family, Livia was
expected to marry well and live quietly. Instead, she discovered her
past-life memories at sixteen and became a force that would challenge
the Roman Republic itself.
## The Awakening
During a Senate ceremony, Livia experienced a sudden flood of memories
from her previous life as Aya, the Atlantean priestess. This awakening
changed everything.
image: "/images/livia/portrait-senatorial.jpg"
images:
- url: "/images/livia/portrait-01.jpg"
caption: "In senatorial robes"
- url: "/images/livia/sketch-youth.jpg"
caption: "As a young woman"
tags:
- protagonist
- awakened
- roman-era
- epoch-02
attributes:
- key: house
name: "Noble House"
value: "Mercuria"
- key: soul_archetype
name: "Soul Archetype"
value: "Aya-Prime"
- key: epoch_code
name: "Epoch Code"
value: "11L02"
- key: incarnation_number
name: "Incarnation Number"
value: 2
dataType: int
- key: strength
name: "Strength"
value: 18
dataType: int
- key: special_abilities
name: "Special Abilities"
value:
- temporal-sight
- empathic-healing
- political-cunning
relations:
- targetId: "char-aya-11l01-uuid"
kind: "reincarnation-of"
strength: 0.95
attributes:
- key: soul_continuity
value: 0.95
- key: memory_retention
value: 0.2
- targetId: "char-marcus-11l02-uuid"
kind: "loves"
strength: 1.0
children:
- id: "arc-awakening-uuid"
type: arc
name: "From Senate to Rebellion"
summary: "Livia's transformation from privileged noble to rebel leader"
children:
- id: "beat-memory-flood-uuid"
type: beat
name: "The Memory Flood"
summary: "Livia's past-life memories return during a Senate ceremony"
content:
- key: visual
name: "Visual"
value: |
The Senate chamber. Livia stands frozen as golden light
fills her vision. Around her, time seems to slow.
- key: narration
name: "Narration"
value: |
A thousand lifetimes crash through her mind. She is Aya,
standing in the Great Pyramid. She is someone else, someone
older, someone yet to come.
- key: duration
name: "Duration"
value: "03:45"
- id: "beat-decision-uuid"
type: beat
name: "The Decision"
summary: "Livia chooses rebellion over privilege"
Universe Hierarchy Example
metadata:
formatVersion: "1.2"
author: "Universe Creator"
id: "universe-11lives-uuid"
type: universe
name: "11 Lives"
summary: "Eleven souls across eleven epochs"
children:
- id: "epoch-01-uuid"
type: epoch
name: "Epoch 01: Atlantis"
children:
- id: "char-aya-uuid"
type: character
name: "Aya"
summary: "Atlantean priestess"
- id: "epoch-02-uuid"
type: epoch
name: "Epoch 02: Rome"
children:
- id: "char-livia-uuid"
type: character
name: "Livia Mercuria"
summary: "Roman rebel"
relations:
- targetId: "char-aya-uuid"
kind: "reincarnation-of"
With Includes Example
metadata:
formatVersion: "1.2"
id: "party-uuid"
type: group
name: "Adventuring Party"
children:
- include: "/Characters/Aya.codex.yaml"
- include: "/Characters/Livia.codex.yaml"
- include: "/Characters/Marcus.codex.yaml"
Best Practices
1. Use name as Primary Identifier
name: "Livia Mercuria" # ✅ Primary identifier
title: "The Rebel Senator" # ✅ Optional display name
2. Multiline Strings with Pipe Format
body: |
This is a long multiline string.
It preserves line breaks and formatting.
Perfect for narrative content.
3. Prioritize Clarity Over Brevity
# ❌ Too cryptic
attributes:
- key: str
value: 18
# ✅ Clear and explicit
attributes:
- key: strength
name: "Strength"
value: 18
dataType: int
4. Use Semantic Type Names
type: character # ✅ Clear
type: location # ✅ Clear
type: chapter # ✅ Clear
type: beat # ✅ Clear
type: arc # ✅ Clear
5. Tag Comprehensively
tags:
- 11-lives # Series
- epoch-02 # Period
- protagonist # Function
- awakened # Status
- roman-era # Context
6. Include DataTypes for Attributes
attributes:
- key: strength
value: 18
dataType: int # ✅ Explicit type
- key: birth_date
value: "75 BCE"
dataType: date # ✅ Explicit type
7. Document Versions Semantically
metadata:
documentVersion: "1.0.0" # Initial
documentVersion: "1.1.0" # Minor updates
documentVersion: "2.0.0" # Major revision
8. Clean String Whitespace
# ❌ Trailing spaces
name: "Livia Mercuria "
# ✅ Clean strings
name: "Livia Mercuria"
Use the migration script's --reformat option to clean up whitespace.
9. Use Display Settings for Clean Presentation
# For lists, checklists, or structured data modules
display:
breadcrumb: false # Remove parent breadcrumb from titles
icon: false # Remove type icons for minimalist look
type: false # Remove type badges
# Children inherit these settings automatically
children:
- name: "Item 1"
# Automatically has breadcrumb=false, icon=false, type=false
Working with Git Projects
When using codex files in Git repositories:
File Organization
my-universe/
├── .codex-index.yaml # Project index
├── Characters/
│ ├── Aya.codex.yaml
│ ├── Livia.codex.yaml
│ └── Marcus.codex.yaml
├── Locations/
│ ├── Atlantis.codex.yaml
│ └── Rome.codex.yaml
└── images/
├── Aya/
├── Livia/
└── Marcus/
Using Includes
# main.codex.yaml
metadata:
formatVersion: "1.0"
id: "party-uuid"
type: group
name: "Main Characters"
children:
- include: "/Characters/Aya.codex.yaml"
- include: "/Characters/Livia.codex.yaml"
- include: "/Characters/Marcus.codex.yaml"
Image Paths
# In /Characters/Aya.codex.yaml
image: "/images/Aya/portrait.jpg"
images:
- url: "/images/Aya/concept-01.jpg"
caption: "Concept art"
- url: "/images/Aya/final.jpg"
caption: "Final design"
Paths starting with / are relative to the Git repository root.
Migration from Legacy Formats
If you have files in older formats (with data wrappers or packetType fields), use the migration script:
# Migrate a single file
python scripts/migrate_codex_to_v1.py myfile.codex.yaml
# Migrate a directory
python scripts/migrate_codex_to_v1.py /path/to/codex/directory/
# Reformat an already-migrated file (clean strings, apply pipe format)
python scripts/migrate_codex_to_v1.py --reformat myfile.codex.yaml
# Dry run (see what would change without modifying files)
python scripts/migrate_codex_to_v1.py --dry-run myfile.codex.yaml
# Skip backups
python scripts/migrate_codex_to_v1.py --no-backup myfile.codex.yaml
The script:
* ✅ Removes data wrapper
* ✅ Creates metadata object
* ✅ Moves format info to metadata.formatVersion
* ✅ Handles title vs name intelligently
* ✅ Cleans whitespace from strings
* ✅ Applies pipe format (|) for multiline strings
* ✅ Creates backups automatically (.backup extension)
Legacy Format Example
Before (Legacy V0.9):
packetType: node
version: "0.9.0"
title: "Character"
data:
id: "uuid"
type: character
name: "Hero"
After (V1.0+):
metadata:
formatVersion: "1.2"
id: "uuid"
type: character
name: "Hero"
Validation
What the App Validates
When you upload or view a codex file, the app checks:
- ✅
metadataobject exists - ✅
metadata.formatVersionequals"1.0","1.1","1.2", or"1.3" - ❌ Rejects files with
datawrapper (legacy format) - ❌ Rejects files missing
metadata
Required Validation
A V1.0+ parser MUST validate:
- Metadata Exists:
metadataobject must be present at root - Format Version:
metadata.formatVersionmust equal"1.0","1.1","1.2", or"1.3" - No Data Wrapper: Files with
datakey at root must be rejected
Error Messages
Missing Metadata:
Invalid format: V1.0+ codex files must have a 'metadata' section.
Please migrate using scripts/migrate_codex_to_v1.py
Wrong Version:
Unsupported format version: 0.9.0. Only V1.0, V1.1, and V1.2 are supported.
Legacy Format:
Legacy format detected: Files with 'data' wrapper are not supported.
Please migrate using scripts/migrate_codex_to_v1.py
Optional Validation
Parsers MAY optionally validate:
- UUID format (if
idpresent) - ISO-8601 timestamps (if
created/updatedpresent) - Semantic versioning (if
documentVersionpresent) - Relation target existence
- Circular include detection
JSON Format Examples
All examples above use YAML, but here's the equivalent in JSON:
Simple Character (JSON)
{
"metadata": {
"formatVersion": "1.2",
"documentVersion": "1.2.0",
"author": "Author Name"
},
"id": "char-livia-uuid",
"type": "character",
"name": "Livia Mercuria",
"summary": "Roman noblewoman turned rebel leader",
"attributes": [
{
"key": "house",
"name": "Noble House",
"value": "Mercuria"
},
{
"key": "strength",
"name": "Strength",
"value": 18,
"dataType": "int"
}
],
"children": [
{
"id": "arc-uuid",
"type": "arc",
"name": "The Awakening"
}
]
}
With Body (JSON)
{
"metadata": {
"formatVersion": "1.2"
},
"id": "char-aya-uuid",
"type": "character",
"name": "Aya",
"body": "Born under the constellation of the Eternal Flame, Aya was marked from birth with the silver crescent upon her brow.\n\nAt sixteen, she discovered her prophetic sight during the Pyramid Meltdown."
}
Selective Include (JSON)
{
"metadata": {
"formatVersion": "1.2"
},
"id": "scene-uuid",
"type": "scene",
"name": "Act 1",
"children": [
{
"include": "/Characters/Aya.codex.yaml"
},
{
"include": {
"file": "/Characters/Marcus.codex.yaml",
"fields": ["summary", "image"]
}
}
]
}
Technical Specification
Conformance Levels
Level 1: Basic Parser
* MUST validate metadata.formatVersion = "1.0", "1.1", "1.2", or "1.3"
* MUST reject files with data wrapper
* MUST support all node fields
* MUST preserve order of children
Level 2: Full Parser * All Level 1 requirements * MUST support include directives (both string and object syntax) * MUST support selective field inclusion (V1.1) * MUST support both string and object tag formats (V1.2) * MUST resolve relative image paths * MUST handle both YAML and JSON
Level 3: Advanced Parser * All Level 2 requirements * MUST detect circular includes * MUST support relative path resolution * MUST render weighted tags with size variation (V1.2) * SHOULD validate UUIDs * SHOULD validate timestamps * SHOULD support relation validation
MIME Types
- YAML:
application/x-yamlortext/yaml - JSON:
application/json
References
- ISO 8601: Date and time format
- RFC 4122: UUID specification
- YAML 1.2: YAML specification
- JSON: RFC 8259
- Semantic Versioning: semver.org
- SPDX: Software Package Data Exchange
Implementation Checklist
- [ ] Parse
metadataobject - [ ] Validate
formatVersion = "1.0" - [ ] Reject legacy
datawrapper - [ ] Support all optional node fields
- [ ] Parse
attributesarray - [ ] Parse
relationsarray - [ ] Parse
childrenarray (recursive) - [ ] Resolve
includedirectives - [ ] Resolve relative image paths
- [ ] Support YAML format
- [ ] Support JSON format
- [ ] Detect circular includes
- [ ] Preserve child order
Resources
- Git Projects Guide — Learn about Git Codex Projects for version-controlled storytelling
- Migration Script — Located at
scripts/migrate_codex_to_v1.pyin the repository - JSON Schema — See
codex_schema_v1.pyfor the full JSON Schema definition
Version History
V1.3 (February 2026)
* Added diagram content type with Mermaid.js rendering (23 diagram types)
* Added .mermaid and .mmd file support via include resolver
* Added content-array include resolution (includes inside content[] arrays)
* Added width field to content items for layout control (1/1, 1/2, 1/3)
* Added spreadsheet content type with Jspreadsheet CE integration
* Added .spreadsheet.yaml format for self-contained programmable spreadsheets
* Content array now preferred over dict format (both supported)
* Flex-based layout replaces CSS masonry for content sections
* Include resolver supports .csv, .xlsx, .spreadsheet.yaml, .mermaid, and .mmd files
* Backwards compatible with V1.0, V1.1, and V1.2
V1.2 (November 30, 2025) * Enhanced tag array support with both string and object formats * Weighted tag display with size variation based on count values * Full rendering support for mixed tag arrays * Backwards compatible with V1.0 and V1.1
V1.1 (November 14, 2025)
* Enhanced include directives with selective field inclusion
* Support for relative path resolution (no slash or ./)
* Object syntax for includes: { file: "...", fields: [...] }
* Backwards compatible with V1.0
V1.0 (October 25, 2025) * Initial stable release * Perfect recursion * Metadata consolidation * Include directives * No data wrapper
License
This specification is licensed under CC BY-SA 4.0.
Summary
ChapterWise Codex Format V1.3 is a perfectly recursive, elegant format where:
✅ Any part can be a standalone codex ✅ No data wrapper — content at root ✅ Metadata consolidates format info ✅ Enhanced include directives — full or selective ✅ Relative path support — flexible file organization ✅ Full YAML and JSON support ✅ Media-aware with image galleries ✅ Flexible attributes and relations ✅ Enhanced tagging — simple strings or weighted objects ✅ Beautiful fractal structure
Start with a simple character, grow to a universe — the same format works at every level.