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 applications

Invariants 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.

InstallRepository