Obsidian Publisher Skill
Purpose
Write markdown documents and mermaid diagrams to Obsidian vaults.
When to Use
-
Outputting research notes to Obsidian
-
Creating documentation in a vault
-
Generating diagrams for knowledge base
-
Exporting analysis results
Overview
Obsidian uses plain markdown files in folder-based vaults. Publishing is simply writing .md files to the correct directory.
Vault Structure
vault-path/ ├── folder/ │ ├── note.md │ └── subfolder/ │ └── nested-note.md ├── attachments/ # Optional: for images └── templates/ # Optional: note templates
Publishing Workflow
Step 1: Receive Vault Path
The vault path is passed per-request. Validate it exists:
from pathlib import Path
def validate_vault(vault_path: str) -> Path: path = Path(vault_path).expanduser().resolve() if not path.exists(): raise ValueError(f"Vault not found: {vault_path}") if not path.is_dir(): raise ValueError(f"Vault path is not a directory: {vault_path}") return path
Step 2: Create Document Structure
def create_note( vault_path: str, folder: str, filename: str, content: str, frontmatter: dict = None ) -> Path: """ Create a note in an Obsidian vault.
Args:
vault_path: Path to Obsidian vault
folder: Subfolder within vault (can be nested like "projects/2024")
filename: Note filename (without .md extension)
content: Markdown content
frontmatter: Optional YAML frontmatter dict
Returns:
Path to created file
"""
vault = validate_vault(vault_path)
target_dir = vault / folder
target_dir.mkdir(parents=True, exist_ok=True)
# Sanitize filename
safe_filename = sanitize_filename(filename)
file_path = target_dir / f"{safe_filename}.md"
# Build content with optional frontmatter
full_content = build_content(content, frontmatter)
file_path.write_text(full_content, encoding='utf-8')
return file_path
Step 3: Format Content
def build_content(content: str, frontmatter: dict = None) -> str: """Build markdown content with optional YAML frontmatter.""" if frontmatter: import yaml fm_str = yaml.dump(frontmatter, default_flow_style=False) return f"--- {fm_str}---
{content}" return content
def sanitize_filename(name: str) -> str: """Remove or replace invalid filename characters.""" invalid_chars = '<>:"/|?*' for char in invalid_chars: name = name.replace(char, '-') return name.strip()
Document Formats
Basic Note
Title
Content goes here.
Section
More content.
Note with Frontmatter
My Note
Content here.
Note with Mermaid Diagram
System Architecture
Overview
This document describes the system architecture.
Diagram
flowchart TD
A[Client] --> B[API Gateway]
B --> C[Service]
C --> D[(Database)]
Components
API Gateway
Handles routing and authentication.
### Note with Internal Links
```markdown
# Project Overview
This project uses [[Architecture|the architecture]] defined elsewhere.
Related:
- [[API Design]]
- [[Database Schema]]
See also: [[projects/2024/related-project|Related Project]]
Frontmatter Patterns
Research Note
Meeting Note
Documentation
Diagram Document
Folder Organization Patterns
By Type
vault/
├── notes/
├── research/
├── diagrams/
├── meetings/
└── projects/
By Date
vault/
├── 2024/
│ ├── 01-january/
│ └── 02-february/
└── archive/
By Project
vault/
├── project-alpha/
│ ├── research/
│ ├── design/
│ └── notes/
└── project-beta/
Usage Examples
Publish Research Note
create_note(
vault_path="~/Documents/Obsidian/MyVault",
folder="research",
filename="API Design Patterns",
content="""
# API Design Patterns
## REST Best Practices
Key findings from research...
## GraphQL Considerations
...
""",
frontmatter={
"title": "API Design Patterns",
"date": "2024-01-15",
"tags": ["api", "research"],
"status": "draft"
}
)
Publish Diagram
create_note(
vault_path="~/Documents/Obsidian/MyVault",
folder="diagrams/architecture",
filename="System Overview",
content="""
# System Overview
```mermaid
flowchart TB
subgraph Frontend
A[Web App]
B[Mobile App]
end
subgraph Backend
C[API Server]
D[Worker]
end
A --> C
B --> C
C --> D
Components
- Web App: React-based SPA
- Mobile App: React Native
- API Server: FastAPI
- Worker: Celery
""",
frontmatter={
"title": "System Overview",
"diagram_type": "architecture",
"tags": ["diagram", "architecture"]
}
)
## Integration with Mermaid
Obsidian renders mermaid diagrams natively. Use `documentation-generator:mermaid-expert` for diagram syntax, then embed directly:
```markdown
```mermaid
sequenceDiagram
Client->>Server: Request
Server-->>Client: Response
## Obsidian-Specific Features
### Callouts
```markdown
> [!note]
> This is a note callout
> [!warning]
> This is a warning
> [!tip]
> This is a tip
Tags
#tag-name
Or in frontmatter:
tags:
- tag1
- tag2
Internal Links
[[Note Name]]
[[folder/Note Name]]
[[Note Name|Display Text]]
[[Note Name#Heading]]
Embeds
![[Note to embed]]
![[image.png]]
![[Note#Section]]
Error Handling
class ObsidianPublishError(Exception):
"""Base exception for Obsidian publishing errors."""
pass
class VaultNotFoundError(ObsidianPublishError):
"""Vault path does not exist."""
pass
class InvalidFilenameError(ObsidianPublishError):
"""Filename contains invalid characters."""
pass
Checklist
Before publishing:
- Vault path is valid and accessible
- Filename is sanitized
- Folder structure created
- Frontmatter is valid YAML
- Mermaid diagrams use correct syntax
- Internal links reference existing notes (if applicable)