CtrlK
BlogDocsLog inGet started
Tessl Logo

mcclowes/docusaurus-v2-to-v3-migration

Use when migrating Docusaurus projects from v2 to v3 — upgrade @docusaurus/React/MDX/prism dependencies, rewrite MDX v1 syntax to v3 (escape bare { and <, fix autolinks), swap @tsconfig/docusaurus for @docusaurus/tsconfig, update Prism imports, and resolve React 18 breaking changes. Triggers on tasks involving MDX v1 to v3 migration, Docusaurus dependency updates, React 18 compatibility, or v2/v3 breaking changes.

72

Quality

90%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

breaking-changes.mdreferences/

Docusaurus v2 to v3 Breaking Changes

Required Dependency Updates

Core Packages

  • @docusaurus/core: ^2.x.x → ^3.0.0
  • @docusaurus/preset-classic: ^2.x.x → ^3.0.0
  • @mdx-js/react: ^1.6.22 → ^3.0.0
  • prism-react-renderer: ^1.3.5 → ^2.1.0

Runtime Requirements

  • Node.js: >=16.14 → >=18.0
  • React: ^17.0.2 → ^18.2.0
  • TypeScript: ~4.7.4 → ~5.2.2

TypeScript Configuration

Replace @tsconfig/docusaurus with @docusaurus/tsconfig:

{
  "extends": "@docusaurus/tsconfig",
  "compilerOptions": {
    // your custom options
  }
}

MDX v1 to v3 Migration

The transition from MDX v1 to MDX v3 is the main challenge in adopting Docusaurus v3.

Common MDX Issues

Invalid { Characters

Problem: Bare braces are now invalid in MDX unless part of JSX expressions.

Bad:

Use the {key} to access the value

Good:

Use the `{key}` to access the value
Use the \{key\} to access the value

Invalid < Characters

Problem: Bare angle brackets are invalid unless part of HTML/JSX.

Bad:

If x < 5, then...

Good:

If `x < 5`, then...
If x \< 5, then...

GFM Autolinks Removed

Problem: <email@example.com> and <https://example.com> no longer work.

Bad:

Contact us at <support@example.com>

Good:

Contact us at [support@example.com](mailto:support@example.com)
Visit [https://example.com](https://example.com)

Indented Code Blocks

Problem: Indented code blocks (4 spaces) are no longer recognized.

Bad:

Example code:

    const foo = 'bar';

Good:

Example code:

\`\`\`js
const foo = 'bar';
\`\`\`

Emphasis Adjacent to Spaces

Problem: Emphasis marks next to spaces may not work as expected.

Bad:

This is _really _ important

Good:

This is _really_ important

Prism React Renderer Changes

Theme Import Syntax

Old (v1):

const lightTheme = require('prism-react-renderer/themes/github');
const darkTheme = require('prism-react-renderer/themes/dracula');

New (v2):

const {themes} = require('prism-react-renderer');
const lightTheme = themes.github;
const darkTheme = themes.dracula;

Additional Languages

Prism React Renderer v2 includes fewer languages by default. Add required languages:

module.exports = {
  themeConfig: {
    prism: {
      additionalLanguages: ['bash', 'diff', 'json'],
    },
  },
};

React 18 Migration

Automatic JSX Runtime

React imports are no longer required in files using JSX:

Before:

import React from 'react';

export default function MyComponent() {
  return <div>Hello</div>;
}

After:

// No React import needed
export default function MyComponent() {
  return <div>Hello</div>;
}

Hydration Changes

React 18 has stricter hydration requirements. Ensure:

  • Server and client render the same content
  • No conditional rendering based on typeof window
  • Use useEffect for client-only code

Pre-Migration Checklist

  1. Check Node.js version: node --version (must be >=18.0)
  2. Scan for MDX issues: npx docusaurus-mdx-checker
  3. Backup your project: Commit all changes to git
  4. Review dependencies: Check for custom plugins that may need updates
  5. Test in staging: Don't upgrade production directly

Migration Steps

1. Update package.json

{
  "dependencies": {
    "@docusaurus/core": "^3.0.0",
    "@docusaurus/preset-classic": "^3.0.0",
    "@mdx-js/react": "^3.0.0",
    "prism-react-renderer": "^2.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@docusaurus/tsconfig": "^3.0.0",
    "@docusaurus/types": "^3.0.0",
    "typescript": "~5.2.2"
  },
  "engines": {
    "node": ">=18.0"
  }
}

2. Update TypeScript Config

{
  "extends": "@docusaurus/tsconfig",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@site/*": ["./*"]
    }
  }
}

3. Install Dependencies

npm install

4. Fix MDX Files

Run the checker and fix reported issues:

npx docusaurus-mdx-checker

Common fixes:

  • Wrap { and < in backticks or escape them
  • Convert GFM autolinks to standard Markdown links
  • Replace indented code blocks with fenced code blocks

5. Update docusaurus.config.js

Update Prism configuration:

const {themes} = require('prism-react-renderer');

module.exports = {
  themeConfig: {
    prism: {
      theme: themes.github,
      darkTheme: themes.dracula,
      additionalLanguages: ['bash', 'diff', 'json'],
    },
  },
};

6. Test Locally

npm start

Visit http://localhost:3000 and check:

  • All pages load without errors
  • MDX components render correctly
  • Code blocks display properly
  • Navigation works

7. Production Build

npm run build

Fix any build errors before deploying.

Optional Improvements

Migrate to ESM

Convert docusaurus.config.js to docusaurus.config.mjs:

import {themes} from 'prism-react-renderer';

export default {
  // config
};

Use TypeScript Config

Rename to docusaurus.config.ts:

import type {Config} from '@docusaurus/types';
import {themes} from 'prism-react-renderer';

const config: Config = {
  // config
};

export default config;

Rename MD to MDX

For files containing JSX, rename .md.mdx:

# Example
mv blog/my-post.md blog/my-post.mdx

Update Math Packages

If using math support:

{
  "remark-math": "^6.0.0",
  "rehype-katex": "^7.0.0"
}

Troubleshooting

MDX Parse Errors

Use the MDX Playground to debug:

  1. Enable "remark-gfm" plugin
  2. Enable "remark-directive" plugin
  3. Paste your MDX content
  4. Fix reported errors

Build Failures

Common causes:

  • Outdated plugins or themes
  • Custom components using React 17 APIs
  • Invalid MDX syntax not caught by checker

Hydration Mismatches

React 18 is stricter about hydration. Check for:

  • Client-only code in render
  • Conditional rendering based on window
  • Inconsistent server/client output

Missing Prism Languages

If code blocks don't highlight properly, add to additionalLanguages:

prism: {
  additionalLanguages: ['java', 'php', 'ruby', 'python'],
}

Getting Help

Resources

README.md

SKILL.md

tile.json