Skip to content

System context

Container view

flowchart LR
    User["User or team member"] --> UI["React and Vite frontend"]
    UI -->|HTTP /api and WebSocket| API["FastAPI backend"]
    API --> Vault["Markdown vault and assets"]
    API --> Local["Local-only SQLite, indexes, caches, secrets"]
    API --> MCP["MCP servers and AI providers"]
    API --> Comms["Mail, calendar, contacts providers"]
    API --> Zotero["Zotero translation-server"]
    API --> Publish["Notion, Drupal, and social services"]
    Desktop["Electron desktop shell"] --> UI
    Desktop --> API
    Office["Office add-ins and web clipper"] --> API

Frontend boundary

The frontend is a React single-page application. app/App.tsx owns the authentication gate and global shell; app/routes.tsx composes routes, Vault scope, redirects and lazy page imports while Home remains eager. app/bootstrap.tsx prepares routing and language; app/AppProviders.tsx preserves the StrictMode → API → router → authentication provider order. The relocation places the CSS entry and bootstrap call in app/main.tsx, with ordered styles in app/styles/index.css. Vite proxies /api and WebSocket traffic during native development.

Module ownership

The reviewed relocation assigns composition, navigation and global integration to app/; product domains to features/; reusable infrastructure, UI, records, routing and API adapters to shared/; and generated contracts to generated/. Generated contracts are regenerated, never edited by hand. The authentication provider belongs to features/auth/context/AuthProvider.tsx, while its reusable context belongs to shared/auth/auth-context.ts.

The frontend/feature-public-entries.json manifest records exact reviewed public paths and their reasons. Existing feature root index entries remain supported; an unlisted neighboring module stays private. Consumers use a root entry or an explicitly reviewed entry directly, including separate lazy imports, without introducing an eager aggregate barrel. The manifest describes access; it does not import modules.

Dependencies may flow from app to features and shared infrastructure. Features never depend on app; shared never depends on features or app, including type-only imports. Moving the existing Markdown/wikilink preview code inside shared infrastructure does not resolve its internal cycle. The relocation must preserve lazy boundaries, styles, routes and payloads; the layout alone is not evidence of completed integration or release.

Components call the backend through typed API adapters in shared/api/. The backend remains responsible for authorizing users, workspaces, vaults and destructive operations.

Backend boundary

backend/server.py creates the FastAPI application and registers domain routers. Route modules translate HTTP contracts into service calls. Business logic belongs in backend/services/; persisted relational entities live in backend/models/; AI orchestration lives in backend/agent/; scheduled work lives in backend/scheduler/ and runtime skills.

The application lifespan starts shared infrastructure, constructs agent capabilities, warms safe indexes, starts mail IDLE workers, and later closes those resources. Optional integration startup is isolated so one unavailable provider does not abort the whole server.

Storage boundaries

The vault and local data have deliberately different durability and synchronization properties:

  • Vault: portable user content; may live on local disk or a cloud-backed file provider.
  • Local data: SQLite, indexes, caches, secrets, logs, checkpoints, and outputs; never cloud-synchronized.
  • Configuration: merged from application defaults, user or vault parameters, environment overrides, and local credential stores.

See data and storage for ownership and rebuild rules.

External systems

All external services are optional domain dependencies. OAuth and credentials are managed locally. Adapters normalize provider-specific behavior for Google, Microsoft, IMAP/SMTP, CalDAV, Notion, Drupal, AI providers, social networks, file providers, and Zotero translation.