> ## Documentation Index
> Fetch the complete documentation index at: https://docs.holydocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from Docusaurus

Migrate your Docusaurus documentation to HolyDocs with configuration and component conversion.

## Overview

Docusaurus is a popular documentation framework from Meta. HolyDocs can automatically convert your Docusaurus project, including the `docusaurus.config.js` theme settings, `sidebars.js` navigation structure, and MDX content with admonitions and other Docusaurus-specific syntax.

HolyDocs migrates the **docs** portion of Docusaurus projects. Blog posts, custom pages, and React-based pages are not included in the migration since HolyDocs is purpose-built for documentation.

## Automatic Migration

```bash
# Install HolyDocs CLI
npm install -g holydocs

# Migrate from your Docusaurus project directory
holydocs migrate --from docusaurus

# Preview without modifying files
holydocs migrate --from docusaurus --dry-run
```

The CLI auto-detects Docusaurus projects by the presence of `docusaurus.config.js` or `docusaurus.config.ts`.

## What Gets Converted

**docusaurus.config.js becomes docs.json**

Theme configuration, site metadata, navbar items, and footer links are extracted and mapped to `docs.json` fields.
  **sidebars.js becomes navigation**

Sidebar items — including categories, auto-generated sidebars, and document references — are converted to HolyDocs `navigation.tabs[].groups` structure.
  **Admonitions become Callouts**

Docusaurus admonition syntax (`:::note`, `:::tip`, etc.) is converted to HolyDocs `Callout` components.
  **MDX components are mapped**

Docusaurus-specific imports and components like `<Tabs>`, `<TabItem>`, and `<Details>` are converted to their HolyDocs equivalents.
  **Frontmatter is preserved**

Page frontmatter fields like `title`, `description`, `sidebar_label`, and `sidebar_position` are preserved or remapped.

## Configuration Mapping

### docusaurus.config.js to docs.json

| docusaurus.config.js | docs.json | Notes |
|---|---|---|
| `title` | `name` | Site title |
| `favicon` | `favicon` | Direct mapping |
| `themeConfig.navbar.title` | `name` | Fallback if `title` not set |
| `themeConfig.navbar.logo` | `logo` | Maps `src` and `srcDark` to `light` and `dark` |
| `themeConfig.navbar.items` | `navbar.links` | External links become header links |
| `themeConfig.colorMode.defaultMode` | `appearance.default` | `"light"` or `"dark"` |
| `themeConfig.colorMode.disableSwitch` | `appearance.strict` | Boolean mapping |
| `themeConfig.footer.links` | `footer.socials` / `footer.links` | Social links and grouped footer columns |
| `themeConfig.algolia` | — | Replaced by built-in HolyDocs search |
| `url` | — | Used for canonical URL generation |
| `baseUrl` | — | Used during path resolution |

### Theme Colors

Docusaurus uses CSS custom properties for theming. The migration extracts the primary color from `custom.css` or `themeConfig`:

```css
/* Docusaurus custom.css */
:root {
  --ifm-color-primary: #2e8555;
}
```

This becomes:

```json
{
  "colors": {
    "primary": "#2e8555"
  }
}
```

## Sidebar Conversion

### sidebars.js to docs.json Navigation

Docusaurus sidebars support several item types. Each is handled during migration:

| Sidebar Item Type | docs.json Mapping |
|---|---|
| `type: 'doc'` | Page reference in `groups[].pages` |
| `type: 'category'` | Navigation group (`groups[].group`) |
| `type: 'link'` | External link (added to topbar or group) |
| `type: 'autogenerated'` | Resolved from directory structure |
| `type: 'ref'` | Same as `doc` (cross-sidebar reference) |
| String shorthand | Page reference in `groups[].pages` |

**sidebars.js (Before)**

```javascript
    module.exports = {
      docs: [
        {
          type: 'category',
          label: 'Getting Started',
          items: [
            'intro',
            'installation',
            'quick-start',
          ],
        },
        {
          type: 'category',
          label: 'Guides',
          items: [
            'guides/authentication',
            'guides/pagination',
            {
              type: 'category',
              label: 'Advanced',
              items: [
                'guides/advanced/webhooks',
                'guides/advanced/rate-limiting',
              ],
            },
          ],
        },
        {
          type: 'category',
          label: 'API Reference',
          items: [
            {
              type: 'autogenerated',
              dirName: 'api',
            },
          ],
        },
      ],
    };
    ```
  **docs.json (After)**

```json
    {
      "navigation": {
        "tabs": [
          {
            "tab": "Documentation",
            "groups": [
              {
                "group": "Getting Started",
                "pages": [
                  "intro",
                  "installation",
                  "quick-start"
                ]
              },
              {
                "group": "Guides",
                "pages": [
                  "guides/authentication",
                  "guides/pagination",
                  "guides/advanced/webhooks",
                  "guides/advanced/rate-limiting"
                ]
              },
              {
                "group": "API Reference",
                "pages": [
                  "api/overview",
                  "api/users",
                  "api/projects",
                  "api/billing"
                ]
              }
            ]
          }
        ]
      }
    }
    ```

Deeply nested Docusaurus categories (3+ levels) are flattened into two-level groups. Page paths are preserved so links remain valid.

### Multiple Sidebars

If your Docusaurus project uses multiple sidebars, each becomes a separate tab in HolyDocs:

```javascript
// sidebars.js
module.exports = {
  docs: [/* ... */],
  api: [/* ... */],
  community: [/* ... */],
};
```

Becomes three tabs: "Docs", "API", and "Community" in `docs.json`.

## Content Conversion

### Admonitions to Callouts

Docusaurus uses a triple-colon syntax for admonitions. These are converted to HolyDocs `Callout` components.

**Docusaurus Syntax**

```markdown
    :::note
    This is a note admonition.
    :::

    :::tip
    A helpful tip for the reader.
    :::

    :::info
    Additional context or background.
    :::

    :::caution
    Proceed with care.
    :::

    :::danger
    This action is irreversible.
    :::

    :::note[Custom Title]
    A note with a custom title.
    :::
    ```
  **HolyDocs Syntax**

```mdx
    <Callout type="note">
      This is a note admonition.
    </Callout>

    <Callout type="tip">
      A helpful tip for the reader.
    </Callout>

    <Callout type="info">
      Additional context or background.
    </Callout>

    <Callout type="caution">
      Proceed with care.
    </Callout>

    <Callout type="warning">
      This action is irreversible.
    </Callout>

    <Callout type="note" title="Custom Title">
      A note with a custom title.
    </Callout>
    ```

| Docusaurus Admonition | HolyDocs Callout Type |
|---|---|
| `:::note` | `<Callout type="note">` |
| `:::tip` | `<Callout type="tip">` |
| `:::info` | `<Callout type="info">` |
| `:::caution` | `<Callout type="caution">` |
| `:::danger` | `<Callout type="warning">` |

### Tabs and TabItem

**Docusaurus Syntax**

````mdx
    import Tabs from '@theme/Tabs';
    import TabItem from '@theme/TabItem';

    <Tabs>
      <TabItem value="js" label="JavaScript">
        ```javascript
        const data = await fetch('/api');
        ```
      </TabItem>
      <TabItem value="py" label="Python">
        ```python
        data = requests.get('/api')
        ```
      </TabItem>
    </Tabs>
    ````
  **HolyDocs Syntax**

````mdx
    <Tabs>
      <Tab title="JavaScript">
        ```javascript
        const data = await fetch('/api');
        ```
      </Tab>
      <Tab title="Python">
        ```python
        data = requests.get('/api')
        ```
      </Tab>
    </Tabs>
    ````

The migration:
- Removes `import` statements for `@theme/Tabs` and `@theme/TabItem`
- Renames `<TabItem>` to `<Tab>`
- Converts the `label` prop to `title`
- Removes the `value` prop (not needed in HolyDocs)

### Details to Accordion

**Docusaurus Syntax**

```mdx
    <details>
      <summary>Click to expand</summary>
      Detailed content that is hidden by default.
    </details>
    ```
  **HolyDocs Syntax**

```mdx
    <Accordion title="Click to expand">
      Detailed content that is hidden by default.
    </Accordion>
    ```

### Code Blocks

Docusaurus code blocks with the `title` attribute are converted to HolyDocs code blocks:

**Docusaurus**

````markdown
    ```javascript title="src/index.js"
    console.log('Hello');
    ```
    ````
  **HolyDocs**

````markdown
    ```javascript title="src/index.js"
    console.log('Hello');
    ```
    ````

Code block titles are supported natively in HolyDocs, so no conversion is needed for this syntax.

## React Component Handling

Docusaurus allows importing custom React components in MDX files. HolyDocs does not support arbitrary React imports since content is pre-rendered at build time.

Custom React components imported from `@site/src/components` or local paths will not work in HolyDocs. The migration CLI reports these imports so you can replace them with built-in HolyDocs components or static content.

### Common Replacements

| Docusaurus Component | HolyDocs Alternative |
|---|---|
| Custom `<Card>` component | Built-in `<Card>` component |
| Custom `<Banner>` or `<Hero>` | `<Callout>` with appropriate type |
| `<CodeBlock>` import | Native fenced code blocks |
| `@theme/TOCInline` | Automatic TOC (configured in `docs.json`) |
| `@theme/DocCardList` | `<CardGroup>` with `<Card>` items |
| `BrowserOnly` wrapper | Not needed (no client-side rendering) |

### Handling MDX v1 vs v2 Syntax

Docusaurus v2 uses MDX v1, while Docusaurus v3 uses MDX v2. HolyDocs uses MDX v2+ syntax. Key differences:

| MDX v1 (Docusaurus v2) | MDX v2+ (HolyDocs) |
|---|---|
| `{/* comment */}` | `{/* comment */}` (same) |
| Indented JSX under lists | Requires explicit newline before JSX |
| `<img>` self-closing optional | `<img />` self-closing required |
| Unescaped `{` in text | Must escape as `\{` |
| Unescaped `<` in text | Must escape as `\<` or use `&lt;` |

Run `holydocs check` after migration to catch any MDX v2 syntax issues. The checker reports exact line numbers and suggested fixes.

## Frontmatter Mapping

| Docusaurus Frontmatter | HolyDocs Frontmatter | Notes |
|---|---|---|
| `title` | `title` | Direct mapping |
| `description` | `description` | Direct mapping |
| `sidebar_label` | `sidebarTitle` | Renamed |
| `sidebar_position` | — | Ordering is defined in `docs.json` navigation |
| `slug` | — | URL paths are file-path based |
| `tags` | `tags` | Direct mapping |
| `hide_title` | `hideTitle` | Renamed |
| `hide_table_of_contents` | `toc` | `true` becomes `false` (inverted) |
| `keywords` | `seo.keywords` | Moved under `seo` |
| `image` | `seo.ogImage` | Used for Open Graph |
| `draft` | `draft` | Direct mapping |

## Verification

**Validate the project**

```bash
    holydocs check
    ```

    Pay attention to:
    - MDX syntax errors (especially if migrating from Docusaurus v2 / MDX v1)
    - Missing page references in navigation
    - Unresolved React component imports
  **Preview locally**

```bash
    holydocs dev
    ```

    Check each section of your docs for:
    - Correct navigation structure
    - Properly rendered callouts (no raw `:::` syntax)
    - Working tabs and accordions
    - Images loading correctly
  **Search for unconverted syntax**

Look for any remaining Docusaurus-specific syntax:

    ```bash
    # Check for remaining admonitions
    grep -r "^:::" --include="*.mdx" .

    # Check for Docusaurus imports
    grep -r "@theme/" --include="*.mdx" .
    grep -r "@site/" --include="*.mdx" .

    # Check for TabItem usage
    grep -r "TabItem" --include="*.mdx" .
    ```
  **Deploy**

```bash
    holydocs deploy
    ```

## Common Issues

**MDX parsing errors after migration**

This is most often caused by MDX v1 syntax that is invalid in MDX v2. Common culprits include unescaped curly braces `{` in text content, HTML comments `<!-- -->` (use `{/* */}` instead), and self-closing HTML tags without the slash. Run `holydocs check` for exact error locations.
  **Sidebar categories are flattened**

Docusaurus supports arbitrarily deep category nesting. HolyDocs uses a two-level structure (tabs and groups). Categories deeper than two levels are flattened into the nearest parent group. The page paths and content remain unchanged.
  **Custom theme components not rendering**

Components imported from `@theme/` or `@site/src/components` are not available in HolyDocs. Replace them with built-in HolyDocs components. The migration CLI lists all unresolved imports in its output.
  **Blog and custom pages missing**

HolyDocs migrates only the docs portion of a Docusaurus site. Blog posts, custom pages, and standalone React pages are not included. If you need to preserve this content, consider keeping a separate Docusaurus instance for the blog.
  **Docusaurus plugins not supported**

Docusaurus plugins (like `docusaurus-plugin-openapi`, `docusaurus-plugin-sass`, etc.) are not migrated. HolyDocs has built-in equivalents for common plugins:

    | Docusaurus Plugin | HolyDocs Equivalent |
    |---|---|
    | `docusaurus-plugin-openapi` | Built-in `openapi` config + API playground |
    | `@docusaurus/plugin-google-analytics` | `analytics.googleAnalytics` in docs.json |
    | `@docusaurus/plugin-sitemap` | Automatic sitemap generation |
    | `docusaurus-plugin-sass` | `customCss` in docs.json |
  **Versioned docs**

Docusaurus versioned docs (in `versioned_docs/` and `versioned_sidebars/`) are not automatically migrated. HolyDocs has its own versioning system. Migrate your current docs first, then set up versioning through the HolyDocs dashboard. See the [versioning documentation](/versioning) for details.