Obsidian API: The Thematic Developer's Guide
This guide reorganizes the ~265+ API exports into functional domains. It maps the Obsidian API to standard software architecture patterns (MVC, DOM manipulation, IO) to help you find the right tool for the job.
1. The Core Application Architecture (System Level)
Job: Managing the lifecycle, global state, and event propagation.
App (The Singleton "God Object")
In standard MVC (Model-View-Controller), this.app is your entry point to everything. It holds references to the Model (Vault, MetadataCache) and the View (Workspace).
Access:
this.appinside your plugin.Key Properties: vault, metadataCache, workspace, fileManager, keymap, scope.
Plugin & Component (Lifecycle Management)
Obsidian uses a composite pattern for lifecycle management. Almost every UI element extends Component.
Component: The base class for managing resources.
- load() / unload(): Life and death of the object.
- addChild(component): Attaches a child's lifecycle to this component. Crucial: If you create a complex UI, adding it as a child ensures it gets cleaned up when the plugin unloads.
- registerEvent(): Auto-unregisters events on unload.
- registerDomEvent(): Auto-removes DOM listeners on unload.
- registerInterval(): Auto-clears
setIntervaltimers.
2. The Model Layer: Files & Data
Job: Handling persistence. Obsidian has two layers for this: a high-level logical layer (Vault) and a low-level OS layer (Adapter).
Vault (Logical File System)
Use this for 99% of file operations. It handles caching and synchronizing with Obsidian's internal state.
- Read/Write: read(file), modify(file, data), append(file, data).
- CRUD: create(path, data), delete(file), trash(file, system), rename(file, path).
- Atomicity: process(file, callback) (Prevents race conditions by reading and writing in one atomic transaction).
- Retrieval: getAbstractFileByPath(), getMarkdownFiles(), getRoot().
FileManager (Safe File Operations)
Use this when you need to perform file operations that might break links.
- renameFile(file, newPath): Unlike
vault.rename, this automatically updates internal links pointing to that file across the entire vault. - getNewFileParent(sourcePath): Determines where a new file should be created based on the user's settings (e.g., "Same folder as current file").
TAbstractFile Hierarchy
The abstract representation of files.
- TFile: A specific file. Has properties like basename, extension, stat (size, mtime).
- TFolder: A folder. Has children.
DataAdapter (Low-Level IO)
Accessed via vault.adapter. This is close to Node's fs module.
- Classes: FileSystemAdapter (Desktop), CapacitorAdapter (Mobile).
- Use Case: Reading files inside
.obsidian, accessing hidden dotfiles, or raw system paths. - Warning: Bypasses the cache. Slower for heavy read operations.
3. The Metadata Layer: Indexing & Querying
Job: Knowing about files without reading their content.
MetadataCache
Obsidian maintains an in-memory database of the vault structure.
- getFileCache(file): Returns CachedMetadata.
- resolvedLinks: A massive object map of
{ sourcePath: { targetPath: count } }. Used for graph view calculations. - unresolvedLinks: Links pointing to non-existent files.
- Events: on('changed') (Fires after metadata parsing is done), on('resolve').
CachedMetadata (The Data Structure)
The object returned by the cache.
- frontmatter: YAML properties as a JS object.
- tags: Array of tag caches.
- headings: Array of heading caches (depth, text).
- links / embeds: Outgoing wiki-links.
4. The View Layer: Workspace & Layouts
Job: Managing the windowing system, panes, and tabs.
Workspace
The manager of the UI tree.
- Layout: getLeaf(), splitActiveLeaf(), getRightLeaf().
- Traversal: iterateAllLeaves(cb), getLeavesOfType(type).
- Events: on('active-leaf-change'), on('file-open'), on('layout-change').
WorkspaceLeaf
A single tab container.
- openFile(file): Opens a
TFilein this leaf. - setViewState({ type: 'markdown' }): Changes the view type programmatically.
- view: Access the actual View instance inside the leaf.
Critical Concept: Deferred Views
Job: Optimization. To speed up startup, Obsidian does not load your view until the user actually clicks that tab.
The Trap: When you call
getLeavesOfType('my-view'), theleaf.viewproperty might not be an instance ofMyView. It might be a genericDeferredViewplaceholder.The Fix:
Check Instance: Always check
if (leaf.view instanceof MyView).Reveal First: If you need to manipulate the view, ensure it is loaded by calling
workspace.revealLeaf(leaf).Force Load (Rare): Use
await leaf.loadIfDeferred()if you absolutely need the view state without showing it (use sparingly for performance).
For more information, see https://docs.obsidian.md/plugins/guides/defer-views.
View Hierarchy
- View: Abstract base class.
- ItemView: Base for custom plugin views (Kanban, Calendar).
- Implementation: You must implement getViewType(), getDisplayText(), onOpen(), onClose().
- FileView: Base for views that represent a specific file.
- MarkdownView: The core editor view. Exposes editor (CM6 wrapper) and previewMode (Reading view).
The Layout Tree Classes
Classes representing the DOM structure of the workspace.
- WorkspaceWindow: A pop-out window.
- WorkspaceSplit: A column or row container.
- WorkspaceTabs: A tab group container.
- WorkspaceRibbon: The left-hand sidebar strip.
5. The Component Library: Building UI
Job: Creating standardized UI elements without writing raw HTML. Obsidian exposes its internal UI toolkit.
Input Components
These wrap HTML inputs and handle standard Obsidian styling/events.
- ButtonComponent / ExtraButtonComponent: Buttons and icon-only buttons.
- TextComponent / TextAreaComponent: Text inputs.
- ToggleComponent: Checkbox switches.
- DropdownComponent: Select menus.
- SliderComponent: Range sliders.
- ColorComponent: Color pickers.
- SearchComponent: The standard search box with the magnifying glass icon.
- ProgressBarComponent: Loading indicators.
Settings Builders
- PluginSettingTab: Abstract class for the main settings page.
- Setting: A builder class for rows in the settings page.
6. Interaction Layer: Modals & Menus
Job: Capturing user intent via overlays.
Modals
- Modal: Base class for generic dialogs. You populate
this.contentEl. - Notice: Transient toast notifications (
new Notice("Saved!")). - FuzzySuggestModal: The "Quick Switcher" UI. You provide items; it handles fuzzy search and keyboard nav.
- SuggestModal: Similar to Fuzzy, but allows custom matching logic.
Menus
- Menu: The right-click context menu.
- MenuItem: An item in the menu.
- MenuSeparator: Visual divider.
- Pattern: You typically don't instantiate
Menudirectly unless creating a custom UI button; instead, you hook intoworkspace.on('file-menu')to append items to existing menus.
7. The Editor Engine
Perhaps the most complex aspect of Obsidian development is interacting with the editor. Obsidian uses CodeMirror 6 (CM6), a complete rewrite of the previous engine. CM6 adopts a functional, state-driven architecture.
Job: Manipulating text and the editing experience.
- Editor (Interface): The stable abstraction layer.
- Methods: getCursor, setSelection, replaceRange, getLine, lineCount.
- Best Practice: Use this for text manipulation to ensure compatibility with Mobile and different editor modes.
- EditorSuggest: Base class for autocomplete popups (like typing
@to trigger mentions). - MarkdownPostProcessor: A function signature for altering Reading View rendering.
- MarkdownRenderChild: A component lifecycle manager for elements rendered inside Reading View (essential for cleaning up interactive elements when the user scrolls them away).
8. The Bases API (Native Data Tables)
Job: Interacting with Obsidian's native database engine. "Bases" allow for dynamic, table/grid-like views of vault data, similar to the Dataview plugin but built into the core.
Developer Guide: Build a Bases View
The Data Model (Rows & Cells)
These interfaces represent the actual data returned by a query.
- BasesEntry: Represents a single "row" or file in a Base. Implements
FormulaContext. - BasesEntryGroup: A collection of entries grouped by a specific key (used when the user applies "Group By").
- BasesQueryResult: The complete result set of a query. Contains
data(flat entries) andgroupedData(entries organized into groups). - BasesProperty: Definition of a column/property.
- BasesPropertyId: Unique identifier for a property.
- BasesPropertyType: Enum defining the data type (Text, Number, Date, etc.).
Developer API: Bases schema configuration
These interfaces handle the structure of the .base file (or code block) itself—how the user has configured filters, sorts, and visible columns.
- BasesConfigFile: The serialized JSON structure of a
.basefile. - BasesConfigFileFilter: Definitions for active filters (e.g., "Tag includes #todo").
- BasesConfigFileView: Configuration for a specific view within a Base file (since one file can have multiple views like "Table", "Board").
- BasesSortConfig: Sorting rules (property and direction).
- BasesViewConfig: Runtime configuration options for the view.
View Implementation (Rendering)
Classes used when creating new types of views for Bases (e.g., if you wanted to build a custom "Timeline View" for Bases).
- BasesView: The abstract base class for a visual component that renders Base data.
- Key Method:
onDataUpdated()— Called when the query result changes so you can re-render.
- Key Method:
- BasesViewFactory: Factory function to instantiate your custom view.
- BasesViewRegistration: Object used to register your custom view type with Obsidian.
Summary Comparison Table
| Job | Standard JS/Web | Obsidian API | Why? |
|---|---|---|---|
| File Read | fs.readFile | vault.read(tfile) | Caching, sync safety, mobile support. |
| File Path | path.join | normalizePath() | Cross-platform separator handling. |
| HTML UI | document.createElement | el.createEl('div') | Fluent API, auto-cleaning. |
| Events | addEventListener | registerDomEvent | Auto-cleanup on plugin unload. |
| Settings | <input> tags | new Setting().addText() | Standardization, built-in styling. |
| Timers | setInterval | registerInterval | Prevents "ghost" timers after unload. |