Statblock files
How Atlas statblocks are stored, the YAML of a statblock note, the JSON of a template, and how to write both by hand.
You never need to touch these files, since the card and the template editor write them for you. They are plain text in your vault, though, so you can write statblocks by hand, make them with a script, or keep them in git.
An Atlas statblock is two things:
- A note, a normal Markdown file. Its YAML frontmatter holds the values: this creature's hit points and attacks.
- A template, a JSON file. It holds the shape: which values exist, what kind each one is and where it stands on the card.
Many notes point at one template. The values never go into the template, and the layout never goes into the note, so you can change a template without touching your notes.
The note
This is a complete statblock. Put it in any note and it shows its card.
---
statblock: true
atlas-template: bog-creature-a1b2c3
name: Bog Lurker
level: 3
type: Swamp beast
hp: 27
guard: 13
speed: 20
mood: Hungry
attacks:
- name: Bite
desc: +5 to hit, 2d6 + 3 damage.
- name: Drag under
desc: The target must save or sink.
---
It waits under the reeds by the old causeway.Two properties make it a statblock:
| Property | What it does |
|---|---|
statblock: true | Marks the note as a statblock. Fantasy Statblocks, Dataview and Bases read this property too. |
atlas-template | The id of the template that draws it. Without it, Atlas reads the note as a Fantasy Statblocks statblock. |
Every other property is a value. All of them stand at the top level of the frontmatter, so Obsidian's Properties, Dataview and Bases can read them. Everything under the frontmatter is your own text, and Atlas never changes it.
A few things Atlas does when it writes a note:
- A new note holds only
statblock,atlas-template,nameand, for a token,image. Other values appear as you fill them in. - Clearing a value deletes its property.
- Values it works out, like a modifier, are never stored.
- It changes only the lines of the values you edit. Your comments and the order of other properties stay.
- A note whose YAML has an error is never written. The card tells you the line.
- Changing
namenever renames the file.
A value that does not fit its kind stays as you wrote it, with a small chip like "Not a number". Atlas never converts it.
A note can show its card inside its own text with an empty atlas-statblock code block.
What each kind of value looks like
| Kind | type in the template | In the note |
|---|---|---|
| Text | text | speed: 30 ft. |
| Paragraphs | markdown | description: "It hunts at dusk." |
| Number | number | hp: 27 |
| Rating | rating | cr: 1/4 or cr: 3 |
| Dice | dice | hit_dice: 7d10 + 14 |
| One of a list | choice | size: Large, or languages: Common, Elvish with several |
| Words | list | traits: [Beast, Swamp] |
| Labels and values | pairs | saves: { dex: 5, wis: 2 } |
| Names and text | entries | A list of - name: Bite with desc: … |
| Table | scores | One row: stats: [14, 12, 13]. Several: - [Sword, 1, 1d8] for each row. |
| Groups with items | spells | A list of texts, or of - At will: light, mage hand |
| Counters | counters | A list of - { name: Ki, max: 3, used: 1 } |
| Picture | image | image: art/bog-lurker.webp, a path in the vault |
A counter row can also have regain, a dice formula for the uses that come back, and reset, the recovery action that gives them back.
A table with columns of its own is written as { columns: [Item, Qty], rows: [[Rope, 1]] }.
Keys you cannot use
A property name starts with a letter and holds only letters, digits, _ and -. Keep hyphens out of names you use in formulas. Obsidian, Fantasy Statblocks and Atlas use these for themselves, so a template field cannot:
statblock, atlas-template, atlas-type, layout, tags, aliases, cssclasses, cssclass, token, token-image, statblock-link, path, extends, bestiary, note, columns, mtime, monster, creature, player, position.
name and image are fine: they are the header's name and token art. If Atlas refuses another name, Edit as JSON says why.
References with @
An @ in a value reads a number of the same statblock. The note keeps what you wrote, and the card shows the number. 2d6 + @level on a level 3 creature shows and rolls 2d6 + 3.
| You write | It reads |
|---|---|
@level | A field by its key, or a key it had before you renamed it |
@stats.0 | The first item of a list |
@saves.dex | An entry of labels and values |
@str | A table's column by its name, in any table |
@str.mod | A worked-out row under that column |
@hp | The hit points, whatever the template calls that field |
@con-1 is Con minus 1, and @leveld6 is the level before a d6. A reference that names no number stays as you wrote it, gets a chip on the card and does not roll.
The template file
A template is a JSON file ending in .atlastemplate. Atlas makes them in atlas-vtt/statblock-templates, and finds them anywhere in the vault. The file's name is the template's name, and a note beside it with the same name holds the text new statblocks start with.
This is the template of the Bog Lurker above:
{
"format": "atlas-statblock-template",
"version": 1,
"id": "bog-creature-a1b2c3",
"description": "A small creature card for a homebrew game.",
"diceSetId": "builtin:power-roll",
"fields": [
{ "key": "name", "label": "Name", "type": "text" },
{ "key": "image", "label": "Token art", "type": "image" },
{ "key": "level", "label": "Level", "type": "rating", "meaning": "rating" },
{ "key": "type", "label": "Type", "type": "text", "meaning": "creature-type" },
{ "key": "hp", "label": "Hit Points", "type": "number", "meaning": "hit-points" },
{ "key": "description", "label": "Description", "type": "markdown", "meaning": "description" },
{ "key": "guard", "label": "Guard", "type": "number", "meaning": "armor" },
{ "key": "speed", "label": "Speed", "type": "number", "unit": "ft." },
{ "key": "mood", "label": "Mood", "type": "choice", "options": ["Calm", "Hungry", "Furious"] },
{ "key": "attacks", "label": "Attacks", "type": "entries", "prompt": "Add an attack" }
],
"layout": {
"maxColumns": 1,
"blocks": [
{
"id": "bogrow01",
"type": "row",
"blocks": [
{ "id": "bogguard", "type": "stat", "field": "guard", "look": "stacked" },
{ "id": "bogspeed", "type": "stat", "field": "speed", "look": "stacked" },
{ "id": "bogmood0", "type": "stat", "field": "mood", "look": "stacked" }
]
},
{ "id": "bogline1", "type": "divider" },
{ "id": "bogatk01", "type": "entries", "field": "attacks", "heading": "Attacks", "addLabel": "Add attack" }
]
},
"sample": { "name": "Bog Lurker" }
}The six fields at the top are the header, which Atlas draws by itself. Everything under layout is what comes below it.
Edit it in Atlas
Open the template, click the ⋯ next to Save and choose Edit as JSON. The text stands beside the card, and the card follows once you stop typing. If Atlas cannot use what you typed, it says why under the text, in plain sentences, and the card keeps the last text that worked. Click Done, then Save.
To write a template from nothing, the safest start is Blank in the template gallery, then Edit as JSON. You can also make the file with any text editor.
Top-level keys
| Key | What it holds |
|---|---|
format | Always atlas-statblock-template |
version | Always 1. A file with a higher number opens read-only. |
id | A slug, a hyphen and six letters or digits: bog-creature-a1b2c3 |
description | One line for the gallery |
suits | Role names it suits, as a hint for pickers |
diceSetId | The dice set of its bonuses. Left out, it rolls the collection's dice. |
fields | Everything a statblock of this template holds, in Tab order |
header | hidden: header parts kept off the card, from level, type, hp, description |
layout | maxColumns (1 to 3, default 2), columnWidth in em (default 22) and blocks |
lookups | Tables for patterns, like { "xp": { "1": "200" } } |
sample | Values the editor previews with. They never reach a statblock. |
recovery | The recovery actions. Set these in the editor. |
The ids of built-in dice sets are builtin:d20, builtin:d20-roll-under, builtin:d100-roll-under, builtin:d10-exploding and builtin:power-roll. Your own sets are JSON files in atlas-vtt/dice-sets, each with its id inside.
Keys Atlas does not know stay in the file when it saves.
Fields
| Key | For | What it does |
|---|---|---|
key | All | The property name in the note. Never changes once notes use it. |
label | All | The name on the card |
type | All | One of the kinds above |
meaning | All | What Atlas uses the field for, under Meanings |
formerKeys | All | Old names, read while key is missing. Newest first. |
prompt | All | The text of an empty value, like "Add an attack" |
unit | number, numbered choice | Written after the number, like ft. |
options | choice | The values on offer |
open | choice | true takes other values too |
several | choice | true picks several, written as one line |
numbered | choice | true gives each pick a number: darkvision 60 ft. |
tracks | number | { "counts": "down" } or "up", and max: the field that holds the maximum |
entry | entries | nameKey (default name), textKey (default desc) and extras: a list of { key, label, type, options, several } |
slots | scores | The column names |
slotKeys | scores | Each column's key, by default its name in lower case |
header | scores | false draws no header row |
rows | scores | The rows every statblock starts with |
align | scores | Per column: start, center, end |
addRows, addColumns | scores | false keeps statblocks to the template's rows or columns |
counterRows | counters | Starting rows: { name, max, regain } |
Meanings
A meaning tells Atlas what a field is for when its key is unusual. Your "Guard" works as armour once it has the meaning armor. Each meaning goes on one field. Set meanings in JSON, since the editor has no control for them.
hit-points, armor, rating, size, creature-type, senses, initiative, traits, description, display-name.
rating is the level, and display-name is the name the card shows where the statblock has one, while name stays what identifies it.
Blocks
Every block has an id of eight lowercase letters or digits, unique in the template, and a type.
type | Editor name | Keys |
|---|---|---|
stat | Value | field, label, look (run-in, stacked), pattern, display (plain, signed), rollFrom, rollable, addsToRolls |
tags | Value of words | field, label, look (comma, chips, bullets, numbered) |
pairs | Value of labels and values | field, label, display, rollable, addsToRolls |
metric | Metric | heading, fields, rollable, addsToRolls |
entries | Abilities | field, heading, introField, nameStyle (run-in, heading), addLabel |
scores | Table | field, orientation (row, table), perLine, display, columns, rollable |
counters | Counters | field, label |
track | Number shown as boxes or a gauge | field, label, resource, look (boxes, gauge), counts (down, up) |
text | Text | field or text, heading |
divider | Divider | |
row | Parts side by side | align (start, center, spread), blocks |
The editor shows these too, but you change them in JSON:
type | What it is | Keys |
|---|---|---|
section | A group under a heading | heading, headingField, collapsible (open, closed), blocks |
tabs | Sections shown one at a time. It holds sections only and cannot stand in a row. | heading, blocks |
line | Several values in one line | fields, pattern, separator |
heading | A heading you type | text, level (section, minor) |
spells | Groups with items | field, heading, look (lines, tabs) |
image | A picture | field, shape (token, portrait) |
Atlas keeps a script block from a Fantasy Statblocks import as it was and never runs it in its own card. Do not write one yourself.
A rollFrom names a dice field a value rolls when it shows no dice of its own. rollable and addsToRolls are true or left out, as Roll as a bonus and Add to next roll in the editor.
A table's columns are its worked-out rows, each { label, field, formula, display }. A formula works on the column's score with the word value: floor((value - 10) / 2) is a 5E modifier. They show only while the table holds one row.
Keys every block can have:
| Key | What it does |
|---|---|
showWhen | Shows the block only if a field fits: { "field": "mood", "is": "equal", "value": "Furious" }. is can be present, absent, equal, not-equal, above or below. |
whenEmpty | With nothing to show: hide (the default), fallback shows fallback, fold hides it on a card and folds it into a button under the card where you fill it in |
fallback | A pattern for whenEmpty, so a value can come from other fields |
size | In a row: fit or fill |
className | A word for themes and CSS snippets |
Patterns
A pattern writes a block's values as text, without code.
| Part | Example | Result |
|---|---|---|
| A field | {speed} | 20 |
| Several fields | {immunities, conditions|join:; } | The ones with values, joined by "; " |
| A formula | {=level * 100} XP | 300 XP |
| An optional part | {size}[ ({subtype})] | Leaves out the brackets' content while subtype is empty |
| An item of a list | {stats.1} | The second item |
A filter follows |:
| Filter | What it does |
|---|---|
signed | Numbers with their sign: +3, -1 |
upper, lower | Letter case |
count | How many items there are |
avg | The average of dice, rounded down: 7d10 + 14 gives 52 |
lookup:xp | The row of the template's xp table: {cr|lookup:xp} |
join:; | Joins items with the text after the colon |
A backslash writes { } [ ] \ , | as they are.
Formulas use + - * /, parentheses, field keys, and floor, ceil, round, abs, min and max. Text that holds a number counts as a number. A formula with an empty field shows nothing.
This is how the 5E templates show experience from the challenge rating, with a lookups table called xp:
{ "id": "b5cr0000", "type": "stat", "field": "cr", "label": "XP", "look": "run-in", "pattern": "{cr|lookup:xp}" }Limits
Atlas reads a statblock within limits, far beyond what a real one holds: lists and maps six levels deep, 200 items per list, 10,000 characters per text and 5,000 values per statblock. What lies past a limit is left out of the card and stays in the note.

