Tintero Developers

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 manifestWhat it isWhere its text lives
filesThe manuscript. Chapters, and pieces of chapters.files/<location>.json
docsEverything kept alongside it: outlines, research, notes to self.files/<location>.json
notesSticky notes, either loose or pinned to one chapter.files/<location>.json
files[].snapshotsSaved 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/