03 · Architecture
One knowledge layer. Many interfaces.
Storm is intentionally small. This page is the sketch; depth lives in the repository.
Shape
Clients on macOS, Android, and web — one Flutter codebase — talk REST and a WebSocket to storm-server, a Rust binary you run. The server owns merge, search, tags, attachments, and version history. Notes remain plain Markdown under a storage root you control. Compatible AI agents reach the same vault through MCP.
macOS · Android · Web
│ REST + WebSocket
▼
storm-server (Rust / axum)
│
┌──────┴──────┐
▼ ▼
vaults/*.md state/
plain md indexes · registry
▲
│ MCP
AI applicationsInvariants that matter
- The vault is plain Markdown. Storm state lives in a sibling
state/directory, never mixed into notes. - Notes are tracked by UUID, so renames and moves are metadata, not new identity.
- The server owns the canonical vault. Clients cache and queue; a merged or conflict response means the client adopts the server’s text.
- Conflicts stay in the file. When a merge cannot finish cleanly, markers are written into the note — not a hidden sibling copy.
- Offline is normal. Creates and edits queue on the device and replay when the server returns. Search remains server-side.
- No accounts product. One person, several devices, one token on the network you control.
Go deeper
Living plan and decisions:PLAN.md. Deploy and apt:deploy/. Server and MCP:apps/server/README.md.