Architecture
Standard Red Notes keeps the upstream Standard Notes package split while adding a self-hosted operational layer around it. The user-facing client, server-side services, files, realtime relay, command-line tools, and MCP bridge are separate concerns with explicit boundaries.
Runtime Shape
| Layer | Path | Responsibility |
|---|---|---|
| Web app | app/packages/web |
Browser client, local encryption/decryption, note editing, settings, admin UI, files UI, and local IndexedDB state. |
| Shared client packages | app/packages/* |
Models, crypto helpers, services, editors, icons, styles, mobile/desktop shared code. |
| API gateway and services | server/packages/* |
Auth, sync, files metadata, revisions, gateway routing, websocket gateway, scheduled jobs, server settings, and admin endpoints. |
| Single-container server | Dockerfile.single, docker-compose.single.yml |
Small/self-hosted deployment profile: web app plus all-in-one home server with SQLite and persisted data volume. |
| Multi-container stack | docker-compose.yml |
Production-grade layout with app, gateway, auth/sync/files/revisions services, MySQL, Redis, and queue emulator. |
| CLI tools | cli/ and server/packages/auth/bin/srn_admin.ts |
User-facing encrypted note CLI, operator CLI, and in-container admin helper. |
| MCP bridge | mcp/ |
Stdio or bearer-authenticated HTTP bridge that signs in with account credentials/MFA or a full MCP token, decrypts locally, and keeps writes off by default. |
| Docs and validation | docs/, e2e/ |
Operator docs, API docs, Playwright smoke/correctness/stress tests, and screenshot capture. |
The default Compose profile keeps one public ingress while preserving the server’s internal package boundaries:
flowchart LR
Client["Web, desktop, and mobile clients<br/>encrypt and decrypt locally"]
Front["App nginx front door<br/>only published service"]
subgraph Server["Server container"]
Gateway["API gateway<br/>HTTP and WebSocket entry"]
Auth["Auth and settings"]
Sync["Sync and revisions"]
Files["Files service"]
end
Database[("MariaDB<br/>accounts and encrypted items")]
Uploads[("Uploads volume<br/>encrypted file payloads")]
Cache[("Redis<br/>cache and realtime state")]
Events["floci SNS/SQS<br/>domain-event queues"]
Client -->|"same-origin HTTPS"| Front
Front -->|"/v1, /v2, /auth, /subscription, /sockets"| Gateway
Front -->|"/files"| Files
Gateway --> Auth
Gateway --> Sync
Auth --> Database
Sync --> Database
Files --> Database
Files --> Uploads
Gateway --> Cache
Auth --> Events
Sync --> Events
Files --> Events
Events --> Gateway
Request Flow
- The browser loads the web app from the app front door.
- The app uses same-origin paths for sync, files, auth, and websockets by default.
- The client encrypts notes/files before sending them to server endpoints.
- The gateway routes API calls to auth, sync, files, revisions, and realtime services.
- Server settings and admin registration controls are stored as an overlay so operator changes apply without rebuilding the image.
- Realtime updates travel through the websocket gateway when available, with HTTP sync remaining the fallback path.
Encryption Boundary
The server stores ciphertext for note contents and file payloads. Features that need plaintext either run locally in the client or require explicit operator/user configuration, such as optional AI assistant providers. When an optional feature sends content outside the browser, the UI and docs should name that boundary plainly.
Deployment Profiles
Use the single-container profile for local evaluation, small deployments, and simple backups. Use the multi-container stack when you want independent service scaling, MySQL/Redis, or a reverse-proxy-managed production layout.
Validation Layers
| Check | Scope |
|---|---|
| Unit/render tests | Component behavior, helpers, search, settings panes, editor utilities. |
| TypeScript builds | Package contracts and frontend/server compile integrity. |
| Docker config/build checks | Deployment wiring, environment shape, and image construction. |
| Playwright app-open tests | Real browser bootstrap, styling, console errors, and app responsiveness. |
| Playwright correctness/stress tests | IndexedDB reload integrity, search/tag references, sync push/pull, and large-vault behavior. |
See Validation for the practical commands.