Skip to content
FableDraft

The FableDraft world file

FableDraft imports a whole world from one JSON file. The same format comes out when you export a world, so a file can go out and back in. You can also write one by hand, generate it with a script, or ask an AI assistant to turn your notes into one.

Only two things are required: the world name, and a type and name on each entity. Everything else is optional.

The smallest file

{
  "name": "Tiny",
  "entities": {
    "mira": {"type": "character", "name": "Mira", "fields": {"homeLocationId": "port"}},
    "port": {"type": "location", "name": "Port", "body": "Home of [[id:mira]]."}
  },
  "links": [{"fromId": "mira", "toId": "port", "type": "located_in"}]
}

This makes a world called Tiny with a character, a town, and a link between them. mira and port are ids. You make them up; they only matter when something else needs to point at that entity.

A fuller example

This is the downloadable example file. It has two characters, a town, a faction, a quest with one step, a link, a journal entry and a calendar era.

{
  "$schema": "https://fabledraft.com/schemas/world-1.json",
  "name": "The Saltglass Reach",
  "description": "A coast where the sea froze into glass. Smugglers light paths across it.",
  "calendar": {
    "dateOrder": "mdy",
    "yearLabel": "AR",
    "eras": [{"name": "The Glass Years", "start": 1, "end": null, "color": "#3b6ea5"}]
  },
  "entities": [
    {"id": "gullhaven", "type": "location", "name": "Gullhaven",
     "summary": "A harbour town on the edge of the glass.",
     "fields": {"kind": "town", "founded": "-120"}},
    {"id": "guild", "type": "faction", "name": "The Lantern Guild",
     "description": "Smugglers who mark the safe paths across the ice.",
     "fields": {"leaderId": "Vessa Crane", "baseLocationId": "Gullhaven"}},
    {"id": "mira", "type": "character", "name": "Mira Saltwhistle", "tags": ["party"],
     "summary": "A lamplighter who owes the guild money.",
     "fields": {"role": "pc", "born": "04-17-38", "homeLocationId": "gullhaven", "factionIds": ["guild"]}},
    {"id": "vessa", "type": "character", "name": "Vessa Crane",
     "body": "Captain of [[The Lantern Guild]]. Trusts [[id:mira|Mira]] more than she should.",
     "fields": {"role": "ally", "homeLocationId": "gullhaven", "factionIds": ["guild"]}},
    {"id": "lights", "type": "quest", "name": "Lights on the Glass", "status": "active",
     "fields": {"giverId": "vessa", "difficulty": "easy", "locationIds": ["gullhaven"],
       "objectives": [{"id": "s1", "text": "Relight the north lantern", "done": false, "action": "go", "locationId": "gullhaven"}]}}
  ],
  "links": [
    {"fromId": "mira", "toId": "Vessa Crane", "type": "friend", "label": "old cellmates"}
  ],
  "journal": [
    {"date": "03-02-61", "title": "Session 1", "entityIds": ["mira", "lights"],
     "body": "[[Mira Saltwhistle]] took the lantern job from [[Vessa Crane]]."}
  ]
}

Some things to notice:

Ids and references

An id is any short string you choose: mira, loc-1, 42. FableDraft keeps an id when it is 8 to 12 letters, digits, _ or -. Any other id is replaced with a new one, and every place that pointed at it is updated to match. You never need to care what the final ids are. Give every entity a different id.

A reference is any key that points at an entity:

A reference can hold an entity's id or its name. A name matches without caring about upper or lower case. If two entities share a name, the first one in the file wins. Use ids when names repeat.

Top level

Key Kind Notes
name text Required. The world's name.
description text Shown on the world's home page. Markdown and wikilinks work.
style text Notes on look and tone for the AI tools. Up to 12,000 characters.
portraitStyle text How character portraits look, e.g. "cartoonish, bold outlines". The first choice when you make a portrait. Up to 500 characters; longer text is cut.
entities object or list See Entities.
links list See Links.
journal list See Journal.
maps list See Maps.
calendar object See Calendar and dates.
settings object See Settings.
nameCultures, nameLists list See Name lists.
$schema text Ignored on import.

The whole object may also sit inside a "world" key: {"world": {...}}. Exports from older versions look like that.

Entities

Every entity has a type. The eight types are arc, quest, character, location, faction, item, event and note.

Key Kind Notes
type one of the eight types Required.
name text Required.
id text Optional. Needed only if something points at this entity.
summary text A line or two. Markdown and wikilinks work. If it is empty, tagline is used.
body text The main text. Markdown and wikilinks work. If it is empty, the first non-empty one of description, text and content is used.
status text One of the world's statuses. Default idea. A status the world does not have yet is added to its list.
tags list of text
parentId reference An arc can sit under an arc. A quest can sit under an arc or a quest. A location can sit under a location. Other types have no parent.
order number Position among siblings.
fields object The type's own fields, below.
portraitData image data URL Characters only. See Images.
created, updated timestamp For example 2026-10-01T12:00:00Z. Default: the time of import.

The default statuses are idea, planned, active, completed, failed, dead and retired.

Fields by type

Kinds:

Every type can also have parentRelation (text): what the line to the parent says in the graph, like "part of". Empty shows "parent".

Type Key Kind Values or target
arc startDate, endDate date
arc kind choice main, sub
arc theme text
arc hook, climax, resolution text
quest giverId ref character or item (an item such as a letter the player reads)
quest turnInId ref character. Empty: the player turns the quest in to the giver when the giver is a character, and the quest ends at its last step when the giver is an item.
quest difficulty choice easy, normal, hard, deadly
quest timeLimit text
quest optional yes/no
quest locationIds refs location
quest itemIds refs item
quest prerequisiteIds refs quest
quest hook, ending, failure text
quest journalText text What the player reads in the journal, up to 2000 characters. A longer text is cut, with a warning.
quest objectives list of steps see below
quest rewards list of rewards see below
character born, died date
character role choice pc, npc, villain, ally, neutral
character race, class, age, pronouns text
character homeLocationId ref location
character factionIds refs faction
character appearance, personality, motivation, secrets text
character statblock text shown in a fixed-width font
character portraitUrl text a link to an image
character talks list of talks see Talks
location founded date
location kind choice continent, region, city, town, dungeon, building, wilderness, other
location population, government text
faction founded, dissolved date
faction leaderId ref character
faction baseLocationId ref location
faction alignment, goals text
item created date
item category text one of the world's item categories
item kind choice weapon, armor, artifact, consumable, key, treasure, other
item rarity choice common, uncommon, rare, very_rare, legendary
item value number in gold
item ownerId ref character or faction
event date, endDate date
event when text a free-text time, for example "the winter after the war"
event arcId ref arc
event locationId ref location
note no fields

A quest step (objectives) is an object:

Key Kind Notes
id text Any short string. Give each step one.
text text What happens.
done yes/no
locationId ref location
itemIds refs item
characterIds refs character
talkId text The id of a talk (on any character). Reaching the end of that talk finishes the step. An id no talk in the file has is dropped, with a warning.
action choice read, collect, kill, talk, go, use, other. Missing means a story-only step. Another word is kept as written, with a warning.
count number A whole number from 1 to 9999: how many times, for collect and kill. Missing means 1. Any other value is dropped, with a warning.
targetText text Up to 120 characters. For collect and kill: a target with no entry, like pig.
journalText text Up to 2000 characters. What the game logs when the step finishes. Missing means nothing is logged.

count and targetText stay only under collect, kill or a word off the list. Under any other action, or none, they are removed with no warning. Text over its limit is cut, with a warning.

The target of a step, by action:

Action Target
read, use itemIds
collect itemIds, else targetText
kill characterIds, else targetText
talk characterIds, plus talkId if one set talk is needed
go locationId
other text only

If you read this data to build a game:

A quest reward (rewards) is an object:

Key Kind Notes
id text Any short string.
kind choice item, xp, gold, reputation, other
itemId ref an item, when kind is item
amount number
text text

Any other key in fields is kept as written, with a warning.

Talks

A talk is one conversation between a character and the player. A character's talks is a list of talks. The game plays the first talk in the list whose conditions pass, so put the most specific talks first.

"talks": [{
  "id": "t-k3j9x2",
  "title": "First meeting",
  "conditions": [{"kind": "quest", "questId": "lantern", "state": "not_started"}],
  "lines": [
    {"id": "l1", "speaker": "character", "text": "You look lost, traveller.",
     "conditions": [], "effects": [], "next": null,
     "choices": [
       {"id": "c1", "text": "I'm looking for the lantern keeper.",
        "conditions": [], "effects": [{"kind": "start_quest", "questId": "lantern"}], "next": "l2"},
       {"id": "c2", "text": "Never mind.", "conditions": [], "effects": [], "next": "end"}
     ]},
    {"id": "l2", "speaker": "character", "text": "Follow the coast north.", "next": "end"}
  ]
}]

A talk:

Key Kind Notes
id text Unique in the world, and not the id of an entity. FableDraft makes them as t- and 6 letters or digits. A missing id is made; one already used by another talk or an entity gets a new id, with a warning (steps pointing at it keep pointing at the first talk).
title text Up to 120 characters.
conditions list of conditions The talk can play only when all of them pass.
lines list of lines In order. The first line is the start. Up to 200.

A line:

Key Kind Notes
id text Unique in its talk (lines and choices share the ids). The editor uses l1, l2...
speaker character or player Default character. Another word becomes character, with a warning.
text text Up to 2000 characters. Longer text is cut, with a warning.
conditions list of conditions The line is skipped when one fails.
effects list of effects They run when the line is shown.
next null, "end" or a line id null goes to the line below (the talk ends after the last line). A line with choices ignores next: the picked choice decides. Any other value becomes null, with a warning.
choices list of choices What the player can answer. Up to 8.

A choice has id, text (up to 2000 characters), conditions (the choice is hidden when one fails), effects (they run when it is picked) and next (a line id, "end", or null for the line below).

All conditions in one list must pass. Each list holds up to 10 conditions or effects. Longer lists are cut, with a warning. A condition or effect is an object with a kind:

Condition kind Keys Passes when
quest questId, state: not_started, active, done or failed the player's quest is in that state
step questId, stepId, state: done or not_done that step of the quest is (not) done
item itemId, has: yes/no the player holds (or does not hold) the item
switch switchId, on: yes/no the world switch is on (or off)
Effect kind Keys Does
start_quest questId starts the quest
finish_step questId, stepId marks the step done
finish_quest questId finishes the quest
set_switch switchId, on: yes/no turns the switch on or off
give_item, take_item itemId gives the item to the player, or takes it

questId and itemId are references to a quest and an item (an id or a name). stepId is the id of a step in that quest's objectives. switchId is the id of a switch in Settings. A missing has or on means true.

On import, a condition or effect whose reference cannot be found, points at the wrong type, or names an unknown switch is dropped, with a warning. A condition or effect with a kind FableDraft does not know is kept as written, with a warning; it is dropped (with a notice) the next time the character is saved in FableDraft.

A link is a named relation between two entities. It shows on both entity pages and in the graph.

Key Kind Notes
fromId reference Required.
toId reference Required.
type text Usually one of the world's relation types. Default other.
label text A short note shown on the link, like "captain".
notes text Longer notes. Wikilinks work.
id, created Optional.

The default relation types are ally, enemy, rival, family, friend, lover, mentor, member_of, leads, located_in, owns, knows, serves, created and other.

Journal

Session notes.

Key Kind Notes
date text Free text. Usually the real date of the session.
title text
body text Markdown and wikilinks work.
entityIds list of references The entities this entry is about.
id, created, updated Optional.

Maps

Key Kind Notes
name text Default Map.
imageData image data URL The map picture. See Images.
locationId reference The location this map shows. Ignored if it is not a location.
markers list Pins on the map.
id, created, updated Optional.

A marker:

Key Kind Notes
entityId reference Required. One entity can have one marker per map. A second marker for it is dropped, with a warning.
x number 0 to 1 Required. 0 is the left edge, 1 the right edge.
y number 0 to 1 Required. 0 is the top edge, 1 the bottom edge.
underId reference A location the marker sits inside.
id text Optional.

Positions are fractions of the image, so they stay put when the image is resized. Numbers outside 0 to 1 are pulled back to the nearest edge.

Calendar and dates

Key Kind Notes
dateOrder "mdy" Put this in. It tells FableDraft your dates are month first.
yearLabel text Shown after years, like AR or DR.
monthNames list of text Up to 12 names.
daysPerMonth whole number or null Days in every month, 1 to 31. Leave it out or null for 31.
weekDays list of text Up to 14 week day names, in order. Day 1 of month 1 of year 1 is the first one.
today date text The in-world date it is now, like 04-17-1250. A character's age is counted from born up to died, or up to this day; a counted age replaces the one in the file.
eras list Named spans of years.

An era:

Key Kind Notes
name text Required.
start whole number Required. The first year.
end whole number or null The last year. null means it has not ended. Must not be before start.
color text Like #3b6ea5.
summary text
id text Optional.

An in-world date is one of:

The year always comes last. Use - or / between the parts. Years can be negative (-300) and up to six digits. Months go from 1 to 12 and days from 1 to 31. Leading zeros are optional.

Old exports wrote dates year first (1203-4-17). Without "dateOrder": "mdy", a date that cannot be read month first but looks year first is turned around (1203-4-17 becomes 04-17-1203), with a warning. An old export (one with a top-level created key and no dateOrder) has all its dates read year first. With "dateOrder": "mdy", dates are never turned around.

Settings

Key Kind Notes
statuses list of text Replaces the default statuses. Must not be empty.
relationTypes list of text Replaces the default link types. Must not be empty.
itemCategories list of text Replaces the default item categories (weapons, clothing, books).
switches list On/off flags of the world that talks test and set. Up to 200.

A switch:

Key Kind Notes
id text Kept as written when it is 1 to 64 letters, digits, _ or - and not used twice; otherwise a new id. FableDraft makes them as sw- and 6 letters or digits.
name text Required. Up to 120 characters.
on yes/no The value it starts with. Default false.

Leave settings out to keep the defaults.

Name lists

Name lists hold names for the name generator. Most files can leave them out.

Any text that allows Markdown can link to an entity:

You write It shows
[[Vessa Crane]] a link to the entity named Vessa Crane
[[Vessa Crane|the captain]] the same link, labelled "the captain"
[[id:vessa]] a link to the entity with id vessa, labelled with its name
[[id:vessa|the captain]] the same, with your own label

Name links match without caring about case. A name with no matching entity shows as a "click to create" link. [[id:...]] links are updated on import when an id is replaced.

Images

Images are base64 data URLs, for example data:image/png;base64,iVBORw0.... PNG, JPEG, GIF and WebP work. An image over the size limit (10 MB by default) is re-encoded as WebP on import, so it usually still fits. A character portrait goes in portraitData on the entity. Images on any other type are not stored.

Limits

What stops an import, and what only warns

Nothing is saved until the whole file has been checked. Either the whole world is imported or none of it is.

These stop the import, with a message naming the key:

These import, with a warning in the import report:

These import without a warning:

About the schema

world-1.json is a JSON Schema (draft 2020-12). Its $id is https://fabledraft.com/schemas/world-1.json, and every FableDraft site serves the same file at /schemas/world-1.json.

The schema allows extra keys everywhere, like the importer. It is a little stricter than the importer in a few places. The schema lists the usual choices; the importer accepts other words and warns. The schema also flags a badly formed date, a yes/no or number written as a string, and a marker position outside 0 to 1, where the importer keeps, converts or fixes the value and carries on. A file that passes the schema imports without those warnings.

The schema cannot check that a reference points at a real entity. The importer does that.