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 CLInpm install -g holydocs# Migrate from your Docusaurus project directoryholydocs migrate --from docusaurus# Preview without modifying filesholydocs 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 |
javascriptmodule.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', }, ], }, ],};
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.jsmodule.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.
markdown:::noteThis is a note admonition.::::::tipA helpful tip for the reader.::::::infoAdditional context or background.::::::cautionProceed with care.::::::dangerThis action is irreversible.::::::note[Custom Title]A note with a custom title.:::
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
mdximport 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>
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
importstatements for@theme/Tabsand@theme/TabItem - Renames
<TabItem>to<Tab> - Converts the
labelprop totitle - Removes the
valueprop (not needed in HolyDocs)
Details to Accordion
mdx<details> <summary>Click to expand</summary> Detailed content that is hidden by default.</details>
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:
markdown```javascript title="src/index.js"console.log('Hello');```
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 < |
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
bashholydocs 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
bashholydocs 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 admonitionsgrep -r "^:::" --include="*.mdx" .# Check for Docusaurus importsgrep -r "@theme/" --include="*.mdx" .grep -r "@site/" --include="*.mdx" .# Check for TabItem usagegrep -r "TabItem" --include="*.mdx" .
Deploy
bashholydocs deploy
Common Issues
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.
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.
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.
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 (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 |
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 for details.