Project structure
What a Tintero project looks like on disk, what every file in it is for, and the handful of things that will catch out anyone reading one from outside.
On this page
A Tintero project is a folder, not a file. Nothing in it is compressed, encrypted or deliberately awkward to read. Open one and you will find plain JSON.
That is on purpose. Tintero is not open source, but your writing does not belong to the app: back your projects up your own way, move them somewhere else, convert them, or build a tool that counts something nobody thought to count. Nothing here is in your way, and this page is what every part of that folder is for.
The layout
<project folder>/
<project.id>.tintero the manifest, JSON
files/
<id>.json document content, one file per entry
images/<fileName> raw bytes, original extension
audio/<fileName>
pdfs/<fileName>
backups/
backups.json the backup index
<name>/project.json a full manifest copy
The manifest is named after the project’s own id and ends in .tintero. It holds
everything about the project except two things: the writing, and the binary assets. Those
sit beside it in the folders above.
The manifest
One JSON object, and it is a plain JSON.stringify of the app’s own Project object. There
is no serialiser in between, no field renaming, no custom toJSON. That is what makes the
project format reference a description of the file rather than
a description of a model that resembles it: the TypeScript is the format, and every field
on that page carries the doc comment written next to it in the source.
The way to recognise a Tintero project is the app’s own test: a file matching *.tintero
whose JSON parses and has a string id in it. That is the entire check.
What each kind of entry is
Four arrays in the manifest hold things that have text, and they are the part most people get wrong, because they all have the same shape. There is nothing in an entry that says whether it is a chapter or a research note. The only thing that tells them apart is which array of the manifest lists it.
| In the manifest | What it is | Where its text lives |
|---|---|---|
files | The manuscript. Chapters, and pieces of chapters. | files/<location>.json |
docs | Everything kept alongside it: outlines, research, notes to self. | files/<location>.json |
notes | Sticky notes, either loose or pinned to one chapter. | files/<location>.json |
files[].snapshots | Saved versions of a chapter. A full copy of its text at a moment. | files/<location>.json |
All four land in the same flat files/ folder. A directory listing tells you nothing about
what any of them are, so the manifest is not optional reading.
Following an entry to its text
Every entry has both an id and a location. The text is at
files/<location>.json. In practice location holds the same value as id, but
follow location: nothing in the format guarantees the two stay equal, and a reader that
uses the id will work right up until they diverge.
The folder tree is not a tree
folders holds the sidebar hierarchy, and a folder contains nothing. What is inside it is
worked out from the treePath on each entry, which is the parent’s path plus the entry’s own
name, separated by slashes. An entry at the root is just its own name.
That means moving a folder rewrites the treePath of everything under it, and it means two
entries with the same treePath are a real possibility rather than an impossible state.
Assets
Images, audio and PDFs are files on disk, listed in the manifest as metadata only. Nothing is base64 in a Tintero project, which is why a manuscript with a hundred illustrations still has a small manifest.
Document text refers to a project image with a tintero-image://<key> URL, where the key is
the asset’s relativePath without its images/ prefix, falling back to fileName.
Writing into a project
The same list is why an unrecognised field is not evidence of corruption in the other direction either. A project written by a newer Tintero can carry fields your reader has never seen. Keep them if you are rewriting the file; the writer put something there.
Backups
backups/backups.json is the index, and each backup is a folder holding a full manifest copy
named project.json, not <id>.tintero. Worth knowing if you are scanning a disk for
projects: a match on *.tintero will miss every backup, and a match on project.json will
find backups and .tint archives alike.
The folders, from the source
These are the subfolder names the desktop file system adapter actually uses, extracted rather than typed, because they exist only as string literals scattered through that file and a diagram written by hand is one refactor from being fiction.
images/pdfs/audio/backups/files/