---
title: "Obsidian Vaults"
description: "Obsidian Vaults in the context of Fumadocs serves as a bridging mechanism to transform standard, local Obsidian note repositories into structured, web-ready documentation content. It solves the com..."
last_updated: "2026-07-02T09:46:39.685838+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/content-engine/obsidian-vaults"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/obsidian/src/remark/remark-convert.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-convert.ts)
- [packages/obsidian/src/mdx/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/mdx/index.ts)
- [packages/core/src/source/page-tree/transformer-fallback.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/source/page-tree/transformer-fallback.ts)
- [packages/mdx/src/loaders/mdx/remark-include.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/remark-include.ts)
- [packages/core/src/mdx-plugins/remark-structure.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-structure.ts)
- [packages/core/src/mdx-plugins/remark-steps.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-steps.ts)
- [packages/obsidian/src/remark/remark-wikilinks.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-wikilinks.ts)
- [packages/obsidian/src/build-resolver.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/build-resolver.ts)
- [packages/obsidian/src/remark/remark-block-id.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-block-id.ts)
- [packages/obsidian/src/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/index.ts)
- [packages/obsidian/src/build-storage.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/build-storage.ts)
- [packages/core/src/mdx-plugins/remark-llms.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-llms.ts)
- [packages/core/src/source/llms.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/source/llms.ts)
- [packages/core/src/mdx-plugins/remark-feedback-block.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-feedback-block.ts)
- [packages/core/package.json](https://github.com/blade47/fumadocs/blob/main/packages/core/package.json)
- [packages/preview/src/lib/source/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/lib/source/index.ts)
- [packages/mdx/src/loaders/mdx/remark-postprocess.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/remark-postprocess.ts)
- [packages/obsidian/src/remark/remark-obsidian-comment.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-obsidian-comment.ts)
- [packages/obsidian/src/remark/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/index.ts)
- [packages/obsidian/src/convert.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/convert.ts)
- [packages/core/src/source/storage/content.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/source/storage/content.ts)
- [packages/obsidian/src/utils/get-refs.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/utils/get-refs.ts)
- [packages/twoslash/src/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/twoslash/src/index.ts)
- [packages/obsidian/src/read-vaults.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/read-vaults.ts)
- [packages/python/src/convert.ts](https://github.com/blade47/fumadocs/blob/main/packages/python/src/convert.ts)
- [packages/content-collections/src/configuration.ts](https://github.com/blade47/fumadocs/blob/main/packages/content-collections/src/configuration.ts)
- [packages/core/src/mdx-plugins/remark-llms.runtime.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-llms.runtime.ts)
- [packages/obsidian/tsdown.config.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/tsdown.config.ts)
- [packages/core/src/search/orama-cloud-legacy.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama-cloud-legacy.ts)
- [packages/preview/src/lib/source/storage.ts](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/lib/source/storage.ts)
</details>

Obsidian Vaults in the context of Fumadocs serves as a bridging mechanism to transform standard, local Obsidian note repositories into structured, web-ready documentation content. It solves the compatibility problem between the idiosyncratic markdown features used by Obsidian users (such as Wikilinks, callouts, block IDs, and comments) and the standard MDX/Remark pipeline used by modern static site generators.

The component architecture is designed to intercept raw file collections, parse them into a virtualized storage model, and apply specialized Remark transformations. By centralizing the resolution of cross-file references and syntax conversion, Obsidian Vaults allows developers to maintain their documentation in a personal knowledge management tool while publishing high-quality, linked web documentation with minimal friction.

The system is built on a modular, pipeline-oriented architecture. It uses a custom `VaultStorage` to index files, a `VaultResolver` for path and name-based lookups, and a specific suite of Remark plugins to handle the Obsidian dialect. This decoupling ensures that the core documentation engine remains agnostic of the input source, while the vault-specific logic resides within isolated plugins that translate complex Obsidian markdown into standard MDX elements like custom components or standardized HTML structures.

## Core Data Structures and Storage Model

The storage model is anchored by `buildStorage`, which ingests raw files and classifies them into one of three formats: `content`, `media`, or `data`. This classification drives how the downstream conversion pipeline treats each entry: `content` files undergo Remark processing and frontmatter parsing, `media` files are treated as assets, and `data` files are preserved as-is.

| Field | Type | Purpose |
| :--- | :--- | :--- |
| `format` | `'content' \| 'media' \| 'data'` | Discriminator for processing logic. |
| `path` | `string` | The original normalized path within the vault. |
| `outPath` | `string` | The target path relative to the output directory. |
| `frontmatter` | `Frontmatter` | Parsed YAML metadata for content files. |

Sources: [packages/obsidian/src/build-storage.ts:39-68](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/build-storage.ts#L39-L68)

## Vault Resolver Mechanism

The `VaultResolver` provides the lookup service for cross-linking. It creates internal mapping tables (`pathToFile`, `nameToFile`) to facilitate lookups by file name, relative path, or absolute vault path.

When `resolveAny(name, fromPath)` is called, the system evaluates the target name:
1. It checks if the string starts with `./` or `../` to resolve relative to the current file's directory.
2. It attempts a lookup against `pathToFile`.
3. It falls back to `nameToFile` if the initial resolution fails, providing robust handling for links that omit directory depth.

```typescript
// Example usage of VaultResolver
const resolver = buildResolver(storage);
const target = resolver.resolveAny('my-note', '/path/to/current/note.md');
```
Sources: [packages/obsidian/src/build-resolver.ts:5-26](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/build-resolver.ts#L5-L26), [packages/obsidian/src/build-resolver.ts:58-69](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/build-resolver.ts#L58-L69)

## Wikilink Transformation Flow

The Wikilink plugin (`remarkWikilinks`) is responsible for converting Obsidian's `link` syntax into valid Markdown links or embedded components. The process follows a specific order of operations:

1. **Visit:** It traverses the AST to identify `paragraph` nodes containing `wikilinks`.
2. **Text Parsing:** The `resolveParagraphText` function executes a regex match for the `...` pattern.
3. **Dispatch:**
   - If it is an internal link (`isEmbed = false`), it calls `resolver.resolveAny` and generates a standard markdown `link` node.
   - If it is an embed (`isEmbed = true`), it attempts to resolve the file and returns a `mdxJsxFlowElement` (typically an `<include />` component) for content or an `image` node for media assets.

> [!NOTE]
> Wikilinks that resolve to heading-only targets are handled specifically by `getHeadingHash`, which processes the hash segment without slugifying block IDs (strings starting with `^`).

Sources: [packages/obsidian/src/remark/remark-wikilinks.ts:15-17](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-wikilinks.ts#L15-L17), [packages/obsidian/src/remark/remark-wikilinks.ts:84-137](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-wikilinks.ts#L84-L137)

## Callout and Syntax Normalization

Obsidian's blockquote syntax `[!type]` is converted into standard Fumadocs-compatible callout components. The `remarkConvert` plugin handles this:
1. It looks for `blockquote` nodes in the MDAST.
2. `resolveCallout` extracts the type (e.g., `info`, `warning`) from the first line using `RegexCalloutHead`.
3. It uses `mdast-separate` to split the title from the rest of the node content.
4. It calls `createCallout` to transform the structure into a clean JSX/component-ready tree.

Sources: [packages/obsidian/src/remark/remark-convert.ts:10-46](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-convert.ts#L10-L46)

## Block ID Transformation

Obsidian uses `^block-id` as an anchor. The `remarkBlockId` plugin parses these IDs by visiting `paragraph` nodes, scanning for the regex `/(?<!\\)\^(?<block_id>\w+)$/m`, and replacing the paragraph with a `<section>` element featuring the corresponding `id` attribute.

```mermaid
flowchart TD
    A[Visit Paragraph] --> B{Matches Block ID Regex?}
    B -->|Yes| C[Extract ID]
    C --> D[Replace Node with Section Element]
    B -->|No| E[Skip Node]
```
Sources: [packages/obsidian/src/remark/remark-block-id.ts:7-50](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/remark/remark-block-id.ts#L7-L50)

## Lifecycle of a Vault Conversion

The `fromVault` entry point orchestrates the lifecycle:
1. `readVaultFiles`: Fetches raw file contents from the disk.
2. `convertVaultFiles`:
   - Builds storage and resolver context.
   - Runs the Remark processor chain (`remark-parse` → `remark-gfm` → `remark-math` → `remarkWikilinks` → `remarkConvert` → `remarkObsidianComment` → `remarkBlockId`).
   - Stringifies back to MDX using `remark-mdx` and `remark-stringify`.
3. `writeVaultFiles`: Maps the resulting output types (asset, content, data) to their respective destinations.

```mermaid
sequenceDiagram
    participant Input as ReadFiles
    participant Storage as BuildStorage
    participant Proc as Remark Processor
    participant Output as WriteFiles
    
    Input->>Storage: Load files
    Storage->>Proc: Initialize storage & resolver
    Proc->>Proc: Run Remark plugins chain
    Proc->>Output: Emit output files
```
Sources: [packages/obsidian/src/index.ts:15-20](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/index.ts#L15-L20), [packages/obsidian/src/convert.ts:57-119](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/convert.ts#L57-L119)

## Related

- [Content Storage](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/content-engine/content-storage)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
