Tintero Developers

Manifest types

Every type in a .tintero manifest: the root and the 77 it reaches, with the 677 fields they declare, extracted from the interfaces the app serialises.

On this page

Every type in a .tintero manifest, resolved from Project outwards until nothing new turns up, so this is the whole file rather than the parts somebody remembered to list. The names, the types, the optionality and the descriptions all come out of the interfaces the app serialises, which means the page cannot describe a field that no longer exists or miss one that just appeared.

Before you read one

Three things are worth having in mind before the tables below make sense, and each has a page of its own because they are about the container rather than the types:

  • A project is a folder, not a file, and the manifest sits in it beside the text and the assets. See project structure.
  • There is no format version anywhere. An optional field is optional forever, and its absence means an older project rather than a damaged one.
  • None of the writing is in here. Every entry's text is a separate file of ProseMirror JSON, found through the entry's location.

The shareable form of a project is a .tint archive, which holds the same manifest under a different name.

Timestamps

Nearly every timestamp is a number, milliseconds since 1970. The exceptions are typed Date in the source, which means JSON.stringify writes them out as ISO-8601 strings instead:

ImagesModel.createdAt AudioAsset.createdAt PdfAsset.createdAt

Nothing in the file marks them out, so a reader that expects numbers everywhere gets a string on exactly these fields. This list is read from the source, not from memory. A field that changes type in Tintero moves in or out of it on the next sync.

The manifest root

The top level of a .tintero file. The required fields are in every project. The optional ones are missing from projects made before that feature existed.

Project #

12 required of 29

The root of the .tintero manifest. There is no serialiser between this object and the file: the manifest is a plain JSON.stringify of it, so this declaration is the file format. Two consequences worth knowing before reading one. Optional fields are optional forever, because a feature added later shows up as a field that older projects simply do not have, and there is no version number anywhere to tell you which release wrote the file. And the writing itself is never in here: every chapter, doc, note and saved version keeps its text in its own file under files/, addressed by the entry's location. Importing rebuilds this object field by field from an allow list in ProjectFactory, so keys of your own survive ordinary saving and vanish the first time a project is imported.

images ? ImagesModel []

Images stored under the project's images/ folder. Undefined in projects with none.

coverImageId ? string | null

The project's cover: the id of one of the in images. Undefined or null means no cover, and the welcome screen draws a placeholder seeded from id instead. Resolved to a URL or data URL on demand. The image itself is deliberately not inlined here, to keep the manifest small.

id string

Stable identifier, a UUID. Also the name of the manifest file: <id>.tintero.

name string

Title as the writer typed it. Not unique and not an identifier.

description string | null

Free text shown on the project card. Null when never filled in.

path string

Where the project folder sits, as the platform writes paths. Used to reopen it.

createdAt number

When the project was created, epoch milliseconds.

lastModified number

When anything in the project last changed, epoch milliseconds.

baseLastModified ? number

The If-Match value of a v1 upload: the lastModified this client last saw on the SERVER. Set transiently just before uploading, and compared by the server against its stored value so an upload from a stale base is rejected with a 409 instead of overwriting somebody else's work. It is never persisted and takes no part in the local model, since every upload overwrites it. It is not in the file.

folders ProjectFolder []

The folder tree. Folders hold no content of their own, only a place in the hierarchy.

files ProjectFile []

Manuscript entries, the chapters and scenes that make up the book itself.

docs ProjectDoc []

Documents: the writer's own material that is not part of the manuscript.

notes NotesModel []

Notes, which are documents with their own panel rather than a place in the tree.

worldbuilding ? WorldbuildingElement []

Every worldbuilding element, of every type, in one array. Undefined means none.

customWorldbuildingTemplates ? CustomWorldbuildingTemplate []

Element types the writer defined themselves, beyond the built-in ones.

characters CharacterModel []

The cast. Characters are their own type rather than a worldbuilding element.

cardboardGrids ? CardboardGrid []

Corkboards: freeform grids of cards. Undefined in projects that never opened one.

plotGrids ? PlotGrid []

Plot grids: the structured table view of the story.

tags string[]

Project-level tags, used for filtering on the welcome screen.

collections ? Collection []

Collections: named groupings of entries that cut across the folder tree.

wordCountLog ? WordCountLog []

Daily word counts, one entry per day the writer worked.

syncVersion ? number

Which sync protocol wrote this: 1 for the full upload, 2 for incremental live sync.

writingGoals ? WritingGoal []

Writing targets. Undefined means a project older than the feature, which triggers a migration from the old trophy settings the first time it is opened.

writingMinutesLog ? WritingMinutesLog []

Minutes written per day, fed by the timer, for goals counted in minutes.

timelines ? TimelineData []

Timelines: events placed on an axis, in lanes.

flowMaps ? FlowMap []

Flowmaps: nodes and arrows for mapping how the story connects.

bookmarks ? Bookmark []

The index of manuscript bookmarks. The anchors themselves live in the document text as bookmark nodes; this side holds their number, label and file. Undefined means a project older than the feature.

audioAssets ? AudioAsset []

Narrations rendered to audio files. Undefined in projects with no audio.

pdfAssets ? PdfAsset []

PDFs kept alongside the project for reference. Undefined in projects with none.

src/app/domain/project/models/project.interface.ts

Every type in the manifest

The 76 other types the root reaches. They were found by following the interfaces outwards rather than by somebody listing them, so this is the whole file and not a summary of it. 5 of them are classes rather than interfaces, marked as such, because their constructors fill in defaults a field list cannot show, and one of them quietly upgrades older character data on the way in.

AudioAsset #

class 7 required of 17

A generated narration stored in the project, parallel to . The bytes live on disk under the project's audio/ folder (written via IOIntegrationInterface.saveAudioToProject); this object is the metadata that travels inside Project.audioAssets.

id string

Stable identifier, a UUID.

title string

The name shown to the writer.

fileName string

The file's name inside audio/, extension included.

relativePath string

Path under the project, normally audio/<fileName>. For a pack, the first clip.

size number

File size in bytes.

mimeType string

MIME type of the stored bytes, for example audio/mpeg.

format ? AudioFormat

Container/codec, e.g. 'mp3' | 'wav'.

durationMs ? number

Playback length in milliseconds, when known.

lang ? string

ISO language the text was synthesized in.

voice ? string

Voice id used to synthesize (provider voice id or native engine voice name).

OS-native engine or a cloud API.

provider ? string

Provider that produced an api-origin asset (e.g. 'openai', 'elevenlabs').

sourceDocId ? string

Id of the project doc/file this audio narrates, when generated from one.

treePath ? string

Location in the file tree (parent path + name). Set when the audio lives in the tree.

createdAt Date

When the narration was generated. Typed Date, so it serialises as ISO-8601.

hash ? string

Content hash, used to tell whether the narration still matches its text.

segments ? AudioSegment []

When present, this asset is a PACK: an ordered sequence of clips played/mixed gapless. A simple asset (single file) has no segments; relativePath/fileName then point at the lone clip. For a pack they point at the first clip (compat).

src/app/domain/project/models/audio-asset.model.ts

AudioAssetOrigin #

Where an audio file came from.

'native' | 'api' | 'import'

src/app/domain/project/models/audio-asset.model.ts

AudioSegment #

5 required of 11

One clip within a pack (TINT-214). A pack is an ordered list of clips played/mixed sequentially with silences between them, never stitched into a single byte stream until export. Each clip's bytes live on disk under the project's audio/ folder, just like a simple asset; this is the metadata.

id string

Stable identifier of the clip, a UUID.

relativePath string

Path of the clip's bytes under the project (audio/<id>.<format>).

durationMs number

Clip length in milliseconds (derived once on synthesis, not re-decoded).

format ? AudioFormat

Container/codec the engine ACTUALLY produced for this clip. Not always what was asked for: the native engine ignores the requested format (macOS always yields m4a/AAC), so the pack's own format is derived from this rather than from the request.

gapBeforeMs number

Silence (ms) inserted BEFORE this clip when playing or mixing, which is how a pause is rendered.

sourceRange ? { from: number; to: number; docId: string }

Source text range in the annotated doc this clip was synthesized from.

voice ? string

Voice id used (catalog id or native engine voice name).

emotion ? TtsEmotion

Emotion the clip was synthesized with, matching the ttsEmotion mark in the text.

params ? { speed?: number; pitch?: number; stability?: number; style?: number }

Expressive params used, kept for incremental regeneration.

soundTags ? TtsSoundTagName[]

Sound tags applied to the clip, matching the ttsSoundTag nodes in the text.

hash string

Content hash (text + voice + emotion + params) for incremental regeneration.

src/app/domain/project/models/audio-asset.model.ts

BaseWorldbuildingElement #

4 required of 13

What every worldbuilding element has, whatever kind it is. All of them live together in one Project.worldbuilding array, so type is the only thing telling a location from a deity. That makes this the discriminated union's tag, and an unknown value in it means an element from a newer version of the app rather than a damaged one. A word on the fields of the element types that extend this. A field named somethingId or somethingIds holds the id of another element, and so do the relationship fields the app fills from a picker (allies, enemies, languages and a few more). Everything else is text the writer typed, including the arrays: terrain, goals and their kind are lists of words, not references to anything.

id string

Stable identifier, a UUID. What other elements refer to it by.

name string

The element's name, and what the app matches against when it highlights the prose.

type string

Which kind of element this is. The tag that decides which interface applies.

description ? string

Free text description, the main body of the element.

portrait ? string

The element's portrait image, as a fileName or relativePath into images/.

landscape ? string

The element's banner image, as a fileName or relativePath into images/.

tags ? string[]

Tags the writer attached, used for filtering.

color ? string

Colour chosen for the element, as CSS. Also used to highlight it in the text.

createdAt number

When the element was created, epoch milliseconds.

updatedAt ? number

When the element last changed, epoch milliseconds.

notes ? string

The writer's own notes about the element, kept apart from description.

extraFields ? ExtraField []

Fields the writer added to this element alone. See .

isFavorite ? boolean

Whether the writer pinned it to the top of the list.

src/app/domain/project/models/worldbuilding/base-worldbuilding.interface.ts

Bookmark #

3 required of 7

A navigation bookmark in the manuscript. The anchor itself, the actual position, is an inline node in the document JSON (bookmark-node.ts). This is only the project's index of them, adding the file, the number and the label. It lives inside Project so it syncs between devices without a table of its own.

id string

The same value as the data-bookmark-id of the node in the document.

fileId string

The entry whose text holds the anchor.

number ? number

Quick access slot, 0 to 9. Absent means a bookmark with no shortcut.

label ? string

What the writer called it. Absent means the panel shows a generated label.

pos ? number | null

A cache of where the node is, refreshed when the file is saved. It orders the panel and makes next and previous work without opening files. The document node is always the truth. Undefined means not reconciled yet. Null means reconciled and no node was found, so the bookmark is unresolved: it is shown marked as such and never deleted on its own.

lastModified number

Epoch milliseconds. Required by the most-recent-wins merge in sync.

deletedAt ? number | null

Soft delete. Without it the sync merge resurrects deleted bookmarks, because merging never removes: an item present on only one side is kept.

src/app/domain/project/models/bookmark.interface.ts

CardboardAxisHeader #

2 required of 3

A label on one row or one column of a corkboard.

index number

Which row or column it labels, zero based.

label string

What it says.

color ? string

Colour of the header, as CSS.

src/app/domain/project/models/cardboard.interface.ts

CardboardCell #

3 required of 15

One cell of a corkboard. Cells carry their own coordinates rather than sitting in a two-dimensional array, so the cells list is sparse: an empty square of the board has no entry at all.

id string

Stable identifier of the cell.

type string

What the cell holds, one of the values.

referenceId ? string

Id of the thing the cell stands for, when its type points at one.

position { row: number; col: number; }

Where the cell sits on the board, zero based.

content ? string

The cell's text.

imageUrl ? string

Project asset (tintero-image://<key>) or a plain remote URL typed by the user.

audioAssetId ? string

AudioAsset.id in Project.audioAssets. Audio is always a project asset, never a remote URL.

pdfAssetId ? string

PdfAsset.id in Project.pdfAssets.

color ? string

Colour of the cell, as CSS.

checked ? boolean

For a checkbox cell, whether it is ticked.

title ? string

A heading for the cell.

references ? CellReference []

Links from this cell to elsewhere in the project. See .

tags ? string[]

Tags on the cell, used for filtering the board.

status ? string

The cell's status, matching one of the project's configured statuses.

inlineNotes ? InlineNote []

Notes pinned inside the cell. See .

src/app/domain/project/models/cardboard.interface.ts

CardboardCellType #

| 'unassigned' | 'sticky-note' | 'chapter-note' | 'note' | 'character' | 'image' | 'audio' | 'pdf' | 'checkbox' | 'multi'

src/app/domain/project/models/cardboard.interface.ts

CardboardGrid #

7 required of 15

A corkboard: a grid of cards the writer arranges however they like.

id string

Stable identifier, a UUID.

name string

What the writer called this board.

rows number

How many rows the board has.

cols number

How many columns the board has.

The cells that hold something. Empty squares are simply absent.

createdAt number

When the board was created, epoch milliseconds.

lastModified number

When the board last changed, epoch milliseconds.

rowHeaders ? CardboardAxisHeader []

Labels down the side of the board.

colHeaders ? CardboardAxisHeader []

Labels across the top of the board.

showHeaders ? boolean

Whether headers are shown at all. The two per-axis flags below override it.

showColHeaders ? boolean

Whether the column headers are shown. Undefined falls back to showHeaders.

showRowHeaders ? boolean

Whether the row headers are shown. Undefined falls back to showHeaders.

firstColumnSticky ? boolean

Whether the first column stays put while the board scrolls sideways.

cellTypeWhitelist ? CardboardCellType []

When set, the only cell types this board allows.

Which kind of board it is: freeform, or shaped like a plot grid.

src/app/domain/project/models/cardboard.interface.ts

CardboardPreset #

'free' | 'plotgrid'

src/app/domain/project/models/cardboard.interface.ts

CardboardReferenceType #

| 'chapter' | 'doc' | 'character' | 'worldbuilding'

src/app/domain/project/models/cardboard.interface.ts

CellReference #

3 required of 3

A link from a corkboard cell to something else in the project.

id string

Stable identifier of the reference itself, not of what it points at.

Which array of the project to look targetId up in.

targetId string

Id of the chapter, doc, character or worldbuilding element being pointed at.

src/app/domain/project/models/cardboard.interface.ts

CharacterInterface #

3 required of 3

Also has every field of BaseWorldbuildingElement .

A character seen as a worldbuilding element. Characters live in Project.characters, not in Project.worldbuilding, but the pickers and the element union treat them as one of the kinds. This is the shape they take when they do. The real record is .

id string

Id of the this stands for.

name string

The character's name.

type 'character'

Always character, which is what puts it in the element union.

src/app/domain/project/models/character.model.ts

CharacterModel #

class 7 required of 32

A character. A class rather than an interface, which matters when reading the file: the constructor fills in defaults a field list cannot show, and it quietly upgrades older data. A character saved before the worldbuilding links existed gets worldbuilding built for it out of the three legacy fields the first time the app loads it. The three legacy fields are still written and still read. They are not removed on migration, so an old project holds the same fact twice.

id string

Stable identifier, a UUID. Fixed once the character exists.

name string

The name the character is known by, and what the app matches against in the prose.

firstName ? string

Given name, when the writer split the name up.

lastName ? string

Family name, when the writer split the name up.

pronouns ? string[]

The character's pronouns, as the writer wrote them.

aka ? string[]

Other names they go by, which are also matched against the prose.

description ? { physical?: string; psychological?: string; }

The old two-part description. Superseded by physicalDescription and psychologicalDescription and kept only so older projects still read. New code writes the two flat fields.

physicalDescription ? string

What the character looks like, as one block of text.

portrait string | undefined

The character's portrait, as a fileName or relativePath into images/.

landscape string | undefined

The character's banner image, as a fileName or relativePath into images/.

folderPath string | undefined

Where the character sits in the characters panel's own folder tree.

position number | undefined

Sort order within its folder, ascending.

psychologicalDescription ? string

What the character is like inside, as one block of text.

color ? string

Colour used for the character, as CSS. Also what highlights them in the text.

gender ? string

Gender, as free text rather than a fixed set.

age ? string

Age, as text, since a world may not count years the way ours does.

birthdate ? string

When they were born, in the world's own calendar, so free text.

birthplace ? string

Where they were born, as text. Migrated into worldbuilding.locations as well.

occupation ? string

Their trade, as a plain name. Superseded by worldbuilding.occupations, which holds ids, and still written alongside it.

species ? string

Their species, as a plain name. Superseded by worldbuilding.species.

faction ? string

Their faction, as a plain name. Superseded by worldbuilding.factions.

worldbuilding ? CharacterWorldbuilding

Every tie between this character and the world. See .

traits ? string[]

What they are like, as short pieces of text.

goals ? string[]

What they want, as text.

fears ? string[]

What they are afraid of, as text.

backstory ? string

Where they come from, as one block of text.

notes ? string

The writer's own notes about them, kept apart from the description.

tags ? string[]

Tags the writer attached, used for filtering.

createdAt number

When the character was created, epoch milliseconds. Fixed once set.

updatedAt ? number

When the character last changed, epoch milliseconds.

relationships ? Relationship []

Ties to other characters. See .

variants ? CharacterVariant []

Other versions of this character. See .

src/app/domain/project/models/character.model.ts

CharacterVariant #

4 required of 7

A version of a character: an alias, a disguise, who they become in act three. A variant is a patch, not a copy. overrides holds only the fields that differ, so reading one means starting from the character and laying these on top.

id string

Stable identifier of the variant within its character.

name string

What the writer calls this version.

description ? string

What makes it different, in the writer's words.

position ? number

Where it sits in the list of variants, ascending.

overrides Partial<Omit< CharacterModel , 'id' | 'variants'>>

The fields that differ from the character. Everything absent is inherited unchanged.

createdAt number

When the variant was created, epoch milliseconds.

updatedAt ? number

When the variant last changed, epoch milliseconds.

src/app/domain/project/models/character.model.ts

CharacterWorldbuilding #

0 required of 38

How a character is tied into the world, one array of element ids per kind of tie. Thirty-eight ways of being connected to something, all of them optional and all of them holding ids from Project.worldbuilding. One exception is worth knowing about when reading old projects: a character migrated from the three legacy fields (CharacterModel.species, occupation, faction) gets the plain NAME the writer typed pushed into species, occupations, factions or locations instead of an id, and nothing marks the difference. Resolve by id first and fall back to matching on name.

species ? string[]

Ids of the elements this character belongs to.

factions ? string[]

Ids of the elements they belong to.

occupations ? string[]

Ids of the elements they hold.

locations ? string[]

Ids of the elements tied to them.

religions ? string[]

Ids of the elements they follow.

magicSystems ? string[]

Ids of the elements they can use.

languages ? string[]

Ids of the elements they speak.

technologies ? string[]

Ids of the elements they use.

groupMember ? string[]

Ids of the groups they belong to.

groupLeader ? string[]

Ids of the groups they lead.

groupFounder ? string[]

Ids of the groups they founded.

groupExMember ? string[]

Ids of the groups they used to belong to.

groupExLeader ? string[]

Ids of the groups they used to lead.

deityFollower ? string[]

Ids of the deities they follow.

deityChampion ? string[]

Ids of the deities they act for.

deityClergy ? string[]

Ids of the deities they serve as clergy.

deityEnemy ? string[]

Ids of the deities that oppose them.

deityBlessed ? string[]

Ids of the deities that have blessed them.

deityCursed ? string[]

Ids of the deities that have cursed them.

deityExFollower ? string[]

Ids of the deities they used to follow.

creatureTamed ? string[]

Ids of the creatures they have tamed.

creatureHunted ? string[]

Ids of the creatures they hunt.

creatureProtected ? string[]

Ids of the creatures they protect.

creatureEncountered ? string[]

Ids of the creatures they have met.

creatureCompanion ? string[]

Ids of the creatures that travel with them.

creatureFamiliar ? string[]

Ids of the creatures bound to them.

itemOwner ? string[]

Ids of the items they own.

itemCreator ? string[]

Ids of the items they made.

itemDiscovered ? string[]

Ids of the items they found.

itemGuardian ? string[]

Ids of the items they guard.

itemExOwner ? string[]

Ids of the items they used to own.

itemSeeker ? string[]

Ids of the items they are looking for.

eventParticipant ? string[]

Ids of the events they took part in.

eventKeyFigure ? string[]

Ids of the events they were central to.

eventCausedBy ? string[]

Ids of the events they brought about.

eventWitness ? string[]

Ids of the events they saw.

eventVictim ? string[]

Ids of the events done to them.

eventHero ? string[]

Ids of the events they came out of well.

src/app/domain/project/models/character.model.ts

Collection #

5 required of 5

A named grouping of entries that cuts across the folder tree. An entry can be in any number of collections and stays exactly where it is in the tree. Nothing on the entry itself records the membership: it exists only in items here.

id string

Stable identifier, a UUID.

name string

What the writer called the collection.

createdAt number

When the collection was created, epoch milliseconds.

lastModified number

When the collection last changed, epoch milliseconds.

Its members, in the order the writer arranged them.

src/app/domain/project/models/colletions.interface.ts

CollectionItem #

2 required of 2

One entry inside a , and which array of the project to find it in.

id string

Id of the or .

type 'file' | 'doc'

Which of the two it is, since ids alone do not say.

src/app/domain/project/models/colletions.interface.ts

Creature #

1 required of 25

Also has every field of BaseWorldbuildingElement .

A beast, a monster or anything else alive that is not a of people. habitat and habitatIds are the usual pair: the first is what the writer typed, the second is the locations they picked.

type 'creature'

Always creature. The tag that says which interface applies to this element.

creatureType ? 'beast' | 'monster' | 'mythical' | 'domesticated' | 'magical' | 'undead' | 'elemental' | 'other'

What sort of creature it is.

behavior ? 'friendly' | 'hostile' | 'neutral' | 'varies' | 'territorial' | 'protective'

How it acts towards people.

intelligence ? 'animal' | 'low' | 'moderate' | 'high' | 'genius'

How much it understands.

lifespan ? string

How long it lives, as text.

habitat ? string[]

Where it lives, as text.

habitatIds ? string[]

Ids of the elements where it lives.

diet ? 'carnivore' | 'herbivore' | 'omnivore' | 'magical' | 'parasitic' | 'energy'

What it eats.

rarity ? 'common' | 'uncommon' | 'rare' | 'legendary' | 'unique' | 'extinct'

How often it is met, extinct included.

physicalTraits ? string[]

How it looks, as text.

abilities ? string[]

What it can do, as text.

weaknesses ? string[]

What it cannot stand, as text.

size ? 'tiny' | 'small' | 'medium' | 'large' | 'huge' | 'colossal'

Roughly how big it is.

domesticatable ? boolean

Whether it can be tamed at all.

magicalProperties ? string[]

What is unusual about it, as text.

relationshipWithSpecies ? { speciesId: string; relationshipType: 'domesticated' | 'feared' | 'worshipped' | 'hunted' | 'symbiotic' | 'neutral'; description?: string; }[]

How each species in the project regards it.

knownLocations ? string[]

Where it has been seen, as text.

knownLocationIds ? string[]

Ids of the elements where it has been seen.

culturalSignificance ? string

What it means to the people of the world, as one block of text.

averageSize ? string

Typical size, as text, alongside the coarse size band.

socialStructure ? string

How they live together, as one block of text.

encounteredBy ? string[]

Who has met it, as text.

tamedBy ? string[]

Who has tamed it, as text.

huntedBy ? string[]

Who hunts it, as text.

protectedBy ? string[]

Who protects it, as text.

src/app/domain/project/models/worldbuilding/creature.interface.ts

CustomField #

4 required of 10

One field in a .

id string

Stable identifier, and the key the value is stored under in customFields.

name string

Internal name of the field.

label string

What the writer sees beside the input.

What kind of input it is, which decides what the stored value looks like.

placeholder ? string

Grey text shown in the empty input.

description ? string

Help text shown under the input.

defaultValue ? any

What a new element starts with in this field.

Rules the value is checked against.

relationshipConfig ? RelationshipConfig

For a relationship field, what it may point at.

order ? number

Where the field sits in the form, ascending.

src/app/domain/project/models/worldbuilding/custom-field.interface.ts

CustomFieldType #

'text' | 'textarea' | 'checkbox' | 'relationship'

src/app/domain/project/models/worldbuilding/custom-field.interface.ts

CustomFieldValidation #

0 required of 4

The rules a is checked against as the writer fills it in.

required ? boolean

Whether the field has to be filled in.

minLength ? number

Shortest accepted value.

maxLength ? number

Longest accepted value.

pattern ? string

A regular expression the value has to match, as a string.

src/app/domain/project/models/worldbuilding/custom-field.interface.ts

CustomWorldbuildingElement #

4 required of 6

Also has every field of BaseWorldbuildingElement .

An element of a kind the writer invented, described by one of the project's s. The template says which fields exist; this holds what was put in them. A reader that does not know the template still gets the values, keyed by field id, and can look the labels up in Project.customWorldbuildingTemplates.

type string

Not one of the built-in kinds. Holds the template's own type string.

customType string

Id of the this element follows.

customTypeName string

The template's name, copied here so the element reads on its own.

customTypeIcon ? string

The template's icon, copied here.

customTypeColor ? string

The template's colour, copied here.

customFields { [fieldId: string]: any }

The values, keyed by the id of the in the template.

src/app/domain/project/models/worldbuilding/custom-worldbuilding.interface.ts

CustomWorldbuildingTemplate #

7 required of 11

A kind of worldbuilding element the writer defined themselves. The template is the schema and holds the data. They are stored apart, in Project.customWorldbuildingTemplates and Project.worldbuilding, so a tool reading one needs the other to put labels on the values.

id string

Stable identifier, and what an element's customType points at.

name string

What the writer called this kind of element.

description ? string

What it is for, in the writer's words.

icon string

Icon shown for elements of this kind.

color string

Colour used for elements of this kind, as CSS.

fields CustomField []

The fields elements of this kind have. See .

createdAt number

When the template was created, epoch milliseconds.

updatedAt number

When the template last changed, epoch milliseconds.

archived ? boolean

Archived templates stay in the file so their elements keep their labels.

tags ? string[]

Tags on the template itself, not on its elements.

version ? number

Bumped when the field list changes, so older elements can be recognised as older.

src/app/domain/project/models/worldbuilding/custom-worldbuilding-template.interface.ts

Deity #

1 required of 32

Also has every field of BaseWorldbuildingElement .

A god, or something close enough to be worshipped. Several things here come in pairs: temples beside templeIds, followers beside followerIds. The plain one is what the writer typed and the Ids one is what they picked from the project. Both can hold something at once and neither is derived from the other, so a reader that wants everything has to look at both.

type 'deity'

Always deity. The tag that says which interface applies to this element.

deityType ? 'god' | 'goddess' | 'demigod' | 'titan' | 'spirit' | 'angel' | 'demon' | 'ancestor' | 'elemental' | 'other'

What sort of divine being it is.

domains ? string[]

What it is the god of, as text.

alignment ? 'good' | 'neutral' | 'evil' | 'chaotic' | 'lawful' | 'balanced' | 'unknown'

Where it stands morally.

powerLevel ? 'lesser' | 'intermediate' | 'greater' | 'overdeity' | 'quasi-deity'

How much power it has, relative to the rest of the pantheon.

physicalDescription ? string

What it looks like when it appears, as one block of text.

symbols ? string[]

Its symbols, as text.

holyDays ? { name: string; date?: string; significance?: string; rituals?: string[]; }[]

The dates in its calendar that matter.

followers ? string[]

Its followers, as text.

followerIds ? string[]

Ids of the elements that follow it.

clergy ? string[]

Its clergy, as text.

clergyIds ? string[]

Ids of the elements that serve as its clergy.

temples ? string[]

Its temples, as text.

templeIds ? string[]

Ids of the elements that are its temples.

artifacts ? string[]

Objects tied to it, as text.

artifactIds ? string[]

Ids of the elements tied to it.

enemies ? string[]

Who it opposes, as text.

allies ? string[]

Who stands with it, as text.

parentDeity ? string

Id of the deity it descends from, which is how a pantheon's family tree is built.

childrenDeities ? string[]

Ids of the deities that descend from it.

worshippedBy ? string[]

Who worships it, as text.

worshippedByIds ? string[]

Ids of the elements that worship it.

religionIds ? string[]

Ids of the elements it belongs to.

myths ? string[]

The stories told about it, as text.

prayers ? string[]

What is said to it, as text.

offerings ? string[]

What is given to it, as text.

manifestations ? string[]

How it shows itself in the world, as text.

intervention ? 'active' | 'passive' | 'dormant' | 'dead' | 'unknown'

How involved it is in mortal affairs.

moralCode ? string[]

What it demands of its followers, as text.

champions ? string[]

Who acts in its name, as text.

enemies_deities ? string[]

Ids of the deities it is at odds with, as picked from the project.

allies_deities ? string[]

Ids of the deities it is allied with, as picked from the project.

src/app/domain/project/models/worldbuilding/deity.interface.ts

ExtraField #

4 required of 4

A field the writer added to one element by hand, without defining a template for it.

id string

Stable identifier of the field within its element.

label string

What the writer called it.

value string

What they put in it, always as text.

type 'text' | 'textarea'

Whether it is shown as a single line or a box.

src/app/domain/project/models/worldbuilding/base-worldbuilding.interface.ts

Faction #

1 required of 14

Also has every field of BaseWorldbuildingElement .

An organised group with an agenda: a party, an order, a guild, a syndicate.

type 'faction'

Always faction. The tag that says which interface applies to this element.

factionType ? 'political' | 'religious' | 'military' | 'economic' | 'criminal' | 'academic' | 'other'

What kind of faction it is.

ideology ? string

What it believes, as text.

goals ? string[]

What it is trying to achieve, as text.

structure ? 'hierarchy' | 'democracy' | 'council' | 'anarchy' | 'other'

How it is organised internally.

territory ? string[]

What it holds, as text.

resources ? string[]

What it can draw on, as text.

allies ? string[]

Ids of the factions it is allied with.

enemies ? string[]

Ids of the factions it is at odds with.

leaderIds ? string[]

Ids of the characters or elements who lead it.

memberIds ? string[]

Ids of the characters or elements who belong to it.

foundedDate ? string

When it was founded, in the world's own calendar, so free text.

status ? 'active' | 'disbanded' | 'dormant' | 'unknown'

Whether it still exists.

influence ? 'local' | 'regional' | 'national' | 'continental' | 'global' | 'interplanetary'

How far its reach goes.

src/app/domain/project/models/worldbuilding/faction.interface.ts

FileSnapshot #

4 required of 5

A saved version of a chapter or document. A snapshot is a full copy of the text at a moment in time, kept in its own file next to every other content file. Nothing about it says which entry it came from: that link exists only in the snapshots array it is listed in.

id string

Stable identifier, a UUID.

location string

Where the saved text is: files/<location>.json, alongside live content.

name string

What the writer called this version, or the automatic label it was given.

createdAt number

When the version was taken, epoch milliseconds.

writingMode ? WritingMode

The writing mode the text was in when it was saved.

src/app/domain/project/models/file-snapshot.interface.ts

FlowMap #

6 required of 6

A flowmap: nodes and arrows on a free canvas, for mapping how the story connects.

id string

Stable identifier, a UUID.

name string

What the writer called this flowmap.

nodes FlowMapNode []

Its nodes. Position is on the node itself, so the order here means nothing.

connections FlowMapConnection []

The arrows between them.

createdAt number

When the flowmap was created, epoch milliseconds.

lastModified number

When the flowmap last changed, epoch milliseconds.

src/app/domain/project/models/flowmap.interface.ts

FlowMapArrowType #

'simple' | 'bidirectional' | 'unidirectional-forward' | 'unidirectional-backward' | 'dotted'

src/app/domain/project/models/flowmap.interface.ts

FlowMapConnection #

4 required of 8

An arrow between two flowmap nodes.

id string

Stable identifier of the connection.

fromNodeId string

Id of the the arrow leaves.

toNodeId string

Id of the the arrow reaches.

What the arrow looks like, and which way it points.

label ? string

Text drawn on the arrow.

startEdgePosition ? number

Where on the source node's edge the arrow starts.

endEdgePosition ? number

Where on the target node's edge the arrow lands.

color ? string

Colour of the arrow, as CSS.

src/app/domain/project/models/flowmap.interface.ts

FlowMapNode #

6 required of 17

A box on a flowmap.

id string

Stable identifier, and what a connection's fromNodeId and toNodeId point at.

label string

The text in the node.

x number

Horizontal position on the canvas, in pixels.

y number

Vertical position on the canvas, in pixels.

What shape the node is drawn as. Not a fixed set: a custom string is allowed.

color string

Colour of the node, as CSS.

title ? string

A small label above the node's text ("DECISION", "ACT II"). The writer types it. It sits where the shape's type name used to be drawn, which told nobody anything. Without it the node shows only label.

padding ? number

Padding inside the node, in pixels, chosen by hand. Without it the shape's own padding applies, set in SCSS: every shape needs its own, since a circle has to keep its text off the curve, but the value that suits three words smothers one.

extendedText ? string

Longer text kept with the node and shown when it is opened.

noteColor ? string

Colour key for a note node: yellow, green and the rest, rather than CSS.

linkedDocument ? string

Id of the project document tied to this node.

linkedCharacterId ? string

Id of the project character tied to this node.

linkedWorldbuildingId ? string

Id of the project worldbuilding element tied to this node.

todoList ? { id: string; text: string; done: boolean }[]

For a todo-list node, its items.

width ? number

Node width in pixels, when the writer resized it.

height ? number

Node height in pixels, when the writer resized it.

customData ? any

Anything a node type keeps that has no field of its own. Shape depends on type.

src/app/domain/project/models/flowmap.interface.ts

FlowMapNodeType #

'circle' | 'square' | 'rounded' | 'document' | 'todo-list' | 'simple-list' | 'diamond' | string

src/app/domain/project/models/flowmap.interface.ts

Group #

1 required of 28

Also has every field of BaseWorldbuildingElement .

A smaller body of people than a : a family, a guild, a coven, a crew. Like , some things come in pairs. territory is what the writer typed and territoryIds is what they picked from the project's locations.

type 'group'

Always group. The tag that says which interface applies to this element.

groupType ? 'family' | 'guild' | 'clan' | 'cult' | 'gang' | 'tribe' | 'order' | 'circle' | 'brotherhood' | 'society' | 'other'

What sort of group it is.

size ? number

How many belong to it.

parentFaction ? string

Id of the it sits under, when it is part of a larger body.

leadership ? string

How it is led, as one block of text.

leaderIds ? string[]

Ids of the elements that lead it.

memberIds ? string[]

Ids of the elements that belong to it.

requirements ? string[]

What it takes to join, as text.

benefits ? string[]

What members get out of it, as text.

traditions ? string[]

What it always does, as text.

meetingPlace ? string

Where it meets, as text.

meetingPlaceId ? string

Id of the where it meets.

foundedDate ? string

When it was founded, in the world's own calendar, so free text.

status ? 'active' | 'disbanded' | 'dormant' | 'secret' | 'unknown'

Whether it still exists, and whether anyone knows.

influence ? 'local' | 'regional' | 'widespread' | 'limited'

How far its reach goes.

goals ? string[]

What it is trying to achieve, as text.

rituals ? string[]

What it does together, as text.

hierarchy ? string

How rank works inside it, as one block of text.

territory ? string[]

What it holds, as text.

territoryIds ? string[]

Ids of the elements it holds.

resources ? string[]

What it can draw on, as text.

allies ? string[]

Ids of the groups it is allied with.

enemies ? string[]

Ids of the groups it is at odds with.

secrets ? string[]

What it keeps quiet, as text.

initiationProcess ? string

How somebody gets in, as one block of text.

socialStatus ? 'respected' | 'feared' | 'neutral' | 'outcast' | 'unknown'

How the world at large regards it.

relatedFactions ? string[]

Ids of the elements it is connected to.

homeBase ? string

Where it is based, as text.

src/app/domain/project/models/worldbuilding/group.interface.ts

ImagesModel #

class 7 required of 12

An image stored in the project. The bytes are a file under the project's images/ folder. This object is the metadata that travels in the manifest, and it is deliberately the only thing that does: nothing here is base64, so a project with a hundred illustrations still has a small manifest.

id string

Stable identifier, a UUID.

title string

The name shown to the writer, which is not the file name on disk.

fileName string

The file's name inside images/, extension included.

relativePath string

Path under the project, normally images/<fileName>. See imageStorageKey.

size number

File size in bytes.

mimeType string

MIME type of the stored bytes, for example image/png.

width ? number

Pixel width, when it was measured.

height ? number

Pixel height, when it was measured.

createdAt Date

When the image was added. Typed Date, which means JSON.stringify writes it as an ISO-8601 string rather than the epoch milliseconds used almost everywhere else.

hash ? string

Hash of the bytes, used to spot a real change.

lastModified ? number

When the image metadata last changed, epoch milliseconds.

treePath ? string

Position in the file tree, the parent's path plus the name, mirroring AudioAsset.treePath. Undefined means the image has no place of its own and shows up in the fixed Images folder.

src/app/domain/project/models/images.model.ts

InlineNote #

2 required of 9

A small note pinned inside a corkboard cell, alongside whatever the cell already holds.

id string

Stable identifier of the note within its cell.

What the note is, which decides which of the fields below carry anything.

content ? string

The note's text.

title ? string

A heading for the note.

color ? string

Colour of the note, as CSS.

checked ? boolean

For a checkbox note, whether it is ticked.

imageUrl ? string

Project asset (tintero-image://<key>) or a plain remote URL typed by the user.

audioAssetId ? string

AudioAsset.id in Project.audioAssets. Audio is always a project asset, never a remote URL.

pdfAssetId ? string

PdfAsset.id in Project.pdfAssets.

src/app/domain/project/models/cardboard.interface.ts

InlineNoteKind #

'sticky' | 'checkbox' | 'image' | 'audio' | 'pdf'

src/app/domain/project/models/cardboard.interface.ts

Item #

1 required of 27

Also has every field of BaseWorldbuildingElement .

An object that matters to the story: a sword, a letter, a crown, a key. The where-and-whose fields come in pairs. currentOwner is the name the writer typed and currentOwnerId is the element they picked, and the two are kept independently.

type 'item'

Always item. The tag that says which interface applies to this element.

itemType ? 'weapon' | 'armor' | 'tool' | 'jewelry' | 'document' | 'artifact' | 'clothing' | 'consumable' | 'currency' | 'key' | 'book' | 'other'

What sort of object it is.

rarity ? 'common' | 'uncommon' | 'rare' | 'legendary' | 'unique' | 'cursed'

How rare it is, cursed included, since that is how the writer thinks of it.

value ? string

What it is worth, as text, since worlds do not agree on currency.

properties ? string[]

What it does, as text.

magicalProperties ? string[]

What it does that is not ordinary, as text.

origin ? string

Where it came from, as one block of text.

currentLocation ? string

Where it is now, as text.

currentLocationId ? string

Id of the it is in now.

currentOwner ? string

Who has it now, as text.

currentOwnerId ? string

Id of the element that has it now.

previousOwners ? string[]

Who had it before, as text.

previousOwnerIds ? string[]

Ids of the elements that had it before.

condition ? 'pristine' | 'excellent' | 'good' | 'worn' | 'damaged' | 'broken' | 'destroyed'

What state it is in.

materials ? string[]

What it is made of, as text.

weight ? string

What it weighs, as text.

dimensions ? string

How big it is, as text.

requirements ? string[]

What it takes to use it, as text.

effects ? string[]

What happens when it is used, as text.

limitations ? string[]

What it cannot do, as text.

culturalSignificance ? string

What it means to the people of the world, as one block of text.

historicalEvents ? { eventName: string; date?: string; description?: string; }[]

Things that happened to it, written inline rather than linked to event elements.

relatedItems ? string[]

Ids of the items connected to it.

associatedFactions ? string[]

Ids of the elements connected to it.

associatedGroups ? string[]

Ids of the elements connected to it.

createdBy ? string

Who made it, as text.

discoveredBy ? string

Who found it, as text.

src/app/domain/project/models/worldbuilding/item.interface.ts

Language #

1 required of 10

Also has every field of BaseWorldbuildingElement .

A language spoken in the world.

type 'language'

Always language. The tag that says which interface applies to this element.

speakers ? string[]

Who speaks it, as text.

speakerCount ? number

How many speakers it has.

writingSystem ? string

How it is written down, as text.

familyGroup ? string

The family it belongs to, as text.

dialects ? string[]

Its dialects, as text.

commonPhrases ? { phrase: string; meaning: string; context?: string; }[]

A small phrasebook the writer keeps with the language.

culturalSignificance ? string

What the language means to the people who speak it, as one block of text.

status ? 'thriving' | 'declining' | 'dead' | 'ceremonial'

Whether it is still in use.

relatedLanguages ? string[]

Nearby languages, as text.

src/app/domain/project/models/worldbuilding/language.interface.ts

Location #

1 required of 17

Also has every field of BaseWorldbuildingElement .

A place in the world, from a room to a planet.

type 'location'

Always location. The tag that says which interface applies to this element.

locationType ? 'city' | 'village' | 'region' | 'country' | 'continent' | 'planet' | 'building' | 'landmark' | 'other'

What scale of place it is.

parentLocationId ? string

Id of the location this one sits inside, which is how the place hierarchy is built.

climate ? string

The climate, as text.

terrain ? string[]

Terrain types, as words the writer typed.

population ? number

How many people live there.

governmentType ? string

How the place is governed, as text.

rulerIds ? string[]

Ids of the characters or elements who rule it.

notableFeatures ? string[]

Things worth mentioning about the place, as text.

economy ? string[]

What the place lives on, as text.

defenses ? string[]

How it is defended, as text.

threats ? string[]

What threatens it, as text.

history ? string

The place's history, as one block of text.

culturalNotes ? string

Notes on its culture, as one block of text.

languages ? string[]

Ids of the elements spoken there.

currency ? string

What they use for money, as text.

importantEvents ? { eventName: string; date?: string; description?: string; }[]

Things that happened here, written inline rather than linked to event elements.

src/app/domain/project/models/worldbuilding/location.interface.ts

MagicSystem #

1 required of 10

Also has every field of BaseWorldbuildingElement .

How magic works in this world: where it comes from and what it takes.

type 'magicSystem'

Always magicSystem. The tag that says which interface applies to this element.

sourceOfPower ? string

Where the power comes from, as one block of text.

limitations ? string[]

What it cannot do, as text.

costs ? string[]

What using it costs, as text.

practitioners ? string[]

Who can use it, as text.

schools ? { name?: string; focus?: string; commonSpells?: string[]; }[]

The traditions within the system, written inline.

artifacts ? string[]

Objects tied to the system, as text.

forbiddenMagic ? string[]

What is off limits, as text.

socialAcceptance ? 'accepted' | 'feared' | 'regulated' | 'forbidden'

How the world at large treats it.

learningMethod ? 'innate' | 'study' | 'training' | 'bloodline' | 'divine' | 'other'

How somebody comes to be able to use it.

src/app/domain/project/models/worldbuilding/magic-system.interface.ts

NotesModel #

class 5 required of 7

A sticky note. Notes are not part of the tree. A note either floats free in the project or is pinned to one chapter through fileId, and its text lives in its own file like everything else.

id string

Stable identifier, a UUID.

fileId string | null

The chapter this note is pinned to, or null for a note that belongs to the project.

type string

The note's colour, which is also what the writer sorts and filters them by.

location string

Where the note's text is: files/<location>.json.

textAssociated string | null

The passage the note was attached to, kept so the note survives the text moving.

hash ? string

SHA-256 of the note's content file, used by sync.

lastModified ? number

When the note last changed, epoch milliseconds.

src/app/domain/project/models/notes.model.ts

Occupation #

1 required of 12

Also has every field of BaseWorldbuildingElement .

A trade or role somebody in the world can hold.

type 'occupation'

Always occupation. The tag that says which interface applies to this element.

category ? 'combat' | 'crafting' | 'scholarly' | 'service' | 'leadership' | 'artistic' | 'spiritual' | 'other'

What sort of work it is.

requiredSkills ? string[]

What it takes to do the job, as text.

commonTraits ? string[]

What the people who do it tend to be like, as text.

socialStatus ? 'low' | 'middle' | 'high' | 'varies'

Where it puts a person socially.

averageIncome ? string

What it pays, as text.

workingConditions ? string

What the work is like, as one block of text.

trainingRequired ? string

What training it needs, as one block of text.

advancementPath ? string[]

Where the job leads, as text.

relatedOccupations ? string[]

Nearby trades, as text.

typicalEmployers ? string[]

Who tends to employ them, as text.

commonSpecies ? string[]

Which species tend to do it, as text.

src/app/domain/project/models/worldbuilding/occupation.interface.ts

PdfAsset #

class 7 required of 10

A PDF document attached to the project (research, contracts, style guides, proofs…), parallel to / . The bytes live on disk under the project's pdfs/ folder (written via IOIntegrationInterface.savePdfToProject); this object is the metadata that travels inside Project.pdfAssets.

id string

Stable identifier, a UUID.

title string

The name shown to the writer.

fileName string

The file's name inside pdfs/, extension included.

relativePath string

Path under the project, normally pdfs/<fileName>.

size number

File size in bytes.

mimeType string

MIME type of the stored bytes, in practice application/pdf.

pageCount ? number

Page count, when known. Filled in lazily the first time the PDF is rendered.

createdAt Date

When the PDF was attached. Typed Date, so it serialises as an ISO-8601 string.

hash ? string

Hash of the bytes, used to spot a real change.

treePath ? string

Position in the file tree, the parent's path plus the name, mirroring AudioAsset.treePath. Undefined means the PDF shows up in the fixed PDFs folder.

src/app/domain/project/models/pdf-asset.model.ts

PlotGrid #

7 required of 8

A plot grid: the story laid out as a table, one column per strand.

id string

Stable identifier, a UUID.

name string

What the writer called this grid.

columns PlotGridColumn []

Its columns, in the order they are shown.

rowCount number

How many rows the grid has. Cells beyond this are not shown.

The cells that hold something. Empty ones are simply absent.

createdAt number

When the grid was created, epoch milliseconds.

lastModified number

When the grid last changed, epoch milliseconds.

rowNotes ? PlotGridRowNote []

Banners across whole rows. Absent in grids made before they existed.

src/app/domain/project/models/plotgrid.interface.ts

PlotGridCell #

4 required of 7

One cell of a plot grid. Addressed by column id and row number rather than by a pair of indices, so reordering the columns does not touch the cells. Empty cells are simply absent from the list.

id string

Stable identifier of the cell.

What the cell holds: nothing yet, a chapter, or a note.

columnId string

Id of the the cell sits in.

rowIndex number

Which row the cell sits in, zero based.

referenceId ? string

Id of the chapter the cell stands for, when its type is chapter.

content ? string

The cell's text.

color ? string

Colour of the cell, as CSS.

src/app/domain/project/models/plotgrid.interface.ts

PlotGridCellType #

'unassigned' | 'chapter' | 'note'

src/app/domain/project/models/plotgrid.interface.ts

PlotGridColumn #

3 required of 3

A column of a plot grid: a strand of the story, or whatever the writer decides.

id string

Stable identifier, and what a cell's columnId points at.

name string

What the writer called the column.

position number

Where the column sits, left to right, ascending.

src/app/domain/project/models/plotgrid.interface.ts

PlotGridRowNote #

3 required of 5

A banner across a whole row of a plot grid. It marks something that belongs to the plot rather than to one cell: the start of an arc, an act break, an event that touches every strand at once.

id string

Stable identifier of the banner.

rowIndex number

Which row it sits ABOVE, zero based. A value equal to the grid's rowCount puts it at the very bottom, under the last row.

content string

What the banner says.

color ? string

Colour of the banner, as CSS.

height ? number

How tall the banner is, in pixels. Absent means the default of 34.

src/app/domain/project/models/plotgrid.interface.ts

ProjectDoc #

7 required of 8

Also has every field of ProjectFileBase .

A document: everything the writer keeps that is not the manuscript itself. Outlines, research, notes to self. Same shape as a and stored the same way, in files/<location>.json. What separates the two is the array it is listed in, so a reader cannot tell a chapter from a research note by looking at the entry alone. The fields it redeclares are inherited from and repeated here.

id string

Stable identifier, a UUID.

name string

The name shown in the tree.

title string

Display title. Usually the same as name.

location string

Where the text is: files/<location>.json.

treePath string

Position in the sidebar tree, a slash separated path of names.

createdAt number

When the document was created, epoch milliseconds.

lastModified number

When the document last changed, epoch milliseconds.

snapshots ? FileSnapshot []

Saved versions. Optional here and temporary in practice, since a document picks them up mainly when live sync has to keep the server's copy of a conflict around.

src/app/domain/project/models/project-doc.interface.ts

ProjectFile #

1 required of 11

Also has every field of ProjectFileBase .

A manuscript entry: a chapter, or a piece of one. This is the half of the project that becomes the book. Everything the writer keeps alongside it, research, outlines, character sheets, is a instead. The distinction is not in the shape, it is which array of the manifest the entry sits in.

summary ? string

Short summary of the chapter, written by the writer.

synopsis ? string

Longer synopsis, kept separately from summary and shown in the outline views.

order ? number | null

Place in the reading order of the manuscript, ascending. Null or undefined sorts last. Separate from position, which orders the tree: the two can disagree on purpose.

snapshots FileSnapshot []

Saved versions of this chapter. Each one keeps its own text under files/.

charactersManuallyExcluded ? string[]

Character ids the writer took off the detected list for this chapter.

charactersManuallyIncluded ? string[]

Character ids the writer added to the detected list for this chapter.

charactersIncluded ? string[]

The character ids that end up counted as appearing here, after both manual lists.

status ? string | null

Editorial status, matching one of the project's configured statuses.

bookRole ? string | null

Role in the exported book (a BookRole). Null or undefined means an ordinary chapter.

readOrder ? boolean

False takes the chapter out of the reading order without deleting it.

scenes ? Scene []

Scenes marked inside the chapter's text, mirroring its scene nodes.

src/app/domain/project/models/project-file.interface.ts

ProjectFileBase #

8 required of 18

What every entry in the tree has, whether it is a chapter or a document. The entry is metadata only. Its text lives in a separate file addressed by location, which is the single most important thing to know when reading a project from outside: nothing here contains a word the writer typed.

id string

Stable identifier, a UUID. What every other part of the project refers to it by.

name string

The name shown in the tree, and the one the writer edits when they rename it.

title string

Display title. Usually the same as name.

location string

Where the text is: files/<location>.json, holding ProseMirror JSON. In practice this holds the same value as id, but it is the field to follow rather than the id, since nothing guarantees they stay equal.

treePath string

Position in the sidebar tree as a slash separated path of names, built from the parent's path plus this entry's name. A node at the root is just its own name. The fixed panels prefix theirs with *characters* or *worldbuilding*.

createdAt number

When the entry was created, epoch milliseconds.

lastModified number

When the entry or its text last changed, epoch milliseconds.

statusHistory ? StatusHistory []

The trail of editorial statuses this entry has been through, newest last.

links ? string[]

Ids of other entries linked from this one.

hash string

SHA-256 of the content file, used by sync to tell a real change from a rewrite.

color ? string

Colour chosen for the tree row, as CSS. Undefined means the theme decides.

customIcon ? string

Icon chosen for the tree row. Undefined means the default for the entry type.

wordNumber ? number

Cached word count of the content file. A cache, so it can lag behind the text.

keywords ? string[]

Keywords the writer attached to the entry.

customMetadata ? Record<string, string>

Metadata fields the writer defined and filled in themselves.

systemMetadata ? Record<string, string>

Metadata the app writes about the entry, session and writing metrics among it. Never editable by the writer, unlike customMetadata. See system-metadata.util.ts.

writingMode ? WritingMode

Which editor this entry opens in: prose, screenplay or theatre.

position ? number

Sort order among its siblings in the tree.

src/app/domain/project/models/project-file.base.interface.ts

ProjectFolder #

3 required of 7

A folder in the sidebar tree. It holds nothing. What is inside it is worked out from the treePath of the entries, not from a list of children here, so moving a folder means rewriting the paths of everything under it.

id string

Stable identifier, a UUID.

title string

The folder's name, as shown in the tree.

treePath string

Its own path in the tree, which every entry inside it is prefixed with.

color ? string

Colour chosen for the tree row, as CSS.

customIcon ? string

Icon chosen for the tree row.

lastModified ? number

When the folder last changed, epoch milliseconds.

position ? number

Sort order among its siblings.

src/app/domain/project/models/project-folder.interface.ts

Relationship #

2 required of 5

A tie from one character to another. Stored on one side only. When isBidirectional is set, the other character's side of it is worked out from inverseType rather than written down again, so a reader walking the cast will see each pair once and has to mirror it themselves.

characterId string

Id of the on the other end.

type string

What this character is to them, in the writer's own words: "brother", "rival".

description ? string

The detail behind the tie.

isBidirectional ? boolean

Whether the tie also holds in the other direction.

inverseType ? string

What the other character is to this one, when the tie runs both ways.

src/app/domain/project/models/character.model.ts

RelationshipConfig #

1 required of 2

What a relationship field is allowed to point at.

allowedTypes string[]

Which element types can be picked, by their type tag.

multiple ? boolean

Whether more than one can be picked.

src/app/domain/project/models/worldbuilding/custom-field.interface.ts

Religion #

1 required of 11

Also has every field of BaseWorldbuildingElement .

A faith: what is believed, who is worshipped and what is done about it.

type 'religion'

Always religion. The tag that says which interface applies to this element.

deityIds ? string[]

Ids of the elements it worships.

beliefs ? string[]

What it holds to be true, as text.

practices ? string[]

What its followers do, as text.

holyTexts ? string[]

Its scriptures, as text.

clergy ? { rank: string; responsibilities?: string[]; requirements?: string[]; }[]

Its ranks of clergy, written inline rather than as elements of their own.

temples ? string[]

Ids of the elements that serve as its temples.

holyDays ? { name: string; date?: string; significance?: string; }[]

The dates in its calendar that matter.

followersCount ? number

How many follow it.

influence ? 'local' | 'regional' | 'widespread' | 'dominant'

How far its reach goes.

relationshipWithOtherReligions ? { religionId: string; relationship: 'allied' | 'neutral' | 'competitive' | 'hostile'; description?: string; }[]

Where it stands with the other faiths in the project.

src/app/domain/project/models/worldbuilding/religion.interface.ts

Scene #

6 required of 12

A scene marked inside a chapter. Two halves that have to agree. The text carries a scene node whose sceneId attribute points here, and this entry carries everything about the scene that is not text. Reading a project from outside, the node tells you where a scene starts and ends and this tells you what it is.

id string

Stable identifier, matching the sceneId attribute of the node in the text.

name ? string

What the writer called the scene. Absent means it is shown by its position.

povCharacterId string | null

The character whose point of view the scene is written from, or null for none.

charactersInScene ? string[] | null

Ids of the characters who appear in the scene.

objectsInScene ? string[] | null

Ids of the worldbuilding elements that appear in the scene.

What kind of scene it is, which is also what colours it in the editor.

locationId string | null

The worldbuilding location the scene happens in, or null for none.

createdAt number

When the scene was created, epoch milliseconds.

updatedAt number

When the scene last changed, epoch milliseconds.

startOffset ? number

Cached start position of the scene node in the document. The node is the truth.

endOffset ? number

Cached end position of the scene node in the document. The node is the truth.

notes ? string

The writer's notes about the scene, as plain text.

src/app/domain/project/models/scene.interface.ts

SceneType #

MAIN_CONTINUITY FLASHBACK DREAM VISION MEMORY PROLOGUE EPILOGUE INTERLUDE MONTAGE

src/app/domain/project/models/scene.interface.ts

Species #

1 required of 14

Also has every field of BaseWorldbuildingElement .

A kind of people or being that the world is populated with.

type 'species'

Always species. The tag that says which interface applies to this element.

physicalTraits ? string[]

How they look, as text.

abilities ? string[]

What they can do, as text.

lifespan ? string

How long they live, as text.

homeworld ? string

Where they come from, as text.

culture ? string

Their culture, as one block of text.

language ? string[]

Ids of the elements they speak.

dietType ? 'omnivore' | 'carnivore' | 'herbivore' | 'other'

What they eat.

averageHeight ? string

Typical height, as text, since worlds do not agree on units.

socialStructure ? string

How they organise themselves, as one block of text.

commonOccupations ? string[]

Ids of the elements common among them.

alliedSpecies ? string[]

Ids of the species they are allied with.

neutralSpecies ? string[]

Ids of the species they are neutral towards.

hostileSpecies ? string[]

Ids of the species they are hostile to.

src/app/domain/project/models/worldbuilding/species.interface.ts

StatusHistory #

2 required of 2

One step in an entry's editorial life: what it became, and when.

status string

The status it moved to, matching one of the project's configured statuses.

dateTimestamp number

When it moved, epoch milliseconds.

src/app/domain/project/models/status-history.interface.ts

Technology #

1 required of 10

Also has every field of BaseWorldbuildingElement .

A piece of technology, from a plough to a jump drive.

type 'technology'

Always technology. The tag that says which interface applies to this element.

techLevel ? 'primitive' | 'medieval' | 'renaissance' | 'industrial' | 'modern' | 'futuristic' | 'mixed'

Roughly what era it belongs to.

category ? 'transportation' | 'communication' | 'warfare' | 'medicine' | 'agriculture' | 'energy' | 'other'

What it is for.

functionality ? string

What it does, as one block of text.

creators ? string[]

Who made it, as text.

users ? string[]

Who uses it, as text.

rarity ? 'common' | 'uncommon' | 'rare' | 'legendary' | 'unique'

How rare it is.

requirements ? string[]

What it needs to work, as text.

sideEffects ? string[]

What it does that nobody intended, as text.

relatedTechnologies ? string[]

Nearby technologies, as text.

src/app/domain/project/models/worldbuilding/technology.interface.ts

TimelineAxisMetric #

2 required of 3

How a timeline labels its axis. Labels only: none of this is a real date.

unit ? string

What goes before the number: "Year", "Day", "Chapter". Empty means just the number.

start number

The value of the first column.

step number

How much each column adds.

src/app/domain/project/models/timeline.interface.ts

TimelineBlockData #

3 required of 11

One bar on a timeline lane, standing for a chapter or for an event.

id string

Stable identifier of the block.

kind ? 'document' | 'event'

What the block stands for. Absent means document, which is what every block created before this field existed is, so nothing had to be migrated.

fileId ? string

Id of the manuscript entry. Required when kind is document.

sceneId ? string

Id of the inside that entry, when the block is one scene rather than all of it.

eventId ? string

Id of a worldbuilding element of type event. Required when kind is event. Half the structure of a novel is things that happen and are written in no chapter. The event already exists in the project, with its date and duration, and this is what lets it be placed on the line.

childTimelineId ? string

Id of a timeline that drills into this block.

startCol number

Which column the block starts at.

spanCols number

How many columns it covers.

color ? string

Colour of the block, as CSS.

characterId ? string

Id of the project character tied to this block.

worldbuildingId ? string

Id of the project worldbuilding element tied to this block.

src/app/domain/project/models/timeline.interface.ts

TimelineData #

6 required of 11

A timeline: the story laid out along an axis, in lanes. The axis is not made of dates. A column is a unit of pace the writer chooses, and axisMetric only says how to label it, so nothing here can be read as a calendar.

id string

Stable identifier, a UUID.

name string

What the writer called this timeline.

parentId ? string

Id of the timeline this one hangs off, when a block on that one drills into this.

The lanes, top to bottom.

milestones ? TimelineMilestoneData []

Milestones of the whole story. A first turning point or a climax does not belong to one strand, so its line crosses every lane. The per-lane still exist for marking something inside one lane, which is now the exception rather than the rule.

segments ? TimelineSegmentData []

Named stretches of the axis: acts, parts, seasons, whatever the writer decides. They turn a bare grid into something readable without forcing a column to be a date.

How the axis is labelled. Absent means columns numbered from 1, which is what timelines had before this existed. These are not real dates: the writer picks the metric ("year 8123 to 9123", "day 1 to 40", "session 1 to 12"), which is why a starting value and a step are all it takes.

unassignedNotes TimelineNoteData []

Notes that have not been put on a lane yet.

customWidth ? number

Column width in pixels, when the writer set one.

createdAt number

When the timeline was created, epoch milliseconds.

lastModified number

When the timeline last changed, epoch milliseconds.

src/app/domain/project/models/timeline.interface.ts

TimelineLaneData #

6 required of 7

One horizontal strand of a timeline.

id string

Stable identifier of the lane.

name string

What the writer called the lane.

collapsed boolean

Whether the lane is folded shut.

customHeight ? number

Lane height in pixels, when the writer set one.

The blocks on this lane.

Notes pinned to this lane.

Milestones that belong to this lane alone, rather than to the whole story.

src/app/domain/project/models/timeline.interface.ts

TimelineMilestoneData #

4 required of 4

A marked moment on a timeline, drawn as a line down the lanes it applies to.

id string

Stable identifier of the milestone.

text string

What the milestone says.

color string

Colour of the line, as CSS.

position number

Which column it sits at.

src/app/domain/project/models/timeline.interface.ts

TimelineNoteData #

4 required of 4

A note pinned to a timeline, either on a lane or waiting to be put on one.

id string

Stable identifier of the note.

text string

What the note says.

color string

Colour of the note, as CSS.

position number

Which column it sits at.

src/app/domain/project/models/timeline.interface.ts

TimelineSegmentData #

4 required of 5

A named stretch of a timeline's axis: an act, a part, a season.

id string

Stable identifier of the segment.

name string

What the writer called it.

startCol number

Which column it starts at.

spanCols number

How many columns it covers.

color ? string

Colour of the segment, as CSS.

src/app/domain/project/models/timeline.interface.ts

WordCountLog #

3 required of 3

One day of writing, as the statistics and the goals read it.

dayTimestamp number

The day this row is for, epoch milliseconds at the start of that day.

count number

Words written that day.

objective number

The daily target in force that day, kept so past days are not rescored later.

src/app/domain/project/models/WordCountLog.ts

WorldbuildingElement #

| Species | Faction | Occupation | Location | Religion | MagicSystem | Technology | Language | WorldbuildingEvent | Creature | Item | Group | CharacterInterface | Deity | CustomWorldbuildingElement

src/app/domain/project/models/worldbuilding/worldbuilding-event.interface.ts

WorldbuildingEvent #

1 required of 12

Also has every field of BaseWorldbuildingElement .

Something that happened in the world's history.

type 'event'

Always event. The tag that says which interface applies to this element.

eventType ? 'war' | 'disaster' | 'discovery' | 'political' | 'religious' | 'social' | 'personal' | 'other'

What kind of event it was.

date ? string

When it happened, in the world's own calendar, so free text rather than a date.

duration ? string

How long it lasted, as text.

locationIds ? string[]

Ids of the elements where it happened.

participantIds ? string[]

Ids of the elements that took part in it.

causes ? string[]

What led to it, as text.

consequences ? string[]

What came of it, as text.

keyFigures ? string[]

Who mattered in it, as text rather than as ids.

relatedEvents ? string[]

Other events it connects to, as text rather than as ids.

historicalSignificance ? string

Why it matters to the world, as one block of text.

publicKnowledge ? 'widely-known' | 'limited-knowledge' | 'secret' | 'forgotten'

How much of the world knows about it, which is a plot fact rather than a historical one.

src/app/domain/project/models/worldbuilding/worldbuilding-event.interface.ts

WritingGoal #

5 required of 8

A writing target the writer set for themselves. It lives inside Project, like wordCountLog, so it syncs between devices without a backend of its own. Progress is NOT stored: it is worked out from the logs every time, in GoalProgressService, so nothing here can disagree with the record of what was written.

id string

Stable identifier, a UUID.

What is being counted: words, chapters, characters, streak days and so on.

Over what period it is counted.

target number

How many of type count as meeting the goal in one cadence.

title ? string

The writer's own title. When absent the interface builds one from the other fields.

createdAt number

When the goal was created, epoch milliseconds.

lastModified ? number

The sync clock, updated on every change. Goals written before this existed fall back to createdAt. Incremental pull spots changes by timestamp, so a goal without one is invisible to it.

archivedAt ? number | null

Soft delete. Archived goals are kept so a sync merge does not resurrect them.

src/app/domain/project/models/writing-goal.interface.ts

WritingGoalCadence #

'daily' | 'weekly' | 'monthly' | 'total'

src/app/domain/project/models/writing-goal.interface.ts

WritingGoalType #

| 'words' | 'chapters' | 'chaptersCreated' | 'characters' | 'worldbuilding' | 'streak' | 'minutes'

src/app/domain/project/models/writing-goal.interface.ts

WritingMinutesLog #

2 required of 2

One day of time spent writing, fed by the timer rather than by counting words.

dayTimestamp number

The day this row is for, epoch milliseconds at the start of that day.

minutes number

Minutes written that day.

src/app/domain/project/models/WritingMinutesLog.ts

WritingMode #

Which editor an entry opens in, and which nodes its text is allowed to use.

PROSE SCREENPLAY THEATRE

src/app/domain/project/models/project-file.interface.ts