# Migrating from Docusaurus {#migrating-from-docusaurus}


`sourcey migrate docusaurus` reads `docusaurus.config.*`, your sidebars and your docs, and writes a standalone Sourcey project beside them. Your Markdown stays where it is; only the syntax that needs a native form changes.

```bash
npm install            # the configuration is loaded with your own dependencies
npx sourcey migrate docusaurus --dry-run
```

Docusaurus configuration and sidebar files are programs: they can read files, branch on environment variables and call `require.resolve`. The migration loads them the way Docusaurus does, with your installed dependencies and `NODE_ENV=production`, so run it in the environment your production build uses (for example with the same `DOCS_LOCALES` or `.env`). Documents themselves are read, never run.


## Configuration {#configuration}


| Docusaurus | Native Sourcey |
| --- | --- |
| `title`, `url`, `baseUrl`, `trailingSlash` | `name`, `siteUrl`, `baseUrl`, `prettyUrls` |
| docs plugin instances (`routeBasePath`, `path`) | a navigation tab each, at the same route |
| `versions.json`, `versioned_docs`, `versioned_sidebars`, `lastVersion`, `versions` | tab versions with the same paths and labels; `banner` becomes the version's status and `noIndex` keeps it out of search engines |
| `i18n.locales`, `localeConfigs` | `i18n` with the same URL prefixes, labels, language and direction |
| `editUrl` (a string) | `repo`, `editBranch`, `editBasePath` |
| `showLastUpdateTime` | [`lastUpdated`](https://sourcey.com/docs/config/ref-config.md#last-updated) |
| `onBrokenLinks: "throw"`, the default | [`brokenLinks: "error"`](https://sourcey.com/docs/config/ref-config.md#broken-links) |
| docs `breadcrumbs`, on unless a docs instance turns them off | [`navigation.breadcrumbs`](https://sourcey.com/docs/config/ref-config.md#breadcrumbs) |
| frontmatter `custom_edit_url` | frontmatter `editUrl` (`null` becomes `false`) |
| `markdown.preprocessor` | run on each document as Docusaurus runs it; its result is written as the native page |
| `staticDirectories` | `publicDir`; several directories are merged into one |
| `themeConfig.navbar` logo, links, doc links and dropdowns, `footer` links and copyright | `logo`, `navbar.links` (dropdowns as menus), `footer.links`, `footer.text` |
| `colorMode`, `--ifm-color-primary` in custom CSS | `theme.appearance`, `theme.colors` |
| `@docusaurus/plugin-client-redirects` (`redirects` and `createRedirects`) | `redirects` |
| `headTags`, `stylesheets`, `scripts`, and Google Analytics (`gtag` in the classic preset, or `@docusaurus/plugin-google-gtag`) | `components/Head.html`, which every page's head ends with |
| swizzled theme components in `src/theme` | listed in the report; a [page part](https://sourcey.com/docs/components.md#page-parts) in `components/` draws a header, footer or the end of a page of the site's own |


## Docs and sidebars {#docs-and-sidebars}


Every page keeps its URL, computed as Docusaurus computes it: number prefixes such as `01-intro.md` are dropped, a frontmatter `id` names the page inside its directory, a `slug` is resolved against it, and `index`, `README` or a file named after its directory is the directory's page. The configuration keeps file names as routes (`markdown({ slugs: "file" })`) when that matches most pages; the others get an explicit `slug`.

Sidebars become native navigation in the order Docusaurus showed them, including autogenerated sidebars with `_category_.json` labels, positions and links. A category that links a page lands on it; a generated-index category becomes an authored page listing its section with `<PageCards>`. Pages no sidebar lists stay published, out of the menu. Several sidebars become sections of one navigation, each named by the navbar's link into it and open while the reader is in it, as Docusaurus shows one sidebar at a time; the tab's own sidebar leads as written. A sidebar's HTML item that is a heading, a few words such as "API", heads the items after it.

Each translation moves once from `i18n/<locale>/docusaurus-plugin-content-docs/<version>/` to a directory of the locale's name inside the content it translates, which is where native reads a locale. Untranslated pages fall back to the default language, as they did. Translated category labels become the locale's navigation messages.


## Markdown and components {#markdown-and-components}


Pages are read the way your Docusaurus version read them. Docusaurus 3 reads Markdown as MDX 3. Docusaurus 2 read it as MDX 1, where indented lines are code, braces in text are text, and a `<` that opens no HTML tag, such as `<PROXY_IP>`, is a character; the migration keeps those as they were. Components your swizzled `src/theme/MDXComponents` makes available on every page are recognised as if each page imported them.

| Docusaurus | Native Sourcey |
| --- | --- |
| `:::note Title` and `:::note[Title]` admonitions | `:::note[Title]`; `important`, `success` and `secondary` become the callout they rendered as, with their title |
| `` ```mdx-code-block `` | its contents, converted like the rest of the page |
| HTML comments in MDX | kept as written |
| `@theme/Tabs`, `@theme/TabItem` | `Tabs` and `Tab`; native tabs open on their first tab and are chosen per set, so `groupId`, `queryString` and a default tab are listed in the report |
| `@theme/Admonition` | the matching callout |
| `@theme/DocCardList` | `PageCards` for the category the page lands |
| `@docusaurus/Link` | a Markdown link; inside an HTML element, or with an anchor's attributes such as `className` or `style`, the anchor Docusaurus draws |
| `@theme/CodeBlock` | a fenced code block with its language and title |
| `@theme/ThemedImage` | a figure with its light and dark pictures |
| imported Markdown partials | `<Include>` |
| `src/pages/*.md` | [site pages](https://sourcey.com/docs/config/ref-config.md#site-pages) (`pages: "./src/pages"`), drawn with the site's header and footer as Docusaurus drew them |

A page's JavaScript is read where it is static and written as what it shows: its `export const` values, constants it imports from the project (`@site/` included), `useBaseUrl()`, lists drawn with `.map()` over static data, the page's own components and helper functions, conditional JSX such as `{premium && <Badge />}`, and pure string and array methods. A style object is written as the CSS React writes from it. Anything else, such as state, effects or a fetch, stops the migration at its line.


## What stops a migration {#what-stops-a-migration}


React pages, your own components (until you convert them in the `--mapping` file), API reference plugins, tag pages and content MDX 3 cannot read stop the migration with the file and line. A React page you are retiring can be listed under `docusaurus.removePages` in the mapping file.
