Elyra
Elyra The coding agent eTerm The terminal that knows where each command ends Huskarl AI colleagues on your own Mac Starf An activity monitor for Apple silicon that never invents a number etrans An SSH and SFTP client for macOS Elyra VM Virtual machines for macOS, Linux and Windows on your Mac Litr A small, native web browser for macOS Notr A notebook for macOS e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Refr Local-first PDF workspace for macOS Elyra Workspace A desktop workspace for coding agents Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Elyra
The .notespace format

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: 4286593715 is 0xFF803AB3.
  • 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, length in 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:

  • schemaVersion must 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 level is 0 to 2. Versions: at most 20 per page.
  • Block geometry: x and y from 0 to 100,000; width 24 to 20,000; height 12 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.
  • zoom is 0.25 to 4.
  • The file is at most 32 MiB.

Older NoteSpace files without section groups or isCollapsed load as ungrouped and expanded.