Skip to content

A Docusaurus plugin that seamlessly integrates your Obsidian vault with Docusaurus, automatically transforming Obsidian-specific syntax (wikilinks, callouts) into Docusaurus-compatible markdown.

License

Notifications You must be signed in to change notification settings

gl0bal01/docusaurus-plugin-obsidian-vault

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

docusaurus-plugin-obsidian-vault

License: MIT TypeScript Docusaurus GitHub

A Docusaurus plugin that seamlessly integrates your Obsidian vault with Docusaurus, automatically transforming Obsidian-specific syntax (wikilinks, callouts) into Docusaurus-compatible markdown.

Live demo

A live demo is available at: gl0bal01.com/intel-codex

Features

  • Automatic Content Sync: Sync your Obsidian vault to Docusaurus docs at build time
  • Wikilink Conversion: Transforms [[wikilinks]] into proper Docusaurus markdown links
  • Callout Support: Converts Obsidian callouts to Docusaurus admonitions
  • Asset Management: Automatically copies images and other assets
  • Category Generation: Auto-generates _category_.json files for sidebar navigation
  • Frontmatter Enhancement: Preserves and enhances YAML frontmatter
  • Custom Banners: Add informational banners at top/bottom of synced files
  • MDX Compatibility: Escapes problematic characters for MDX
  • Local & GitHub Sources: Support for both local vaults and GitHub repositories
  • Customizable Transformations: Configure which transformations to apply
  • Hot Reload: Watch mode for local development

Installation

npm install docusaurus-plugin-obsidian-vault

or

yarn add docusaurus-plugin-obsidian-vault

Usage

Add the plugin to your docusaurus.config.ts:

import type { Config } from '@docusaurus/types';

const config: Config = {
  // ... other config
  plugins: [
    [
      'docusaurus-plugin-obsidian-vault',
      {
        vaultSource: {
          type: 'local',
          path: '/path/to/your/obsidian-vault',
        },
        docsPath: 'docs/vault',
        assetsPath: 'static/img/vault',
      },
    ],
  ],
};

export default config;

Configuration

Plugin Options

interface ObsidianPluginOptions {
  // Source vault configuration (required)
  vaultSource: VaultSource;

  // Destination in Docusaurus docs (required)
  docsPath: string;

  // Multi-instance docs support (optional)
  docsPluginId?: string; // ID of the docs plugin instance for multi-instance setups

  // Transformation options
  transformations?: TransformationOptions;

  // Asset handling
  assetsPath?: string; // Default: 'static/img/obsidian-vault'

  // Filtering
  exclude?: string[]; // Default: ['**/.obsidian/**', '**/.git/**', '**/node_modules/**']
  include?: string[]; // Default: ['**/*.md']

  // Category generation
  generateCategories?: boolean; // Default: true
  categoryLabels?: Record<string, string>;
  categoryIndexFile?: string; // Filename to use as category index (e.g., 'START.md', 'README.md')

  // Banners
  bannerTop?: string; // Optional banner at top of each file (after frontmatter)
  bannerBottom?: string; // Optional banner at bottom of each file

  // Debug
  debug?: boolean; // Default: false
}

Vault Source Options

Local Vault

{
  vaultSource: {
    type: 'local',
    path: '/absolute/path/to/vault',
  }
}

GitHub Repository

{
  vaultSource: {
    type: 'github',
    repository: 'username/repo-name',
    branch: 'main', // Optional, default: 'main'
    token: process.env.GITHUB_TOKEN, // For private repos
    path: '.temp-vault', // Where to expect the cloned repo
  }
}

For GitHub sources, you'll need to clone the repository in your CI/CD pipeline:

# .github/workflows/deploy.yml
- name: Checkout vault
  uses: actions/checkout@v4
  with:
    repository: username/vault-repo
    path: .temp-vault
    token: ${{ secrets.GITHUB_TOKEN }}

Transformation Options

{
  transformations: {
    convertWikilinks: true, // Default: true
    wikilinkStyle: 'relative', // 'relative' | 'absolute'
    convertCallouts: true, // Default: true
    preserveFrontmatter: true, // Default: true
  }
}

Examples

Basic Setup

// docusaurus.config.ts
export default {
  plugins: [
    [
      'docusaurus-plugin-obsidian-vault',
      {
        vaultSource: {
          type: 'local',
          path: '/Users/username/Documents/MyVault',
        },
        docsPath: 'docs/knowledge-base',
      },
    ],
  ],
};

Advanced Configuration

// docusaurus.config.ts
export default {
  plugins: [
    [
      'docusaurus-plugin-obsidian-vault',
      {
        vaultSource: {
          type: 'local',
          path: '/Users/username/Documents/MyVault',
        },
        docsPath: 'docs/knowledge-base',
        assetsPath: 'static/img/kb',

        // Exclude certain paths
        exclude: [
          '**/.obsidian/**',
          '**/Private/**',
          '**/Templates/**',
        ],

        // Custom category labels
        categoryLabels: {
          'osint': 'Open Source Intelligence',
          'cyber': 'Cybersecurity',
          'tools': 'Tool Documentation',
        },

        // Transformation options
        transformations: {
          convertWikilinks: true,
          convertCallouts: true,
          preserveFrontmatter: true,
        },

        // Custom banners
        bannerTop: ':::info\nThis file is synced from the Obsidian vault. [Edit on GitHub](https://github.com/username/vault)\n:::',
        bannerBottom: '*Last synced from Obsidian vault*',

        generateCategories: true,
        categoryIndexFile: 'START.md', // Use START.md as category index page
        debug: true,
      },
    ],
  ],
};

GitHub Integration

// docusaurus.config.ts
export default {
  plugins: [
    [
      'docusaurus-plugin-obsidian-vault',
      {
        vaultSource: {
          type: 'github',
          repository: 'username/my-vault',
          branch: 'main',
          path: '.temp-vault',
        },
        docsPath: 'docs/vault',
      },
    ],
  ],
};

Multi-Instance Docs Setup

Docusaurus supports multiple docs instances, allowing you to have separate documentation sections with their own sidebars and routes. This is perfect for integrating an Obsidian vault as a separate docs instance alongside your main documentation.

Why use multi-instance?

  • Keep your Obsidian vault content separate from your main docs
  • Different route base paths (e.g., /docs for main docs, /intel-codex for vault)
  • Separate sidebars and navigation
  • Different edit URLs and configurations

Complete multi-instance setup requires TWO plugin configurations:

  1. A @docusaurus/plugin-content-docs instance for the vault
  2. The docusaurus-plugin-obsidian-vault to sync content to that instance
// docusaurus.config.ts
import type { Config } from '@docusaurus/types';

const config: Config = {
  // ... other config

  plugins: [
    // 1. Create a separate docs instance for your Obsidian vault
    [
      '@docusaurus/plugin-content-docs',
      {
        id: 'intel-codex', // Unique ID for this docs instance
        path: 'intel-codex', // Folder where vault content will be synced
        routeBasePath: 'intel-codex', // URL route: /intel-codex
        sidebarPath: './sidebars-intel-codex.ts', // Separate sidebar config
        editUrl: 'https://github.com/username/vault-repo/tree/main/',
        showLastUpdateAuthor: false,
        showLastUpdateTime: true,
        sidebarCollapsed: true,
      },
    ],

    // 2. Obsidian vault sync plugin (syncs TO the intel-codex folder)
    [
      'docusaurus-plugin-obsidian-vault',
      {
        vaultSource: {
          type: 'github',
          repository: 'username/vault-repo',
          branch: 'main',
          path: '.temp-vault', // GitHub Actions clones here
        },
        docsPath: 'intel-codex', // Syncs to the docs instance folder
        docsPluginId: 'intel-codex', // Optional: specify which docs instance
        assetsPath: 'static/img/intel-codex',
        exclude: ['**/.obsidian/**', '**/.git/**', '**/Templates/**'],
        transformations: {
          convertWikilinks: true,
          convertCallouts: true,
          preserveFrontmatter: true,
        },
        generateCategories: true,
        categoryLabels: {
          'intel-codex': 'Intel Codex',
          'Investigations': 'Investigations',
          'Security': 'Security Research',
        },
        categoryIndexFile: 'START.md', // Use START.md as category index
        bannerTop: ':::danger[Synced from **Obsidian vault**]\\nFor full graph and advanced features, download the **[Vault](https://github.com/username/vault-repo)** and open in **Obsidian**.\\n:::',
        debug: true,
      },
    ],
  ],

  // Configure the navbar to link to the vault docs instance
  themeConfig: {
    navbar: {
      items: [
        // Regular docs link
        {
          type: 'docSidebar',
          sidebarId: 'mainSidebar',
          position: 'left',
          label: 'Docs',
        },
        // Link to vault docs instance
        {
          type: 'docSidebar',
          sidebarId: 'intelCodexSidebar', // Must match sidebar ID in sidebars-intel-codex.ts
          position: 'left',
          label: 'Intel Codex',
          docsPluginId: 'intel-codex', // Must match docs instance ID
        },
      ],
    },
  },
};

export default config;

Create a separate sidebar file for the vault (sidebars-intel-codex.ts):

import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';

const sidebars: SidebarsConfig = {
  // This ID must match the sidebarId in navbar config
  intelCodexSidebar: [
    {
      type: 'autogenerated',
      dirName: '.', // Generate sidebar from intel-codex folder
    },
  ],
};

export default sidebars;

GitHub Actions workflow (for GitHub vault sources):

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout main repo
        uses: actions/checkout@v4

      # Clone the vault BEFORE building Docusaurus
      - name: Checkout Obsidian vault
        uses: actions/checkout@v4
        with:
          repository: username/vault-repo
          path: .temp-vault
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Build site
        run: npm run build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./build

Important notes for multi-instance:

  1. Folder Structure:

    • The intel-codex/ folder should be git-ignored (it's auto-generated)
    • The plugin automatically creates this folder with a placeholder during initialization
    • The plugin syncs vault content to this folder at build time
    • The placeholder is removed after vault sync completes
  2. Route Paths:

    • Main docs: / (configured in preset)
    • Vault docs: /intel-codex (configured in docs instance)
  3. Sidebar Configuration:

    • Main docs use sidebars.ts
    • Vault docs use sidebars-intel-codex.ts
    • Each has independent navigation
  4. Edit URLs:

    • Main docs can link to main repo
    • Vault docs link to vault repo (configured in docs instance editUrl)
  5. docsPluginId Usage:

    • The docsPluginId option is informational and helps with debugging
    • The actual multi-instance setup is done via the @docusaurus/plugin-content-docs plugin
    • Both plugins must use matching paths (e.g., both use intel-codex)
  6. Plugin Initialization Order:

    • The obsidian-vault-plugin creates the destination folder immediately during plugin initialization
    • This ensures the folder exists BEFORE the @docusaurus/plugin-content-docs plugin tries to load it
    • A temporary placeholder file is created to prevent errors, then removed after sync completes

Transformations

Wikilinks

Obsidian wikilinks are automatically converted to Docusaurus-compatible links. The plugin intelligently calculates relative paths based on file location.

Obsidian wikilinks are vault-root-relative:

[[Page Name]]
[[folder/Page Name|Custom Label]]
[[Page Name#Section]]

Converted paths depend on file depth:

From a root-level file:

[Page Name](./Page Name.md)
[Custom Label](./folder/Page Name.md)

From a nested file (e.g., Cases/Example/README.md):

[Page Name](../../Page Name.md)
[Custom Label](../../folder/Page Name.md)

The plugin automatically:

  • Calculates the correct ../ prefix based on file depth
  • Preserves custom display labels
  • Handles section anchors (#heading)
  • Works with both root-level and nested files

Callouts

Obsidian callouts are converted to Docusaurus admonitions:

Obsidian:

> [!note] Important Note
> This is the content of the callout.
> It can span multiple lines.

Docusaurus:

:::note Important Note
This is the content of the callout.
It can span multiple lines.
:::

Supported callout types: note, tip, info, warning, danger, caution

Frontmatter

The plugin preserves and enhances YAML frontmatter:

---
title: My Page
tags: [osint, research]
sidebar_position: 1
---

If no title or sidebar_label is present, one is automatically generated from the filename.

Category Index Files

By default, Docusaurus generates an index page for each category. You can specify a custom file to use as the category index:

Configuration:

{
  categoryIndexFile: 'START.md'
}

How it works:

  • Root category: If START.md exists in the vault root, the main category link points to it
  • Subdirectories: If a subdirectory contains START.md, that directory's category link points to it
  • Fallback: If the file doesn't exist in a directory, Docusaurus generates a default index

Example:

vault/
├── START.md          ← Root category index
├── Investigations/
│   ├── START.md      ← Investigations category index
│   └── Platforms/
│       └── twitter.md
└── Security/
    └── malware.md       ← No START.md, uses generated index

With this setup:

  • Clicking "Vault" in sidebar → Opens root START.md
  • Clicking "Investigations" → Opens Investigations/START.md
  • Clicking "Security" → Shows auto-generated index

Banners

Add custom banners to all synced files to provide context or attribution:

Configuration:

{
  bannerTop: ':::info\nThis file is part of the Obsidian vault. [Edit on GitHub](https://github.com/user/repo)\n:::',
  bannerBottom: '*Last synced from Obsidian vault*'
}

Result:

  • bannerTop is inserted after frontmatter (or at the top if no frontmatter exists)
  • bannerBottom is appended at the end of the file
  • Banners support full markdown including Docusaurus admonitions

Example use cases:

  • Attribution and edit links: :::note\nEdit this file in the [Obsidian vault](https://github.com/user/vault)\n:::
  • Sync warnings: :::caution\nDo not edit this file directly - changes will be overwritten\n:::
  • Metadata: *Last synced: {new Date().toISOString()}*

Development Workflow

Local Development

When using a local vault, the plugin watches for changes and hot-reloads:

npm start

The plugin will automatically re-sync when you modify files in your vault.

Production Build

npm run build

The plugin runs during the build process and syncs all vault content.

Vault Statistics

The plugin generates vault statistics accessible in your Docusaurus site:

{
  "totalFiles": 150,
  "totalSize": 2048000,
  "categoriesGenerated": 12,
  "wikilinsConverted": 450,
  "calloutsConverted": 89,
  "assetscopied": 73
}

Access via: .docusaurus/docusaurus-plugin-obsidian-vault/default/vault-stats.json

Troubleshooting

Files not syncing

  1. Check that your vaultSource.path is correct
  2. Verify files aren't being excluded by your exclude patterns
  3. Enable debug: true to see detailed logs

Wikilinks not converting

  • Ensure transformations.convertWikilinks is true
  • Check that the linked files exist in your vault
  • Relative paths should work automatically

Callouts not rendering

  • Verify callout syntax matches Obsidian format: > [!type] Title
  • Supported types: note, tip, info, warning, danger, caution
  • Enable debug: true to check transformation logs

Build errors with GitHub source

  • Ensure the repository is cloned before Docusaurus build
  • Check that vaultSource.path matches your checkout path
  • Verify GitHub token has correct permissions for private repos

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

See MIT License file for details

About

A Docusaurus plugin that seamlessly integrates your Obsidian vault with Docusaurus, automatically transforming Obsidian-specific syntax (wikilinks, callouts) into Docusaurus-compatible markdown.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published