The .notespace format
A .notespace file is a UTF-8 JSON workspace, the format NoteSpace uses for backups.
Notr reads and writes it with the same names, types and limits, so a backup made by
either app opens in the other. Notr uses it for backups and imports; its own storage is
SQLite.
Conventions
- Property names are camelCase.
- Enums are numbers.
- Colors are ARGB as unsigned 32-bit numbers:
4286593715is0xFF803AB3. - Dates are ISO 8601 with an offset, such as
"2026-09-28T15:18:00.123456+02:00". Notr writes at most six fractional digits; it reads any number. - Binary data is base64.
- Text offsets (
start,lengthin marks) are UTF-16 code units. - Unknown properties are ignored, and missing ones take their defaults.
Structure
{
"schemaVersion": 1,
"revision": 42,
"notebooks": [{
"id": "…", "title": "My notebook", "color": 4286593715,
"sectionGroups": [{ "id": "…", "title": "Research", "parentId": null,
"color": 4288832184, "isCollapsed": false }],
"sections": [{
"groupId": null, "id": "…", "title": "Getting started", "color": 4287652792,
"pages": [{
"id": "…", "title": "Welcome", "created": "…", "modified": "…",
"level": 0, "isFavorite": false, "isCollapsed": false,
"paper": 0, "paperColor": 4294967295,
"blocks": [ … ], "ink": [ … ], "versions": [ … ]
}]
}]
}],
"trash": [{ "sectionId": "…", "deleted": "…", "page": { … } }],
"settings": { "selectedPageId": "…", "darkMode": false, "horizontalTabs": false,
"ribbonCollapsed": false, "zoom": 1 }
}
settings.theme is Notr's own: the id of a theme ("nord"), written only when it is
not Notr Light or Notr Dark. darkMode still says whether the theme is dark, so
NoteSpace, which ignores theme, and versions of Notr from before themes show the
notebooks light or dark as before.
Blocks
{
"id": "…", "kind": 0, "x": 48, "y": 145, "width": 600, "height": 52,
"text": "A little space for your big ideas.",
"format": { "fontFamily": "Segoe UI", "fontSize": 27, "bold": true, "italic": false,
"underline": false, "strike": false, "color": 4285542560, "highlight": 0,
"alignment": 0, "bullets": false, "numbered": false },
"marks": [{ "start": 2, "length": 6, "format": { … }, "link": "https://…" }],
"checked": false, "tags": ["Important"], "cells": [["A", "B"], ["1", "2"]],
"data": "iVBORw0…", "fileName": "photo.png", "mediaType": "image/png"
}
A mark's format is complete, not a difference from the block's. Where marks overlap,
the later one wins.
Ink
{ "id": "…", "points": [{ "x": 1, "y": 2, "pressure": 0.5 }],
"color": 4284955319, "width": 3, "tool": 2 }
For shapes, the first and last points are opposite corners (or the ends of a line).
A connector is a line ("tool": 7) with three fields of Notr's own, written only
when set, so other strokes are exactly as NoteSpace writes them:
{ "id": "…", "tool": 7, "points": [ … two points … ], "color": …, "width": 3,
"fromBlockId": "…", "toBlockId": "…", "arrowEnd": true }
fromBlockId and toBlockId are notes on the same page. The points are where the
line was last drawn, so NoteSpace (which ignores the extra fields) shows a plain line
there; Notr works them out again from the notes. A connector whose note isn't on its
page is dropped when the file is read.
Versions
{ "id": "…", "created": "…", "description": "Saved version", "json": "{…page…}" }
json is the page as JSON, without its own versions. id is Notr's: NoteSpace ignores
it, and versions without one get a new ID when read.
Enums
| Enum | Values |
|---|---|
kind |
0 text, 1 heading, 2 to-do, 3 table, 4 picture, 5 attachment, 6 divider |
paper |
0 plain, 1 ruled, 2 grid, 3 dots |
tool |
0 select, 1 type, 2 pen, 3 highlighter, 4 eraser, 5 rectangle, 6 ellipse, 7 line |
alignment |
0 left, 1 center, 2 right |
Validation
Every file is validated completely before it's used; a file that fails is refused
with a message, and nothing is replaced. The rules are in notr-core/src/validate.rs
and groups.rs:
schemaVersionmust be 1.- Every notebook, group, section, page, block and stroke ID is non-empty, at most 100 characters, and unique in the whole workspace.
- Titles are at most 500 characters.
- A group's parent and a section's group must be groups of the same notebook; groups can't form cycles or nest deeper than 8.
- Page
levelis 0 to 2. Versions: at most 20 per page. - Block geometry:
xandyfrom 0 to 100,000;width24 to 20,000;height12 to 20,000; all finite. - Block text: at most 2 MiB (UTF-16); marks at most 10,000 and inside the text; tags at most 100 of at most 200 characters; at most 500 rows of at most 50 cells of at most 100,000 characters; data at most 16 MiB.
- Formats: font size 6 to 144, alignment 0 to 2, family at most 200 characters.
- Strokes: width 0.1 to 100; at most 100,000 points each and 2,000,000 per page; points finite, within ±100,000, pressure 0 to 1.
- Counts: 100 notebooks, 1,000 sections and 1,000 groups per notebook, 10,000 pages, 100,000 blocks, 2,000 pages in the trash.
zoomis 0.25 to 4.- The file is at most 32 MiB.
Older NoteSpace files without section groups or isCollapsed load as ungrouped and
expanded.