An .is file is a ZIP archive containing one IdeaSketch document. It is a document format, not a directory Workspace package. Workspace state belongs in the selected directory's .ideanote/ metadata folder.
IdeaNote resolves document types symmetrically on both sides of the Tauri boundary:
- The frontend File Type Registry selects a document model, parser, serializer, and editor key.
- The backend Document Format Registry selects an independent format module for recognition, validation, reading, writing, and save safety.
- Generic Tauri commands exchange a typed document envelope and do not inspect IdeaSketch manifest or Page fields.
The current registry contains IdeaSketch (.is) and Markdown (.md). Future IdeaTable and IdeaWorkflow modules can be registered without duplicating Workspace/Standalone persistence logic.
Markdown files remain ordinary UTF-8 text files. They are not wrapped in JSON, ZIP, or Workspace metadata.
- Opening rejects invalid UTF-8 without modifying the file.
- A UTF-8 BOM is detected and preserved on save.
- LF and CRLF are detected, normalized to LF only inside the mounted CodeMirror document, and restored when serialized.
- An untouched mixed-ending file is preserved byte-for-byte. Once edited, the user must explicitly choose LF or CRLF before saving.
- CodeMirror is authoritative for normal and Agent edits, so native editor Undo/Redo remains the only history system.
- Preview uses
react-markdownwith GFM. Common semantic Markdown HTML is parsed and passed through an explicit allowlist sanitizer before joining the preview DOM. Script, event, form, embedded browsing, unsafe URL, and style-injection capabilities are rejected. Fencedhtmlblocks use a separate sanitizediframepreview with an empty sandbox permission set and a restrictive CSP; fencedmermaidblocks render in Mermaid strict security mode. Ordinary fenced blocks remain inert highlighted source. - Local preview images are loaded only through a document-directory-confined Tauri command. Traversal, remote image fetching, unsupported image types, and files above 10 MB are rejected.
Markdown saves use the same collision-free staging and atomic replacement boundary as IdeaSketch. Workspace Mode stages under <workspace>/.ideanote/tmp/; Single File Mode uses safe target-filesystem staging and does not create .ideanote/.
Versions use MAJOR.MINOR decimal notation. The manifest header and version value are read before any Page payload.
| Version | Read | Write | Behavior |
|---|---|---|---|
1.0 |
Yes | Yes | Canonical IdeaSketch format used for new files and all saves. |
2.0 |
Header only | No | Protected legacy Workspace format. It is never hydrated, flattened, or overwritten by the v1 writer. |
| Other | No | No | Missing, malformed, old-unknown, and future versions fail safely. |
Opening 2.0 returns a structured legacy-protected result with a migration-deferred message. Workspace Import/Export and v2 migration are not part of the current MVP.
manifest.json
slides/{page-id}.json
media/index.json # optional legacy compatibility
media/{media-id}.{extension} # optional legacy compatibility
The writer always emits manifest.json and one slides/{id}.json entry per ordered manifest Page. It emits media/ entries only when legacy media payloads are explicitly supplied. Current Excalidraw image data normally remains inline in the scene files object.
{
"version": "1.0",
"created": "2026-08-03T10:00:00Z",
"modified": "2026-08-03T10:05:00Z",
"slides": [
{ "id": "page-1", "title": "Overview" },
{ "id": "page-2", "title": "Research" }
]
}Requirements:
versionis exactly1.0for writable documents.createdremains stable across saves;modifiedis refreshed by the IdeaSketch writer.slidescontains at least one Page and defines presentation order.- Every Page
idis unique and contains only ASCII letters, digits,_, or-. - Every Page has exactly one matching
slides/{id}.jsonpayload. - Missing, duplicate, orphan, or non-object Page payloads are rejected.
- Page titles and order are preserved exactly.
{
"type": "excalidraw",
"version": 2,
"elements": [],
"appState": {},
"files": {}
}The complete Excalidraw scene is preserved, including elements, application state, inline files, and Camera data stored by the editor. Presentation behavior is derived from the current IdeaSketch document and does not add a separate archive schema.
Saving validates the complete manifest, Page relationship, scene payloads, and optional media before replacing the target.
- Build the new ZIP in memory.
- In Workspace Mode, write it to a collision-free staging file under
<workspace>/.ideanote/tmp/; in Single File Mode, use the target filesystem's safe local staging strategy without creating.ideanote/. - Atomically commit the staging file over the target on the same filesystem.
- If replacement fails, retain the original target and remove the temporary file.
The writer does not create sibling .is.tmp or .is.bak files in Workspace Mode. A cross-filesystem commit fails safely instead of copying over or deleting the original target.
Older v1 archives may store binary images under media/ with an optional media/index.json. The reader reconstructs those bytes for the frontend adapter. A later save may keep images inline in Excalidraw files and omit media/; this does not change the v1 manifest or Page contract.