Format reference
Mythcode
Mythcode is MythForge’s portable stat-block format: plain YAML that any text editor (or any Game Master in a group chat) can read and write. Every block carries a schema: line that says what it is (mythforge/creature/v1, mythforge/item/v1, mythforge/spell/v1, or mythforge/encounter/v1); the app routes the import from that field alone, wherever it sits in the block. Blocks shared before mid-2026 may carry the older npcroller/ prefix instead; those still import, and re-saving or re-sharing writes the modern id.
Unknown fields are preserved, not rejected. Add your own keys (a campaign note, a source page number) and they survive import, edit, and re-share untouched. The one exception: inside the small fixed-shape objects (a save block, a damage[] entry, a spell slots[] entry) unknown keys are dropped on import.
To import: open the Compendium tab on any shelf and tap the Import (tray) icon in the header, then paste and tap Import. The app confirms what it imported and lands you on the right shelf — an encounter lands in your active campaign instead. If a block fails, each offending field is called out by name. To go the other way, every creature, item, spell, and encounter in the app has a Share Mythcode action that emits this same format. Shared blocks spell out every default the original author left implicit, so they read a little longer than the templates below.
Templates below are minimal: required fields plus enough to be worth playing. Field tables list everything the format accepts. Every template and example on this page is imported verbatim by MythForge’s test suite before it ships.
Beast (creature)
Creatures use schema: mythforge/creature/v1. Only schema, name, ac, hp.average, and the six ability scores are required; everything else has a sensible default. Tags drive shelving and appearance: a creature-type tag (aberration, beast, celestial, construct, dragon, elemental, fey, fiend, giant, humanoid, monstrosity, ooze, plant, undead) picks the icon, and a size tag (tiny, small, medium, large, huge, gargantuan) shows a size badge. A few alias tags pick icons too: human, goblinoid, devil, demon, titan, shapechanger, and any tag starting with swarm.
Anywhere a table below says dice, the notation is validated: NdM with an optional modifier (6d8+12), keep clauses (4d6kh3, 2d20kl1), and an adv or dis suffix. Die counts run 1–100 and sides 2–1000. A damage string is dice first, then an optional damage type: 2d6+2 slashing, flat 1 piercing, or bare 2d6 with no type at all.
Template: paste this into Import
schema: mythforge/creature/v1
name: Cave Lurker
ac: 13
hp:
average: 22
formula: 4d8+4
speed:
walk: 30
climb: 20
abilities:
str: 14
dex: 12
con: 13
int: 3
wis: 10
cha: 5
attacks:
- name: Bite
to_hit: 4
damage: 1d8+2 piercing
type: melee
tags:
- monstrosity
- medium
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
| schema | literal | required | Must be exactly `mythforge/creature/v1`. |
| name | string | required | Non-empty. |
| system | string | default `dnd5e` | Game system id. |
| role | enum | default `independent` | One of `leader`, `minion`, `independent`. |
| influence | integer 0–5 | optional | Only allowed when role is `leader`. |
| ac | integer ≥ 1 | required | Armor class. |
| hp | object | required | See the hp table. |
| speed | map of string → integer ≥ 0 | optional | e.g. `walk: 30`, `fly: 60`, `climb: 20`. |
| abilities | object | required | See the abilities table. |
| attacks | array | default `[]` | See attacks[] entries. |
| traits | array | default `[]` | See traits[] entries. |
| resources | array | default `[]` | Tracked charges. See resources[] entries. |
| spellcasting | object | optional | See the spellcasting table. |
| inventory | array | default `[]` | See inventory[] entries. |
| actions | array | default `[]` | Non-attack actions. See actions[] entries. |
| legendaryActions | array | default `[]` | See legendaryActions[] entries. |
| reactions | array | default `[]` | See reactions[] entries. |
| alignment | string | optional | Free text, e.g. `chaotic evil`. |
| xp | integer ≥ 0 | optional | XP awarded. |
| languages | string | optional | Free text, e.g. `Common, Draconic`. |
| senses | array of strings | default `[]` | Verbatim, e.g. `darkvision 120 ft.`. |
| passivePerception | integer | optional | |
| saves | object | optional | Proficient save modifiers only: any of `str dex con int wis cha`, each an integer. |
| skills | map of string → integer | optional | e.g. `perception: 6`. |
| damageResistances | array of strings | default `[]` | |
| damageImmunities | array of strings | default `[]` | |
| damageVulnerabilities | array of strings | default `[]` | |
| conditionImmunities | array of strings | default `[]` | |
| tags | array of strings | default `[]` | `npc` shelves the creature under NPCs; type + size tags drive icon and badge. |
| image | string | optional | Local path inside the app; stripped when publishing. |
| imageFocus | object | optional | `x` and `y`, each a number 0–1: the image’s cover-crop focus. Center when absent. Publishing strips `image` but keeps `imageFocus`. |
| source | object | optional | See the source table. |
hp
| Field | Type | Required | Notes |
|---|---|---|---|
| average | integer ≥ 1 | required | Starting/max hit points. |
| formula | dice string | optional | Validated dice notation, e.g. `6d8+12`. |
abilities
| Field | Type | Required | Notes |
|---|---|---|---|
| `str`, `dex`, `con`, `int`, `wis`, `cha` | integer 1–30 | all six required | Raw ability scores; modifiers are derived. |
attacks[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| to_hit | integer | required | Attack bonus (may be negative). |
| damage | string | required | Dice, then an optional damage type: `2d6+2 slashing`. Flat damage like `1 piercing` is legal; so is bare `2d6` with no type. |
| type | enum | required | `melee` or `ranged`. |
traits[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| text | string | required |
actions[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| text | string | required | The action’s prose. |
| toHit | integer | optional | For the rare action that rolls to hit but has no attack damage. |
| save | object | optional | See the save table. |
| damage | array | default `[]` | See the damage[] table. |
| resourceName | string | optional | Names an entry in `resources`; two breath weapons can share one pool. |
legendaryActions[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| text | string | required | |
| cost | integer ≥ 1 | default `1` | Legendary action cost. |
| toHit | integer | optional | |
| save | object | optional | See the save table. |
| damage | array | default `[]` | See the damage[] table. |
reactions[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| text | string | required | |
| save | object | optional | See the save table. |
save objects (actions, legendary actions, reactions)
| Field | Type | Required | Notes |
|---|---|---|---|
| ability | enum | required | `str`, `dex`, `con`, `int`, `wis`, or `cha`. |
| dc | integer ≥ 1 | required | |
| onSuccess | enum | required | `none` or `half`. |
damage[] entries (actions and legendary actions)
| Field | Type | Required | Notes |
|---|---|---|---|
| dice | string | required | A validated damage string: `8d6`, or flat `10`. |
| type | string | required | e.g. `fire`. |
resources[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | Referenced by `resourceName` fields. |
| max | integer ≥ 1 | required | |
| recharge | enum | default `none` | `none`, `turn`, `short_rest`, `long_rest`, `day`, `recharge_5_6`, `recharge_6`, `recharge_4_6`. |
spellcasting
| Field | Type | Required | Notes |
|---|---|---|---|
| ability | enum | optional | `int`, `wis`, or `cha`. |
| slots | array | default `[]` | Entries of `level` (integer 1–9) and `max` (integer ≥ 1). |
| knownSpells | array | default `[]` | See knownSpells[] entries. |
| proficiencyBonus | integer 0–10 | optional | |
| saveDc | integer | optional | Overrides the derived DC. |
| attackBonus | integer | optional | Overrides the derived bonus. |
spellcasting.knownSpells[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| spellId | string | required | Reference id, e.g. `srd:bless`. |
| name | string | required | |
| level | integer 0–9 | required | 0 = cantrip. |
| castMode | enum | default `slot` | `slot`, `at_will`, or `resource`. |
| resourceName | string | optional | Required in spirit when castMode is `resource`. |
inventory[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| itemId | string | required | Reference id, e.g. `srd:potion-of-healing`. |
| name | string | required | |
| quantity | integer ≥ 1 | default `1` | |
| resourceName | string | optional | Ties consumption to a tracked resource. |
source
| Field | Type | Required | Notes |
|---|---|---|---|
| license | string | required | e.g. `CC-BY-4.0`, `Homebrew`. |
| attribution | string | optional |
Worked example
schema: mythforge/creature/v1
name: Ashwing Drake
ac: 17
hp:
average: 75
formula: 10d10+20
speed:
walk: 30
fly: 60
abilities:
str: 18
dex: 12
con: 15
int: 8
wis: 11
cha: 14
saves:
dex: 4
con: 5
wis: 3
skills:
perception: 6
stealth: 4
senses:
- blindsight 30 ft.
- darkvision 120 ft.
passivePerception: 16
languages: Draconic
alignment: chaotic evil
xp: 1800
damageImmunities:
- fire
attacks:
- name: Bite
to_hit: 7
damage: 2d10+4 piercing
type: melee
- name: Claw
to_hit: 7
damage: 2d6+4 slashing
type: melee
resources:
- name: Fire Breath
max: 1
recharge: recharge_5_6
actions:
- name: Fire Breath
text: >-
The drake exhales fire in a 30-foot cone. Each creature in that area
must make a DC 14 Dexterity saving throw, taking 8d6 fire damage on a
failed save, or half as much damage on a successful one.
save:
ability: dex
dc: 14
onSuccess: half
damage:
- dice: 8d6
type: fire
resourceName: Fire Breath
legendaryActions:
- name: Tail Swipe
text: The drake makes one tail attack.
cost: 1
toHit: 7
damage:
- dice: 1d8+4
type: bludgeoning
reactions:
- name: Wing Buffet
text: >-
When a creature the drake can see hits it with a melee attack, the
drake beats its wings. The attacker must succeed on a DC 14 Strength
saving throw or be knocked prone.
save:
ability: str
dc: 14
onSuccess: none
tags:
- dragon
- large
source:
license: Homebrew
NPC
An NPC is not a separate schema: it is a creature (schema: mythforge/creature/v1) whose tags include npc. That one tag is what shelves it under NPCs instead of Beasts; every creature field above applies unchanged.
By convention, generated NPCs also carry a race tag and an occupation tag, which power the NPC shelf’s browsing. Races: human, elf, dwarf, halfling, gnome, half-orc, tiefling, dragonborn. Occupations: shopkeeper, innkeeper, blacksmith, farmer, guard, priest, scholar, thief, hunter, bard, healer, sailor. Both lists are conventions, not validation; any tag imports fine.
Template: paste this into Import
schema: mythforge/creature/v1
name: Marta Thistledown
ac: 10
hp:
average: 9
formula: 2d8
abilities:
str: 11
dex: 10
con: 12
int: 11
wis: 14
cha: 13
attacks:
- name: Iron skillet
to_hit: 2
damage: 1d6 bludgeoning
type: melee
traits:
- name: Heard It All
text: Advantage on Insight checks against obvious lies.
tags:
- npc
- halfling
- innkeeper
NPC tag conventions
| Field | Type | Required | Notes |
|---|---|---|---|
| `npc` | tag | required for the NPCs shelf | Without it the creature shelves under Beasts. |
| race tag | tag | convention | One of: human, elf, dwarf, halfling, gnome, half-orc, tiefling, dragonborn. |
| occupation tag | tag | convention | One of: shopkeeper, innkeeper, blacksmith, farmer, guard, priest, scholar, thief, hunter, bard, healer, sailor. |
Worked example
schema: mythforge/creature/v1
name: Brother Aldous
role: independent
ac: 12
hp:
average: 27
formula: 5d8+5
speed:
walk: 30
abilities:
str: 10
dex: 10
con: 12
int: 11
wis: 16
cha: 13
attacks:
- name: Mace
to_hit: 2
damage: 1d6 bludgeoning
type: melee
traits:
- name: Devout
text: Advantage on saving throws against being frightened.
skills:
medicine: 5
religion: 2
languages: Common, Dwarvish
spellcasting:
ability: wis
proficiencyBonus: 2
saveDc: 13
attackBonus: 5
slots:
- level: 1
max: 4
- level: 2
max: 2
knownSpells:
- spellId: srd:sacred-flame
name: Sacred Flame
level: 0
castMode: at_will
- spellId: srd:bless
name: Bless
level: 1
castMode: slot
inventory:
- itemId: srd:potion-of-healing
name: Potion of Healing
quantity: 2
tags:
- npc
- human
- priest
Spell
Spells use schema: mythforge/spell/v1. Level 0 is a cantrip. The components block is required (all three flags default to false). castingTime, range, and duration are free-text strings, exactly as they read on a spell card.
Template: paste this into Import
schema: mythforge/spell/v1
name: Ember Lash
level: 1
school: evocation
castingTime: 1 action
range: 60 feet
components:
verbal: true
somatic: true
duration: Instantaneous
classes:
- sorcerer
- wizard
description: >-
A whip of embers lashes one creature you can see within range. The target
must succeed on a Dexterity saving throw or take 2d8 fire damage.
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
| schema | literal | required | Must be exactly `mythforge/spell/v1`. |
| name | string | required | |
| level | integer 0–9 | required | 0 = cantrip. |
| school | enum | required | `abjuration`, `conjuration`, `divination`, `enchantment`, `evocation`, `illusion`, `necromancy`, `transmutation`. |
| castingTime | string | required | Free text, e.g. `1 action`. |
| range | string | required | Free text, e.g. `60 feet`, `Self`. |
| components | object | required | See the components table. |
| duration | string | required | Free text, e.g. `Concentration, up to 1 minute`. |
| concentration | boolean | default `false` | |
| ritual | boolean | default `false` | |
| classes | array of enums | default `[]` | `bard`, `cleric`, `druid`, `paladin`, `ranger`, `sorcerer`, `warlock`, `wizard`. |
| description | string | default `''` | |
| higherLevels | string | optional | The “At Higher Levels” paragraph. |
| tags | array of strings | default `[]` | |
| source | object | optional | `license` (required string), `attribution` (optional). |
components
| Field | Type | Required | Notes |
|---|---|---|---|
| verbal | boolean | default `false` | |
| somatic | boolean | default `false` | |
| material | boolean | default `false` | |
| materialDesc | string | optional | e.g. `a handful of thorns`. |
Worked example
schema: mythforge/spell/v1
name: Veil of Brambles
level: 2
school: conjuration
castingTime: 1 action
range: 90 feet
components:
verbal: true
somatic: true
material: true
materialDesc: a handful of thorns
duration: Concentration, up to 1 minute
concentration: true
ritual: false
classes:
- druid
- ranger
description: >-
Grasping brambles erupt across a 20-foot square of ground you can see
within range. The area becomes difficult terrain, and a creature that
enters the area or starts its turn there must succeed on a Dexterity
saving throw or take 2d6 piercing damage.
higherLevels: >-
When you cast this spell using a spell slot of 3rd level or higher, the
damage increases by 1d6 for each slot level above 2nd.
tags:
- area
- control
Item
Items use schema: mythforge/item/v1. Only schema, name, and category are required. A weapon’s damage is a validated damage string, dice first with an optional damage type after, exactly as in creature attacks. properties and the armor-ish armorClass are free-form strings, and stealthDisadvantage a simple boolean, so the rest of the format never fights a homebrew item.
Template: paste this into Import
schema: mythforge/item/v1
name: Lantern of Steady Light
category: wondrous
rarity: common
weight: 2
cost: 50 gp
description: >-
This hooded lantern burns without oil, shedding bright light in a 30-foot
radius. Speaking its command word extinguishes or relights it.
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
| schema | literal | required | Must be exactly `mythforge/item/v1`. |
| name | string | required | |
| category | enum | required | `weapon`, `armor`, `ammunition`, `gear`, `tool`, `potion`, `ring`, `rod`, `scroll`, `staff`, `wand`, `wondrous`, `mount`. |
| weight | number ≥ 0 | default `0` | Pounds. |
| cost | string | optional | Free text, e.g. `50 gp`. |
| rarity | enum | default `none` | `none`, `common`, `uncommon`, `rare`, `very-rare`, `legendary`, `artifact`, `varies`. |
| attunement | boolean | default `false` | |
| attunementNote | string | optional | e.g. `by a spellcaster`. |
| damage | string | optional | Weapons: a validated damage string, e.g. `1d4 piercing`. Dice first; the damage type is optional. See the dice note in the Beast section. |
| properties | array of strings | optional | e.g. `finesse`, `light`, `thrown (range 20/60)`. |
| armorClass | string | optional | Armor: free text, e.g. `14 + Dex modifier (max 2)`. |
| stealthDisadvantage | boolean | optional | Armor. |
| description | string | default `''` | |
| tags | array of strings | default `[]` | |
| source | object | optional | `license` (required string), `attribution` (optional). |
Worked example
schema: mythforge/item/v1
name: Duskfang Dagger
category: weapon
rarity: rare
attunement: true
weight: 1
cost: 2000 gp
damage: 1d4 piercing
properties:
- finesse
- light
- thrown (range 20/60)
description: >-
You gain a +1 bonus to attack and damage rolls made with this magic
weapon. While you hold it in dim light or darkness, you can take the
Hide action as a bonus action.
tags:
- magic
Encounter
Encounters use schema: mythforge/encounter/v1: a prebuilt fight — the monster roster, an optional battle map, and any counters — in one block. It is a clean template, never a snapshot: sharing strips party members and everything a running fight accumulates (current hp, initiative, round, conditions), and importing always creates a fresh, un-started encounter in your active campaign.
Each monsters[] entry references its statblock through ref. An srd:-prefixed ref (srd:goblin, srd2024:goblin) resolves against the SRD compendium every install ships with. Any other ref must name an entry under creatures:, where the full statblock travels inside the encounter — each value there is an ordinary, complete mythforge/creature/v1 block you could copy out and import on its own. Importing an encounter adds its embedded homebrew to your bestiary and links the combatants to those new entries.
Map tokens address roster entries by key: an entry with count: 3 and key goblin owns tokens goblin.1 through goblin.3, while a count-1 entry uses its bare key. Token size is not stored — a Large creature takes a 2×2 footprint automatically from its size tag. The optional edition field records which ruleset (2014 or 2024) the encounter was built under; imported homebrew is labelled with it.
Template: paste this into Import
schema: mythforge/encounter/v1
name: Cave Mouth Sentries
edition: '2024'
monsters:
- key: goblin
ref: srd:goblin
count: 2
group: Sentries
map:
cols: 10
rows: 8
terrain:
"4,2": tree
"5,2": rock
tokens:
goblin.1:
x: 3
y: 5
goblin.2:
x: 6
y: 5
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
| schema | literal | required | Must be exactly `mythforge/encounter/v1`. |
| name | string | required | Non-empty. |
| edition | enum | optional | `2014` or `2024` (quote it — bare YAML numbers don’t import). Absent: the importing campaign’s edition applies. |
| monsters | array | default `[]` | The roster. See monsters[] entries. |
| creatures | map of key → creature block | default `{}` | One complete `mythforge/creature/v1` block per unique homebrew statblock, keyed by the `ref` that names it. |
| counters | array | default `[]` | Ritual timers, alarm levels, reinforcement pools. See counters[] entries. |
| map | object | optional | The battle map. Omit for a map-less fight. See the map table. |
monsters[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| key | string | required | Lowercase letters, digits, and dashes; unique across entries. Map tokens address the entry by this key. |
| ref | string | required | `srd:`/`srd2024:`-prefixed = shipped compendium; anything else must match an entry under `creatures:`. |
| count | integer ≥ 1 | default `1` | Imports as `Name 1`, `Name 2`, … when above 1. |
| side | enum | default `enemy` | `party` (allied NPC), `enemy`, or `neutral`. |
| group | string | optional | Mob group name — grouped initiative and the group filter use it. |
| name | string | optional | Display-name override; only allowed when `count` is 1. |
| icon | string | optional | Map-token glyph name. Unknown glyphs fall back to initials. |
| arrivalRound | integer ≥ 1 | optional | Stages the entry as a reinforcement arriving on this round. |
counters[] entries
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| value | integer | required | Starting value; may be negative. |
| tickPerRound | integer | optional | Applied each round: `-1` counts down, `+2` builds up. |
| alertAt | integer | optional | Fires an alert when the value reaches or crosses this. |
map
| Field | Type | Required | Notes |
|---|---|---|---|
| cols | integer 6–20 | required | Grid width; every square is 5 feet. |
| rows | integer 6–24 | required | Grid height. |
| terrain | map of "x,y" → terrain | default `{}` | Keys must be `"x,y"` cell coordinates (quote them). Values: wall, line-h, line-v, line-se, line-ne, tree, tree-round, bush, rock, water, bones, house, door, stairs, box, table, barrel, chest, statue, fire, campfire, tent, pit. Unknown values import as-is for newer builds. |
| fog | array of "x,y" keys | default `[]` | Cells hidden from the players’ table view. |
| background | string | default `brown` | `grey`, `brown`, `green`, or `snow`; unknown values fall back to brown. |
| wallColor | string | default `brown` | `brown` (timber) or `stone`; unknown values fall back to brown. |
| tokens | map of token key → cell | default `{}` | Keys are `<entry key>.<n>` (n from 1 to the entry’s count) or the bare entry key when count is 1. See map.tokens values. |
map.tokens values
| Field | Type | Required | Notes |
|---|---|---|---|
| x | integer ≥ 0 | required | Anchor column, 0-based; must be inside the grid. |
| y | integer ≥ 0 | required | Anchor row, 0-based. |
Worked example
schema: mythforge/encounter/v1
name: Ambush at the Ford
edition: '2024'
counters:
- name: Reinforcement pool
value: 4
tickPerRound: -1
alertAt: 0
monsters:
- key: goblin
ref: srd:goblin
count: 3
group: Goblins
- key: warg-rider
ref: warg-rider
count: 2
group: Riders
arrivalRound: 3
- key: scout
ref: srd:scout
side: party
name: Tam the Guide
creatures:
warg-rider:
schema: mythforge/creature/v1
name: Warg Rider
ac: 14
hp:
average: 22
formula: 4d8+4
abilities:
str: 14
dex: 13
con: 12
int: 8
wis: 10
cha: 7
attacks:
- name: Spear
to_hit: 4
damage: 1d6+2 piercing
type: melee
tags:
- humanoid
- medium
map:
cols: 12
rows: 16
background: green
wallColor: brown
terrain:
"3,4": tree
"3,5": rock
"4,4": water
fog:
- "0,0"
- "1,0"
tokens:
goblin.1:
x: 2
y: 3
goblin.2:
x: 3
y: 3
goblin.3:
x: 4
y: 4
warg-rider.1:
x: 5
y: 5
warg-rider.2:
x: 6
y: 5
scout:
x: 6
y: 10