Interactive architecture map of Obsidian — the knowledge management app built on local-first Markdown. Covering the Electron/Chromium shell, CodeMirror 6 editor engine, plugin system, graph view, Canvas, Sync & Publish services, theme system, search indexing, backlinks, templates, YAML frontmatter, URI protocol, and mobile architecture.
Obsidian is a knowledge management application built around plain-text Markdown files stored locally on your filesystem. Created by Shida Li and Erica Xu (former Dynalist developers), it combines a powerful editor, bidirectional linking, and an extensible plugin architecture — all running inside an Electron shell with a local-first philosophy.
Obsidian runs as an Electron application, leveraging Chromium for rendering and Node.js for filesystem access. The main process manages windows, native menus, file watchers, and the vault lifecycle, while renderer processes handle the UI, editor, and plugin execution.
The Electron main process manages the application lifecycle: creating BrowserWindows, handling native menus, system tray integration, protocol handlers (obsidian:// URI scheme), auto-updates via electron-updater, and coordinating multi-window vault access.
Each vault window runs in a sandboxed Chromium renderer process. Obsidian uses a custom workspace layout system (not standard HTML tabs) with split panes, stacked tabs, and sidebar panels. The renderer hosts the editor, graph view, and all UI components.
Unlike typical Electron apps, Obsidian enables nodeIntegration in renderer processes for direct filesystem access. This powers the local-first model: notes are read/written via Node.js fs APIs, file watchers detect external changes, and plugins can access Node.js modules.
The obsidian:// custom protocol enables deep linking into vaults. Supports actions like obsidian://open?vault=Name&file=Path, obsidian://new, obsidian://search, and custom plugin-registered actions. Registered via Electron protocol handler.
On iOS and Android, Obsidian uses Capacitor (Ionic) instead of Electron, wrapping the same TypeScript/HTML codebase in a native WebView. Mobile uses platform-native file APIs, iCloud/Google Drive integration, and a touch-optimized UI with swipe gestures.
Desktop builds use electron-updater for automatic updates, checking the Obsidian release API. Updates are downloaded in the background and applied on restart. The installer-less version falls back to manual update prompts.
Obsidian prioritizes local-first data ownership. Your vault is a folder of plain Markdown files — no proprietary database, no vendor lock-in. The app is a "thick client" that does everything locally, with optional cloud services (Sync, Publish) layered on top rather than required.
Obsidian's editor is built on CodeMirror 6, a modular, extensible editor framework. Since the v0.13 "Live Preview" update, Obsidian uses CM6's decoration and widget system to render Markdown inline — blending source editing with WYSIWYG preview.
Obsidian builds on CM6's state management system: EditorState (immutable document state), EditorView (DOM rendering), and Transactions (state changes). The architecture is purely functional — every edit creates a new state rather than mutating.
Live Preview uses CM6 decorations to render Markdown inline. Headings render at their visual size, links become clickable, embeds render inline, and code blocks get syntax highlighting — all while maintaining the source Markdown underneath. The cursor reveals raw syntax.
Markdown parsing uses Lezer, CM6's incremental parser system. Obsidian extends the base Markdown grammar with custom node types for wiki-links ([[link]]), embeds (![[embed]]), callouts, and other Obsidian-specific syntax. Parsing is incremental — only changed regions are re-parsed.
Obsidian includes an optional Vim mode powered by the @replit/codemirror-vim extension (a CM6 port of CodeMirror 5's Vim bindings). Supports normal/insert/visual modes, ex commands, marks, registers, and macros.
A vault is simply a folder on your filesystem. Obsidian reads and writes plain Markdown files, watches for external changes, and maintains an internal metadata cache for fast lookup of links, tags, and frontmatter.
Each vault is a directory containing .md files, attachments, and a hidden .obsidian/ config folder. The vault model is portable — copy the folder to any device and open it. No database, no server, no migration.
Obsidian uses Node.js fs.watch (or platform-native equivalents) to monitor the vault directory recursively. External changes (Git pulls, Syncthing, manual edits) are detected and trigger metadata re-indexing and UI updates.
Settings, plugin configs, themes, and workspace layouts live in .obsidian/. Key files: app.json (global settings), appearance.json (theme), hotkeys.json, workspace.json (pane layout), and per-plugin config in plugins/*/data.json.
On vault open, Obsidian builds an in-memory cache of all file metadata: links, backlinks, tags, headings, frontmatter, aliases, and embeds. This cache powers the graph view, search, quick switcher, and link autocomplete without re-reading files from disk.
Notes can start with a YAML block (--- delimited) defining metadata: tags, aliases, cssclass, publish status, custom properties. The metadata cache parses frontmatter and makes it queryable via the API. Dataview and other plugins heavily leverage this.
Images, PDFs, and other attachments are stored as regular files in the vault (configurable attachment folder). Embeds reference them via wiki-links or Markdown image syntax. Obsidian renders images, audio, video, and PDFs inline in the editor.
Obsidian's plugin architecture is its most powerful feature. Core features like Daily Notes, Backlinks, and Graph View are implemented as "core plugins" using the same API available to community developers. Community plugins run in the renderer process with full access to the Obsidian API and Node.js.
The obsidian npm package exposes the official TypeScript API: Plugin, Editor, Vault, Workspace, MetadataCache, Modal, Setting, and more. Plugins extend the Plugin class and register commands, views, settings tabs, and event handlers.
20+ features are shipped as core plugins: Daily Notes, Backlinks, Graph View, Outgoing Links, Tag Pane, Templates, Word Count, Slash Commands, Outline, Page Preview, Publish, Sync, Canvas, and more. Each can be enabled/disabled independently.
The community plugin directory is hosted as a GitHub repo (obsidianmd/obsidian-releases). Plugin submissions go through a code review process. The app fetches the registry to display available plugins, downloads releases from GitHub, and validates manifests.
Community plugins run in the same renderer process as the app — there is no sandbox. Plugins have full access to the DOM, Node.js APIs, and the Obsidian API. This is a deliberate trade-off: maximum power at the cost of requiring user trust. The review process is the primary safety net.
Plugins can register CodeMirror 6 extensions: custom syntax highlighting, decorations, widgets, keymaps, and state fields. The Editor API provides a high-level wrapper, but plugins can also access the raw CM6 EditorView for advanced customizations.
Plugins can register custom view types that appear as panes in the workspace. Views extend ItemView and can render arbitrary HTML. Examples: Kanban boards, calendar views, database tables, mind maps. Views participate in the workspace layout serialization.
The plugin ecosystem is vast: Dataview (database queries via YAML + inline fields), Templater (advanced templating with JS), Excalidraw (whiteboard), Calendar, Kanban, Tasks, Periodic Notes, Linter, Style Settings, BRAT (beta testing), and many more. Some plugins like Dataview have become near-essential to many workflows.
The Graph View visualizes the link structure of your vault as a force-directed node-link diagram. It uses a WebGL/Canvas 2D rendering engine with a physics simulation for layout, supporting thousands of nodes with interactive zoom, filtering, and coloring.
The graph uses a force simulation (similar to d3-force) with repulsion between all nodes, attraction along links, and centering forces. The simulation runs continuously, converging to a stable layout. Node positions are updated per-frame via requestAnimationFrame.
The graph renderer uses Canvas 2D (not WebGL in the standard build) for drawing nodes and edges. Nodes are drawn as circles with text labels, edges as lines with configurable thickness. The renderer supports zoom and pan via transform matrices.
Graph controls allow filtering by path, tags, and search queries. Color groups can be defined with CSS color values per filter expression. Orphan nodes (no links), attachments, and existing-only notes can be toggled. Depth controls limit the local graph radius.
Each note has a local graph view showing only the note and its neighbors within a configurable depth (1-5 hops). The local graph updates reactively as you navigate between notes, providing context about a note's position in the knowledge network.
Canvas is Obsidian's infinite whiteboard, introduced in v1.1. It stores spatial layouts as .canvas JSON files, allowing users to arrange note cards, media, web embeds, and connection arrows on a 2D surface. Canvas is implemented as a core plugin.
Canvas files are JSON with nodes and edges arrays. Nodes have types (text, file, link, group), positions (x, y), dimensions (width, height), and content. Edges connect nodes with optional labels and colors. The format is documented and readable.
Canvas renders using DOM elements positioned with CSS transforms on an infinite pannable/zoomable surface. Note cards embed full Markdown renderers (the same preview renderer used in reading view). Connection arrows are drawn with SVG path elements.
Canvas supports text cards (inline Markdown), file cards (embedded vault notes with live preview), link cards (web page embeds via iframe), and group cards (colored regions for organizing). Nodes can be resized, colored, and connected with directional arrows.
Obsidian offers two optional paid services. Sync provides end-to-end encrypted vault synchronization across devices. Publish converts selected vault notes into a hosted website. Both are implemented as core plugins communicating with Obsidian's cloud infrastructure.
End-to-end encrypted vault sync with version history (up to 12 months). Uses a custom sync protocol over WebSocket: files are chunked, diffed, and encrypted client-side before upload. Conflicts are resolved with automatic merge or side-by-side comparison. Supports selective folder sync.
Converts selected notes into a static website hosted on publish.obsidian.md or a custom domain. Supports theming (CSS), navigation, graph view, search, and password protection. The publish plugin uploads rendered HTML and assets to Obsidian's CDN.
Sync uses client-side AES-256 encryption. The encryption key is derived from a user-chosen password and never leaves the device. Obsidian's servers store only encrypted blobs — they cannot read your notes. Key stretching uses scrypt for brute-force resistance.
Sync maintains a version history for every file, storing snapshots on each save. Users can browse and restore previous versions from within the app. Versions are stored server-side (encrypted) with configurable retention (1-12 months depending on plan).
Because vaults are plain folders, users can sync with any tool: Git, Syncthing, iCloud, Google Drive, Dropbox, or rsync. The community has built plugins for Git-based sync (obsidian-git) and various cloud providers. Obsidian Sync's advantage is conflict resolution, version history, and E2E encryption.
Obsidian's UI is built with vanilla HTML/CSS/TypeScript, using CSS custom properties for theming. The workspace system manages a tree of split panes, tabs, and sidebars. Themes and CSS snippets can override any visual aspect of the application.
The workspace is a tree of split containers, each holding tab groups. Users can split panes horizontally or vertically, drag tabs between groups, pop out tabs into new windows, and save/restore workspace layouts. The layout serializes to workspace.json.
Obsidian defines 400+ CSS custom properties (variables) for colors, spacing, typography, and component styles. Themes override these variables to completely transform the look. The Style Settings plugin exposes theme variables as UI controls.
Users can add .css files to .obsidian/snippets/ for targeted style overrides without installing a full theme. Snippets are toggled individually in settings. Common uses: custom fonts, heading styles, tag colors, sidebar tweaks.
200+ themes available via the theme browser. Themes are single CSS files hosted on GitHub. Popular themes like Minimal, AnuPpuccin, and Things include extensive customization via the Style Settings plugin. Themes can define both light and dark variants.
A fuzzy-search command palette (Cmd/Ctrl+P) provides access to all registered commands — from core actions to plugin commands. Commands can be bound to hotkeys. The palette uses a ranking algorithm that weights recency, frequency, and match quality.
The Quick Switcher (Cmd/Ctrl+O) provides instant fuzzy file navigation. It indexes all file names and aliases, supports path-based filtering, and ranks results by recency and match quality. Plugins can extend it with custom result types.
Obsidian's data layer encompasses the search engine, bidirectional link resolution, template system, and metadata indexing. All of this operates on the in-memory metadata cache built from the vault's Markdown files.
Full-text search across the vault with operators: path:, file:, tag:, line:, section:, block:, boolean operators, and regex. Search indexes are built in-memory from the metadata cache. Results highlight matches in context.
The backlinks panel shows all notes linking to the current note, with surrounding context. Outgoing links shows all links from the current note, including unresolved links (notes that don't exist yet). Both update reactively as you type.
Wiki-links ([[Note Name]]) resolve using a shortest-path algorithm: if multiple files match, the closest file (by folder proximity) wins. Links support aliases ([[Note|Display]]), heading links ([[Note#Heading]]), and block references ([[Note^block-id]]).
The core Templates plugin inserts content from template files, replacing variables like {{title}}, {{date}}, and {{time}}. The community Templater plugin extends this with JavaScript execution, dynamic dates, file/folder prompts, and user-defined functions.
Since v1.4, Obsidian renders YAML frontmatter as a structured Properties view with typed fields (text, list, date, checkbox, number). Properties are editable via a form UI or raw YAML. Custom property types can be defined globally for consistent metadata across the vault.
Tags can be defined inline (#tag) or in frontmatter (tags: [a, b]). Tags support nesting (#parent/child). The Tag Pane core plugin shows a tag tree with counts. Tags are indexed in the metadata cache for instant search and filtering.
Obsidian's linking model is inspired by the Zettelkasten method: atomic notes connected by explicit links. The combination of wiki-links, backlinks, aliases, block references, and the graph view creates an emergent knowledge graph that grows more valuable as you add connections between ideas.
| Subsystem | Technology | Description |
|---|---|---|
| Electron Shell | Electron + Chromium | Desktop app container with Node.js integration |
| Editor | CodeMirror 6 + Lezer | Markdown editor with Live Preview decorations |
| Vault Manager | Node.js fs + chokidar | File I/O, watcher, and vault lifecycle |
| Metadata Cache | TypeScript (in-memory) | Indexed links, tags, headings, frontmatter |
| Plugin Runtime | TypeScript / JavaScript | Plugin loading, API surface, event system |
| Graph View | Canvas 2D + Force Simulation | Force-directed node-link visualization |
| Canvas | DOM + SVG + JSON | Infinite whiteboard with cards and arrows |
| Search | In-memory index | Full-text search with operators and regex |
| Sync | WebSocket + AES-256 | E2E encrypted cloud synchronization |
| Publish | Static site + CDN | Note publishing as a hosted website |
| Theme Engine | CSS Custom Properties | 400+ CSS variables for complete visual control |
| Mobile | Capacitor (Ionic) | Native wrapper for iOS and Android |
| URI Protocol | obsidian:// scheme | Deep linking and inter-app automation |