# aixploits/ignis architecture

> Architecture diagram of the GitHub repository aixploits/ignis, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-22). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/aixploits/ignis
- Repository: https://github.com/aixploits/ignis

## Overview

1. **Top-level shape**
   - Ignis is a monorepo split into a browser-facing client layer and a self-hosted server layer.
   - The main product is the `apps/ignis-server` application, with shared packages under `packages/` for the shim, bridge plugin, UI components, and core server utilities.

2. **Primary runtime boundary**
   - The browser runs Obsidian UI code, but not native Electron.
   - Ignis inserts a compatibility shim that emulates the Electron/Node APIs Obsidian expects, while the server keeps the vault files on disk and mediates access to them.

3. **Server application**
   - `apps/ignis-server/server/` is the central backend runtime.
   - It exposes HTTP routes, manages vault access, serves static assets, handles settings, proxies cross-origin requests when needed, and hosts server-side plugins.
   - The Dockerized server downloads Obsidian from its official source at first run; Obsidian itself is not vendored in the repo.

4. **Browser-side bridge into Obsidian**
   - `packages/bridge/` is the client-side Obsidian plugin that wires Ignis features into the app.
   - It adds Ignis-specific settings tabs, status-bar indicators, workspace controls, plugin-related UI, and file actions such as upload/download.
   - This package is the “integration surface” between the shimmed runtime and the user-visible Obsidian UI.

5. **Compatibility shim layer**
   - `packages/shim/` is the core emulation layer.
   - It provides browser-compatible replacements for Electron APIs, Node modules, filesystem primitives, workspace handling, request/proxy behavior, WebSocket client behavior, and other globals Obsidian or community plugins expect.
   - This package is what allows Obsidian’s renderer code to execute in a normal browser instead of Electron.

6. **Shared server primitives**
   - `packages/server-core/` contains lower-level infrastructure used by the server runtime.
   - It includes filesystem/path helpers, WebSocket plumbing, error types, file-watcher logic, and write coalescing to reduce churn on slow or networked storage.
   - This is the “core infra” boundary beneath route handlers and higher-level vault/plugin services.

7. **Vault/service boundary**
   - `packages/services/` and server routes together form the vault-access layer.
   - The vault service abstraction is where file reads/writes, metadata, watching, and synchronization concerns are concentrated before they are exposed to the browser.
   - In the architecture diagram, this sits between HTTP/WebSocket endpoints and the actual mounted vault filesystem.

8. **HTTP/API surface**
   - `apps/ignis-server/server/routes/` defines the external server API.
   - Key route groups include bootstrap, filesystem operations, vault management, settings, plugin management, proxying, and version reporting.
   - `bootstrap` is especially important: the README notes a pre-compressed bootstrap response that bundles vault info, vault list, metadata tree, and plugin list into one startup call.

9. **Real-time collaboration and tab sync**
   - Ignis uses WebSockets for live synchronization between browser tabs on the same vault.
   - The server publishes file/state changes; browser tabs subscribe and update within seconds.
   - Shared utilities in `server-core` support the watcher and WS transport needed for this cross-tab synchronization loop.

10. **Server-side plugin system**
    - Ignis has its own server plugin system separate from Obsidian’s community plugins.
    - The plugin system code under `apps/ignis-server/server/plugin-system/` handles discovery, config storage, lifecycle management, and Obsidian-facing plugin packaging.
    - This is a distinct extension boundary from client-side community plugins: it extends the server itself, not just the browser runtime.

11. **Headless sync as a server plugin**
    - `apps/ignis-server/server/plugins/headless-sync/` is the main example of the server plugin model.
    - It provides continuous sync without a browser tab, with auth, broadcasting, route handling, and an Obsidian-side companion plugin under `obsidian/`.
    - The README notes it is mutually exclusive with Obsidian Sync per vault, making sync mode a vault-level server policy.

12. **UI package**
    - `packages/ui/` contains reusable Svelte-based UI components and views.
    - These are used for vault management, sync setup, dialogs, and common controls that support the Ignis-specific UX inside Obsidian.
    - In the diagram, this is the presentation layer consumed by the bridge plugin.

13. **Deployment and edge boundaries**
    - The repo includes Docker and compose assets, plus examples for reverse-proxy setups such as Caddy and Authelia/basic-auth.
    - HTTPS or localhost is materially important because browser crypto and clipboard APIs are required for full functionality; plain HTTP on non-localhost origins degrades features like graph view, outline, and sync.
    - External access to some resources may be proxied through Ignis, or fetched directly for allowlisted CORS-friendly hosts.

14. **Operational/performance concerns**
    - The architecture is optimized for large vaults and slow storage using cache-backed content access, indexer prefetch, and optional write coalescing.
    - There is an LRU content cache, bounded memory behavior, and filesystem-watch driven refresh rather than loading the whole vault into memory.
    - These concerns sit mainly in the server-core/shim/filesystem path, not in the UI.

15. **What to show in a diagram**
    - Draw three major zones: browser tab running Obsidian + shim + bridge/UI, the Ignis server runtime, and the mounted vault filesystem.
    - Add side paths for WebSocket sync, HTTP bootstrap/API calls, proxy requests, and the optional server-plugin subsystem.
    - Show the headless-sync plugin as a server-side extension that can operate without an active browser tab.

Main entry points: [`apps/ignis-server/server/index.js`](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/index.js) (Server app), [`apps/ignis-server/server/routes/bootstrap.js`](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/routes/bootstrap.js) (HTTP routes), [`packages/bridge/src/main.js`](https://github.com/aixploits/ignis/blob/main/packages/bridge/src/main.js) (Bridge plugin), [`apps/ignis-server/server/plugins/headless-sync/index.js`](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugins/headless-sync/index.js) (Headless sync)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_browser["Browser layer"]
  node_obsidian_ui["Obsidian UI<br/>browser runtime"]
  node_shim["Shim<br/>compat layer<br/>[init.js]"]
  node_bridge["Bridge plugin<br/>obsidian plugin<br/>[main.js]"]
  node_headless_obsidian["Sync companion<br/>obsidian plugin<br/>[main.js]"]
end

subgraph group_server["Server layer"]
  node_server_entry["Server app<br/>backend entry<br/>[index.js]"]
  node_routes["HTTP routes<br/>api surface<br/>[bootstrap.js]"]
  node_proxy["Proxy layer<br/>request mediation<br/>[proxy.js]"]
  node_settings["Settings store<br/>config service<br/>[settings.js]"]
  node_plugin_system["Plugin system<br/>extension runtime<br/>[manager.js]"]
  node_headless_sync["Headless sync<br/>server plugin<br/>[index.js]"]
  node_assets["Static assets<br/>frontend assets<br/>[index.html]"]
end

subgraph group_shared["Shared packages"]
  node_ui["UI kit<br/>svelte components<br/>[index.js]"]
  node_vault_service["Vault service<br/>storage service<br/>[vault-service.js]"]
  node_server_core["Server core<br/>infra library<br/>[index.js]"]
  node_ws(("WebSocket sync<br/>realtime transport<br/>[ws.js]"))
end

subgraph group_deployment["Deployment"]
  node_docker["Docker runtime<br/>deployment"]
  node_vault_fs[("Vault files<br/>mounted filesystem")]
end

node_obsidian_ui -->|"calls APIs"| node_shim
node_shim -->|"requests data"| node_server_entry
node_bridge -->|"extends UI"| node_obsidian_ui
node_bridge -->|"renders controls"| node_ui
node_server_entry -->|"hosts"| node_routes
node_server_entry -->|"loads config"| node_settings
node_server_entry -->|"loads plugins"| node_plugin_system
node_routes -->|"reads/writes"| node_vault_service
node_vault_service -->|"uses infra"| node_server_core
node_vault_service -->|"mediates"| node_vault_fs
node_server_core -->|"implements"| node_ws
node_ws -->|"syncs state"| node_shim
node_routes -->|"proxies requests"| node_proxy
node_plugin_system -->|"manages"| node_headless_sync
node_headless_sync -->|"adds routes"| node_routes
node_headless_sync -->|"broadcasts"| node_ws
node_headless_sync -->|"companion UI"| node_headless_obsidian
node_server_entry -->|"serves shell"| node_assets
node_docker -->|"starts"| node_server_entry
node_docker -->|"mounts"| node_vault_fs
node_bridge -->|"bootstrap calls"| node_routes
node_bridge -->|"subscribes"| node_ws

click node_shim "https://github.com/aixploits/ignis/blob/main/packages/shim/src/init.js"
click node_bridge "https://github.com/aixploits/ignis/blob/main/packages/bridge/src/main.js"
click node_ui "https://github.com/aixploits/ignis/blob/main/packages/ui/src/index.js"
click node_server_entry "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/index.js"
click node_routes "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/routes/bootstrap.js"
click node_vault_service "https://github.com/aixploits/ignis/blob/main/packages/services/src/vault-service.js"
click node_server_core "https://github.com/aixploits/ignis/blob/main/packages/server-core/src/index.js"
click node_ws "https://github.com/aixploits/ignis/blob/main/packages/server-core/src/ws.js"
click node_proxy "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/routes/proxy.js"
click node_settings "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/settings.js"
click node_plugin_system "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugin-system/manager.js"
click node_headless_sync "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugins/headless-sync/index.js"
click node_headless_obsidian "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugins/headless-sync/obsidian/src/main.js"
click node_assets "https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/assets/index.html"
click node_docker "https://github.com/aixploits/ignis/tree/main/apps/ignis-server/Dockerfile"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_obsidian_ui,node_shim,node_bridge,node_headless_obsidian toneBlue
class node_server_entry,node_routes,node_proxy,node_settings,node_plugin_system,node_headless_sync,node_assets toneAmber
class node_ui,node_vault_service,node_server_core,node_ws toneMint
class node_docker,node_vault_fs toneRose
```

## Components

### Browser layer

Obsidian UI running in a normal browser with the compatibility shim and bridge plugin.

- **Obsidian UI**: browser runtime · Renderer-side Obsidian application code executed outside Electron.
- [Shim](https://github.com/aixploits/ignis/blob/main/packages/shim/src/init.js): compat layer · Browser-facing emulation of Electron, Node, filesystem, workspace, request, and WebSocket APIs. · `packages/shim/src/init.js`
- [Bridge plugin](https://github.com/aixploits/ignis/blob/main/packages/bridge/src/main.js): obsidian plugin · Client-side integration surface that adds Ignis settings, status, workspace, and file actions. · `packages/bridge/src/main.js`
- [Sync companion](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugins/headless-sync/obsidian/src/main.js): obsidian plugin · Obsidian-side companion UI and API layer for the headless sync server plugin. · `apps/ignis-server/server/plugins/headless-sync/obsidian/src/main.js`

### Server layer

Ignis backend runtime, HTTP/API surface, vault mediation, and server-side plugins.

- [Server app](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/index.js): backend entry · Main Ignis server process that wires routes, services, assets, and plugin runtime together. · `apps/ignis-server/server/index.js`
- [HTTP routes](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/routes/bootstrap.js): api surface · Bootstrap, filesystem, vault, settings, plugin, proxy, and version endpoints. · `apps/ignis-server/server/routes/bootstrap.js`
- [Proxy layer](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/routes/proxy.js): request mediation · Cross-origin request proxying and request URL handling for allowed external resources. · `apps/ignis-server/server/routes/proxy.js`
- [Settings store](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/settings.js): config service · Server-side settings handling and persistence for vault and runtime configuration. · `apps/ignis-server/server/settings.js`
- [Plugin system](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugin-system/manager.js): extension runtime · Discovery, config storage, lifecycle management, and packaging for Ignis server plugins. · `apps/ignis-server/server/plugin-system/manager.js`
- [Headless sync](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/plugins/headless-sync/index.js): server plugin · Server-side sync plugin that can run without an active browser tab and broadcasts vault changes. · `apps/ignis-server/server/plugins/headless-sync/index.js`
- [Static assets](https://github.com/aixploits/ignis/blob/main/apps/ignis-server/server/assets/index.html): frontend assets · Server-served HTML and CSS entry assets for the browser client shell. · `apps/ignis-server/server/assets/index.html`

### Shared packages

Cross-cutting packages reused by the browser bridge, shim, and server runtime.

- [UI kit](https://github.com/aixploits/ignis/blob/main/packages/ui/src/index.js): svelte components · Reusable Svelte components and views for vault management, sync setup, dialogs, and common controls. · `packages/ui/src/index.js`
- [Vault service](https://github.com/aixploits/ignis/blob/main/packages/services/src/vault-service.js): storage service · Vault access boundary for reads, writes, metadata, watching, and synchronization concerns. · `packages/services/src/vault-service.js`
- [Server core](https://github.com/aixploits/ignis/blob/main/packages/server-core/src/index.js): infra library · Low-level filesystem, path, WebSocket, error, watcher, and write-coalescing primitives. · `packages/server-core/src/index.js`
- [WebSocket sync](https://github.com/aixploits/ignis/blob/main/packages/server-core/src/ws.js): realtime transport · Server/browser live-change channel used for cross-tab synchronization. · `packages/server-core/src/ws.js`

### Deployment

Container, compose, and proxy entrypoints for running Ignis.

- [Docker runtime](https://github.com/aixploits/ignis/tree/main/apps/ignis-server/Dockerfile): deployment · Container and compose assets used to run Ignis and provision Obsidian on first start. · `apps/ignis-server/Dockerfile`
- **Vault files**: mounted filesystem · On-disk vault storage mounted into the server and mediated through the vault service.

## Connections

- Obsidian UI → Shim: calls APIs · Obsidian renderer code relies on Electron/Node/browser shims to run in a normal browser.
- Shim → Server app: requests data · The shim forwards filesystem, request, and runtime operations to the server.
- Bridge plugin → Obsidian UI: extends UI · The bridge injects Ignis-specific settings, status, workspace, and file actions into Obsidian.
- Bridge plugin → UI kit: renders controls · The bridge reuses shared UI components and views for Ignis-specific interactions.
- Server app → HTTP routes: hosts · The server entrypoint mounts the external HTTP/API surface.
- Server app → Settings store: loads config · Runtime startup and request handling depend on persisted server settings.
- Server app → Plugin system: loads plugins · The backend initializes and manages server-side extensions.
- HTTP routes → Vault service: reads/writes · API handlers delegate vault operations to the vault service boundary.
- Vault service → Server core: uses infra · Vault access builds on filesystem, watcher, WebSocket, and write-coalescing primitives.
- Vault service → Vault files: mediates · The service is the controlled path to the mounted vault on disk.
- Server core → WebSocket sync: implements · Shared infrastructure provides the WebSocket transport used for live updates.
- WebSocket sync → Shim: syncs state · Browser tabs subscribe to server-published changes through the WebSocket channel.
- HTTP routes → Proxy layer: proxies requests · HTTP endpoints can forward selected cross-origin traffic through Ignis.
- Plugin system → Headless sync: manages · The plugin system discovers and runs the headless sync extension.
- Headless sync → HTTP routes: adds routes · The headless sync plugin contributes its own API and auth endpoints.
- Headless sync → WebSocket sync: broadcasts · Headless sync publishes vault state changes over the realtime channel.
- Headless sync → Sync companion: companion UI · The server plugin ships with an Obsidian-side companion plugin for user interaction.
- Server app → Static assets: serves shell · The server delivers the browser entry assets and overrides.
- Docker runtime → Server app: starts · Container entrypoints launch the server runtime and provision dependencies.
- Docker runtime → Vault files: mounts · Deployment binds the vault directory into the server container.
- Bridge plugin → HTTP routes: bootstrap calls · The browser-side integration fetches startup data and settings via the HTTP API.
- Bridge plugin → WebSocket sync: subscribes · The bridge listens for live server events to keep tabs and UI state in sync.
