.foldervas File Format

Open specification of the document format used by Foldervas — an infinite-canvas organizer. Any application may produce or consume these files.

Version: 1 (schema_version = '1') Status: stable Published: 2026-07-10 License: CC BY 4.0 Download as Markdown ↓

1. Container

A .foldervas file is a single SQLite 3 database. There is no wrapper, no compression, no magic bytes beyond SQLite's own. Any SQLite library in any language can create or read one.

A sibling directory named <filename>.assets/ may exist next to the file. It is an optional performance cache maintained by the reading application (see §10) — generators do not need to create it.

2. Database schema

CREATE TABLE canvas_meta (
  key   TEXT PRIMARY KEY,
  value TEXT
);

CREATE TABLE nodes (
  id                  TEXT PRIMARY KEY,  -- UUID
  type                INTEGER NOT NULL,  -- see §3
  x                   REAL NOT NULL,
  y                   REAL NOT NULL,
  width               REAL NOT NULL,
  height              REAL NOT NULL,
  content             TEXT,
  background_color    TEXT,              -- '#rrggbb', 'none', or NULL
  top_color           TEXT,              -- '#rrggbb' accent strip, or NULL
  z_index             INTEGER DEFAULT 0,
  parent_id           TEXT,              -- NULL = root board
  sort_order          INTEGER DEFAULT 0,
  asset_id            TEXT,              -- FK into assets.id
  is_locked           INTEGER DEFAULT 0,
  lock_aspect_ratio   INTEGER DEFAULT 1,
  gallery_columns     INTEGER DEFAULT 2,
  rich_content        TEXT,              -- reserved, leave NULL
  created_at          TEXT,
  updated_at          TEXT,
  -- columns below may be ABSENT in older files; readers must tolerate that
  source_url          TEXT,              -- link cards: the URL
  gallery_column_hint INTEGER DEFAULT -1,
  file_path           TEXT,              -- reserved, leave NULL
  font_size           INTEGER,           -- notes: base font px; connectors: stroke weight
  icon                TEXT,              -- folders: emoji icon
  connect_start       TEXT,              -- connectors: source node id
  connect_end         TEXT,              -- connectors: target node id or NULL
  caption             TEXT,              -- file cards: caption text
  collapsed           INTEGER DEFAULT 0, -- galleries/columns: header-only
  alias_target        TEXT,              -- aliases: target folder id
  theme               TEXT,              -- folders: board theme (see §7)
  rotation            REAL DEFAULT 0,    -- node rotation in degrees (clockwise)
  curvature           REAL DEFAULT 0,    -- connectors: signed apex offset (px); 0 = straight
  text_color          TEXT,              -- text color (hex); NULL = auto by contrast
  text_align          TEXT,              -- free canvas text: left|center|right (NULL = center)
  line_spacing        REAL               -- notes: line-height factor (NULL = 1.45)
);

CREATE TABLE assets (
  id         TEXT PRIMARY KEY,  -- UUID, referenced by nodes.asset_id
  filename   TEXT NOT NULL,
  mimetype   TEXT NOT NULL,
  data       BLOB NOT NULL,     -- the binary, or zeroblob(0) if externalized
  width      INTEGER,           -- images: natural px
  height     INTEGER,
  size       INTEGER,           -- byte length of the binary
  created_at TEXT
);

CREATE INDEX idx_nodes_parent ON nodes(parent_id);
CREATE INDEX idx_nodes_type   ON nodes(type);

3. Node types

typeNameWhat it isKey columns
0TextNote card, or free canvas text when background_color = 'none'content, font_size
1ImageImage card; content doubles as the visible caption (empty/NULL = bare image)asset_id, content
2AttachmentAny file (PDF, video, audio, …); content = display filenameasset_id, content, caption
3ContainerFolder / board: a navigable sub-canvas. Its children are the nodes whose parent_id points at itcontent (title), icon
5GalleryMasonry auto-layout with gallery_columns columns (1 column = a vertical list)gallery_columns, collapsed
7LineConnector (arrow) between nodes — see §6connect_start, connect_end
8AliasShortcut tile that navigates to another folderalias_target

Values 4 (Column) and 6 (HStack) are legacy: readers convert them to Gallery on load (a legacy Column becomes a 1-column gallery). Writers must not emit them — use a Gallery with gallery_columns = 1 for a vertical list. Other unknown type values degrade to 0 (Text).

4. Hierarchy & coordinates

5. Auto-layout containers (Gallery)

6. Connectors (type 7)

7. Captions, aliases, folders

8. The canvas_meta table

Key/value strings. All keys are optional for writers — readers fall back to the defaults below and clamp out-of-range values.

KeyValueDefaultRange
schema_versionformat version1write 1
nodeCountnumber of rows in nodes (integrity check)—must match if present
lastModifiedISO 8601 timestamp——
zoom, offsetX, offsetYroot board viewport1, 0, 0—
folderViewportsJSON: {"<folderId>": {"zoom":n,"offsetX":n,"offsetY":n}}{}—
drawingsJSON — see §9{}—
trashJSON — deleted subtrees, see below[]—
noteWidthdefault width of new notes (px)280160–560
kanbanWidthdefault width of new galleries/columns280220–640
imageWidthtarget longest side of dropped images280120–560
textHeightdefault height of free canvas text4428–120
defaultFontSizedefault note font size (px)1411–28
defaultNoteColor, defaultFolderColor#rrggbb or empty (theme default)empty—
documentThemedocument-wide theme id (same values as folder theme); folders with their own theme win inside their boardempty—
showGrid1/01—
snapSizesnap grid size (px)28app-clamped

Trash — an array of deleted subtrees, restorable by the user:

[{ "id": "<root node id>", "name": "…", "type": 0,
   "deletedAt": "<ISO>", "nodes": [ /* full node objects, root included */ ] }]

9. Drawings (strokes)

The drawings meta key holds freehand ink, grouped by surface:

{
  "__root__":        [ Stroke, … ],   // root board
  "<folderId>":      [ Stroke, … ],   // a folder's board
  "image:<nodeId>":  [ Stroke, … ]    // ink drawn ON an image node
}

Stroke = {
  "id":      "<uuid>",
  "points":  [x0, y0, x1, y1, …],   // flat pairs, length even, ≥ 2
  "color":   "#rrggbb" | "ink",     // "ink" = adapts to light/dark theme
  "width":   number,                 // px: 2 | 4 | 8 typical
  "opacity": number?                 // 0–1, default 1
}

10. Assets (binaries)

Two valid ways to store a binary; readers support both:

  1. Inline (recommended for generators): put the bytes in assets.data. Single self-contained file.
  2. Externalized: write zeroblob(0) in assets.data and place the raw bytes in the sibling directory <filename>.assets/<asset id> (no extension, filename = the asset UUID). Foldervas itself writes this layout for speed and migrates inline blobs to it on save.

11. Requirements for writers

A generator MUST:

A generator SHOULD:

Readers are defensive by design: unknown node types degrade to Text, malformed colors fall back to theme defaults, out-of-range settings are clamped, dangling connect_*/alias_target references are dropped. A partially conforming file opens; a perfectly conforming file round-trips.

12. Versioning

This page documents version 1. Future revisions will bump schema_version and be published here with a changelog; version 1 files will remain readable. Applications encountering a version newer than they support should refuse to write to the file (never silently downgrade it).