| name | obsidian |
| description | Expert knowledge for developing Obsidian plugins and themes using TypeScript, CodeMirror 6, and CSS variables - covers plugin lifecycle, Vault API, Workspace API, editor extensions, styling patterns, and the official Obsidian CLI (obsidian command, plugin:reload, eval, dev tools) |
| hash | 881a7930a553c0d8 |
Obsidian Plugin & Theme Development
Build plugins and themes for Obsidian using TypeScript, CodeMirror 6, and CSS variables.
Core Principles
- Extend Plugin class - Use
onload() for setup, onunload() for cleanup
- Access app via
this.app - Never use global window.app (debugging only)
- Prefer Vault API - Use
this.app.vault over raw Adapter for file ops
- Wait for layout ready - Use
app.workspace.onLayoutReady() for startup logic (and to register vault events, so you skip the initial create burst)
- Guard deferred views - Since 1.7.2 leaves start as
DeferredView; instanceof-check leaf.view before use, call loadIfDeferred() (behind requireApiVersion('1.7.2')) only if truly needed
- Register events properly - Use
this.registerEvent() for auto-cleanup
- Mark external CM6 deps - Never bundle
@codemirror/*, use Obsidian's copy
- Use CSS variables - Override theme variables, not hardcoded colors
- Avoid
!important - Let users override with snippets
- Mobile compatibility - Check
Platform.isMobile before Node.js APIs
- Security first - Never use
innerHTML with user input
Quick Reference
import { Plugin, Notice } from 'obsidian';
export default class MyPlugin extends Plugin {
async onload() {
this.addCommand({
id: 'my-command',
name: 'My Command',
callback: () => new Notice('Hello!')
});
this.addRibbonIcon('dice', 'My Plugin', () => {});
this.registerEvent(
this.app.vault.on('modify', (file) => {})
);
this.registerEditorExtension(myExtension);
}
}
Topics
Plugin Development
Editor Integration
Styling
- Themes & CSS - CSS variables, theme structure, styling patterns
Advanced APIs
Tooling
- Obsidian CLI - Official
obsidian-cli command: vault ops, plugin:reload, eval, dev/screenshot/DOM/CSS inspection
Common Patterns
Wait for Vault Ready
async onload() {
this.app.workspace.onLayoutReady(() => {
const files = this.app.vault.getMarkdownFiles();
});
}
Process Frontmatter Safely
await this.app.fileManager.processFrontMatter(file, (fm) => {
fm.status = 'done';
});
Register Editor Extension
import { ViewPlugin, DecorationSet } from '@codemirror/view';
const myPlugin = ViewPlugin.fromClass(class {
decorations: DecorationSet;
}, { decorations: v => v.decorations });
this.registerEditorExtension(myPlugin);
Resources