Skip to content

The tramme-project/1 project format

A project is a set of files in fixed places. The same files live in storage (an R2 prefix, or a folder on disk) while you work, and in a .tramme archive (zip) to import or export. Any other file is refused: that is what makes it possible to check a project before accepting it.

tramme.json manifest (required)
document.tramme.json the document, schema tramme/1 (required, see document.md)
assets/ files used by the document
plugins/ JS modules declared in the document's "plugins"
thumbnail.webp home screen thumbnail (or .png, .jpg; optional)
.tramme/chats/ the assistant's conversations (<id>.json) and their index (index.json)
.tramme/chat.json single conversation of older projects (read, then moved into chats/)
renders/ exports kept in the project (never in an archive)

The format’s code is in packages/project.

{
"format": "tramme-project/1",
"id": "showcase-3n174m",
"name": "Showcase",
"created": "2026-10-01T12:17:40.210Z",
"modified": "2026-10-01T13:02:11.032Z",
"width": 1920, "height": 1080, "duration": 6,
"thumbnail": "thumbnail.webp",
"app": "tramme"
}
  • id: lowercase letters, digits and hyphens, 3 to 64 characters. An imported project always gets a new id; nothing is overwritten.
  • width, height, duration: the main composition, for the home screen. The server keeps them up to date each time the document is saved, along with modified.
  • No other key is allowed.
  • Relative paths, separated by /, without . or .., without control characters or <>:"|?*, 300 characters at most.
  • assets/: images (png, jpg, webp, gif, avif, svg), fonts (ttf, otf, woff, woff2), sounds (wav, mp3, ogg, m4a, flac), videos (mp4, webm, mov), data (json), modules (js, mjs), documents (pdf, md). Sounds and videos up to 4 GiB (uploaded in parts), other files 95 MB. The editor puts the video of a project made from a video in assets/video/, files attached to the assistant in assets/chat/, the sources of a project made from sources (documents, pictures, videos, sounds, the fonts its kit names) in assets/sources/, with its kit, when one came with them, at assets/sources/kit.json, and transcripts in assets/transcripts/: { "version": 1, "duration", "language", "words": [{ "w", "s", "e" }] }, times in seconds; the transcript of an edit also carries keeps (the passages kept) and its times are composition times. The brief of the project lives in assets/brief.json ({ "version": 1, "kind": "brief", "updated", "format", "look", "motion", "sound", "about", "sources", "tone", "rules" }: the facts come from the document; what the piece is about, what each source is good for, the tone and the rules are the assistant’s and the user’s; the document holds it as the brief asset, and the assistant reads it before it works). The blocks saved from a selection live in assets/blocks/ ({ "version": 1, "kind": "block", "name", "from", "size", "layers", "order", "needs" }), each held by the document as a block- asset.
  • plugins/: js, mjs.
  • renders/: mp4, webm, mov, gif, png, zip, json, svg, wav.
  • 95 MB per file, 2000 files per project, 95 MB per archive.

Before a project enters storage (archive import, tramme unpack, tramme pack):

  1. Structure: allowed paths and extensions, sizes, a valid manifest, a document matching the tramme/1 schema, every asset of the document present in the project (relative src, never leaving the project), every plugin declared by a module asset.
  2. Code, asked about: if the archive carries code — plugins, or expressions in the document — the import lists them (the plugins with their file and size, the expressions with their first addresses) and asks before any of it runs. A refusal stops the import and nothing enters storage. The editor’s own examples skip the question.
  3. Meaning: the plugins are loaded, then the document is validated against the full vocabulary (node types, properties, references, expressions, nested compositions without cycles).

The server checks the document’s structure again on every write.

A zip of the project’s files, without renders/. Media that is already compressed is stored as is. On reading, entries that are too large are refused before decompression; an archive whose whole content sits in a single folder (a zip made by hand) is accepted.

Terminal window
tramme pack examples/launch-film --out launch-film.tramme
tramme unpack launch-film.tramme --out launch-film