Repository navigation
Architecture Overview
OpenNote ships on Windows first, then macOS, Linux, iOS, and Android. The architecture keeps most code shared, so a port means writing new adapters, not rewriting features. The choice is recorded in an architecture decision record (ADR), ADR 0001.
| Part | Technology | Job |
|---|---|---|
| Shell | Tauri 2, written in Rust, with Microsoft Edge WebView2 on Windows | Creates the window, the menus, and the commands that the interface calls |
| Core | Rust library crates | Document model, file format, storage, undo history, search index, audio, and import and export |
| Interface | TypeScript, React, and Vite | What you see: the shell, the editor, ink, and views |
The exe stays small, at about 15 to 30 MB, because it uses the WebView2 that ships with Windows 10 and 11 instead of bundling a browser.
React interface (TypeScript) <--- commands and events ---> Rust shell ---> Rust core crates
shown in WebView2 Tauri IPC
- The interface calls Rust commands through Tauri's inter-process communication (IPC). Tauri 2 grants each command to a window by name.
- Rust sends events back to the interface, for example when a page changes on disk.
- Anything platform-specific sits behind a small Rust or TypeScript interface. Pen input, audio capture, optical character recognition (OCR), and neural processing unit (NPU) acceleration each get one.
- Drawing bypasses React. Ink goes straight to a canvas, so a stroke never waits for a React render.
| Layer | Choice |
|---|---|
| Rich text | ProseMirror through Tiptap |
| Ink | A custom canvas renderer with Pointer Events, and perfect-freehand for stroke shapes |
| Charts | Observable Plot, which gives vector output that stays sharp in PDFs |
| Math | KaTeX to display, MathLive to edit |
| Code and diagrams | CodeMirror 6 and Mermaid, loaded only when a page uses them |
| Search | SQLite full-text search (FTS5) through rusqlite |
| Audio | cpal for capture, Opus for storage |
| On-device intelligence | whisper.cpp for speech, and Windows.Media.Ocr for images |
| Language | TypeScript pinned to 6.0.x until typescript-eslint supports TypeScript 7 (ADR 0003) |
- A notebook is a folder, sections are subfolders, and each page is a folder.
- A page holds
page.json, anassetsfolder for images, PDFs, and audio, andpage.md. -
page.jsonis the source of truth. It stores blocks (text, ink, tables, charts, math, and images) with positions and timestamps. Text inside blocks is Markdown. - Ink stores raw points: position, pressure, tilt, and time.
-
page.mdis a readable copy, written on every save. - Every file carries a
formatVersion, and tested migrations upgrade old files. - Saves are atomic: write a temporary file, flush it, then rename it.
- The search index lives in the local app data folder. It is a cache that can be rebuilt at any time.
The format is designed in Phase 3 and will be published in docs/format/.
The stack must give one codebase on every platform, a small download, pen input drawn within 25 ms, a portable core, and a large pool of contributors. Flutter, Electron, WinUI 3, and Qt were considered and rejected. The decision holds only if ink is fast enough in WebView2. Phase 1 measured it, and the Flutter fallback didn't trigger. See Phase 1 spike results.
OpenNote is licensed under the Apache License 2.0. Repository | Issues | Releases
- Getting started
- Installing and updating
- Where your notes are stored and how they stay safe
- Notebooks, sections, and pages
- Typed notes
- Ink and drawing
- Audio recording
- Math and study tools
- Productivity and study tools
- Tables and charts
- Search and links
- Page views, printing, and PDF
- Import and export
- On-device intelligence
- Settings and Connectors
- Keyboard shortcuts
- Accessibility
- Privacy and your data
- Troubleshooting
- FAQ