--- name: obsidian-sync description: >- Use this skill when designing, building, or troubleshooting the Obsidian vault publishing integration, the server upload API, note normalization (wikilinks, callouts, frontmatter), or the custom Obsidian plugin. --- # Obsidian Vault Publishing & Sync Skill This skill guides the agent in implementing the custom Obsidian plugin and server-side ingestion workflow for publishing blog posts directly from an Obsidian vault. --- ## 1. System Architecture ```text +-------------------+ +-----------------------+ | Obsidian Vault | | Blog Server | | | | | | [Active Markdown] | POST /api/posts | /api/posts Endpoint | | + | -------------------> | + | | Custom Plugin | (Payload: JSON/MD) | Frontmatter Validator | +-------------------+ | + | | Wikilink Normalizer | | + | +-------------------+ | Write to `src/posts/` | | Self-Hosted | CouchDB Sync | + | | LiveSync Server | ===================> | 11ty Build Trigger | +-------------------+ +-----------------------+ ``` --- ## 2. Ingestion API Specification ### Endpoint: `POST /api/posts` - **Headers:** - `Content-Type: application/json` - `Authorization: Bearer ` - **Request Body:** ```json { "slug": "reverse-engineering-iot-firmware", "content": "---\ntitle: \"Reverse Engineering IoT Firmware\"\ndate: 2026-09-12\ntags: [\"#firmware\"]\n---\n\n## Content...", "assets": [ { "filename": "diagram.png", "data": "" } ] } ``` - **Response:** - `200 OK`: `{"status": "published", "path": "/posts/reverse-engineering-iot-firmware/"}` - `400 Bad Request`: `{"error": "Missing required frontmatter: title, date"}` --- ## 3. Obsidian Markdown Normalization Rules 1. **Frontmatter Invariants:** - Must contain `title`, `date`, `tags` (array), and optional `excerpt`, `readingTime`, `draft`. 2. **Wikilinks Translation:** - `[[article-slug]]` $\rightarrow$ `[article-slug](/posts/article-slug/)` - `[[article-slug|Custom Label]]` $\rightarrow$ `[Custom Label](/posts/article-slug/)` 3. **Callout Translation:** - Obsidian callouts: ```markdown > [!NOTE] > Informational notice ``` Must be rendered with corresponding terminal alert styling. 4. **Internal Attachments:** - `![[screenshot.png]]` $\rightarrow$ translated to `![screenshot](/assets/images/posts/screenshot.png)` and written to `src/assets/images/posts/`. --- ## 4. Custom Obsidian Plugin Development The Obsidian plugin runs inside Obsidian desktop/mobile and interacts with the Obsidian API: 1. Registers a ribbon icon (e.g. `send` or `terminal`) and a command: `Publish Current Note to River Rooks Blog`. 2. Reads the active file: ```typescript const activeFile = this.app.workspace.getActiveFile(); const content = await this.app.vault.read(activeFile); ``` 3. Parses frontmatter using Obsidian's metadata cache: ```typescript const cache = this.app.metadataCache.getFileCache(activeFile); ``` 4. Sends the HTTP payload to the configured blog server URL with the Bearer token. 5. Displays an Obsidian `Notice('Published successfully to River Rooks Blog!')`. --- ## 5. Self-Hosted LiveSync Compatibility If using CouchDB-based self-hosted LiveSync: - A local watcher or CouchDB change listener daemon can be configured to detect updates to notes marked with `published: true` or in a dedicated `Blog/` folder. - When an update event fires, the daemon pulls the latest revision from the CouchDB database, runs the normalization pipeline, and saves it to `src/posts/`.