# How to Customize a Docusaurus Theme Using Swizzling: The Complete Guide

> Learn to customize Docusaurus themes with swizzling. Use the CLI to copy and override default React components in your site src theme folder for easy upgrades.

- Repository: [Meta/docusaurus](https://github.com/facebook/docusaurus)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Use the `docusaurus swizzle` CLI command to copy theme components into your site's `src/theme` folder, allowing you to override or extend the default React components while maintaining upgrade compatibility.**

This guide explains how to customize Docusaurus theme components using the swizzling architecture implemented in the `facebook/docusaurus` repository. Whether you need to tweak the navigation bar, modify the footer, or restructure documentation layouts, swizzling provides a safe mechanism to inject your own React code without forking the entire theme.

## What Is Theme Swizzling in Docusaurus?

Docusaurus themes (such as `@docusaurus/theme-classic`) are distributed as plugins that expose React components through virtual modules aliased as `@theme/*`. When you customize Docusaurus theme using swizzling, you extract specific components from the theme package into your local `src/theme` directory, where Docusaurus's Webpack configuration ([`packages/docusaurus/src/webpack/aliases/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/webpack/aliases/index.ts)) prioritizes your versions over the originals.

The architecture distinguishes between **safe** and **unsafe** components. Safe components, defined in [`packages/docusaurus-theme-classic/src/getSwizzleConfig.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts), maintain backward compatibility across minor releases, while unsafe components require the `--danger` flag and may break during upgrades.

## How the Swizzle Command Works

The swizzle CLI implementation resides in [`packages/docusaurus/src/commands/swizzle/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/commands/swizzle/index.ts), which parses arguments and validates component selections against the safety configuration. When you execute a swizzle command, [`packages/docusaurus/src/commands/swizzle/components.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/commands/swizzle/components.ts) handles the file generation logic, computing component paths and applying either **wrap** or **eject** actions.

**Wrap mode** (recommended) creates a wrapper component that imports the original via `@theme-original/*`, allowing you to augment functionality while delegating rendering to the upstream version. **Eject mode** copies the source file verbatim, giving you full control but requiring manual maintenance when the theme updates.

## Customizing Docusaurus Theme Components Step-by-Step

### Finding Components to Swizzle

First, identify the component you want to override. You can browse the theme source code or use the interactive CLI:

```bash
npx docusaurus swizzle

```

This command displays all available components from installed themes, indicating which are safe to swizzle according to the configuration in [`getSwizzleConfig.ts`](https://github.com/facebook/docusaurus/blob/main/getSwizzleConfig.ts).

### Choosing Between Wrap and Eject

Select the appropriate swizzling strategy based on your customization needs:

- **Wrap**: Use this for additive changes (injecting props, wrapping in HOCs, adding analytics). The generated file imports from `@theme-original/ComponentName`, ensuring you receive upstream bug fixes automatically.

```bash
npx docusaurus swizzle @docusaurus/theme-classic Footer --wrap

```

- **Eject**: Use this when you must fundamentally rewrite the component's render logic. You assume full maintenance responsibility for the component file.

```bash
npx docusaurus swizzle @docusaurus/theme-classic BlogPostItem --eject

```

### Editing Swizzled Components

After running the command, find your new component in `src/theme/`. For example, a wrapped Footer component looks like this:

```tsx
// src/theme/Footer/index.tsx
import React from 'react';
import OriginalFooter from '@theme-original/Footer';
import MyLogo from '@site/static/img/my-logo.svg';

export default function Footer(props) {
  return (
    <div>
      <MyLogo className="myFooterLogo" />
      <OriginalFooter {...props} />
    </div>
  );
}

```

The Webpack alias system ensures that `@theme/Footer` now resolves to your local file, while `@theme-original/Footer` continues to point to the theme's built-in version.

### Handling Unsafe Components

Some internal components (like `DocItem`) are marked unsafe because their APIs may change. To swizzle these, add the `--danger` flag:

```bash
npx docusaurus swizzle @docusaurus/theme-classic DocItem --wrap --danger

```

As implemented in [`packages/docusaurus/src/commands/swizzle/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/commands/swizzle/index.ts), the CLI will prompt for confirmation if you omit the flag, warning you about potential breaking changes during upgrades.

## Practical Examples of Docusaurus Theme Swizzling

### Wrapping a NavbarItem with a Tooltip

This example demonstrates extending a safe component to inject Material-UI tooltips:

```bash
npx docusaurus swizzle @docusaurus/theme-classic NavbarItem --wrap

```

```tsx
// src/theme/NavbarItem/index.tsx
import React from 'react';
import OriginalNavbarItem from '@theme-original/NavbarItem';
import Tooltip from '@mui/material/Tooltip';

export default function NavbarItem(props) {
  return (
    <Tooltip title="Custom tooltip" placement="bottom">
      <OriginalNavbarItem {...props} />
    </Tooltip>
  );
}

```

### Ejecting a BlogPostItem for Complete Customization

When you need to restructure the blog post layout entirely:

```bash
npx docusaurus swizzle @docusaurus/theme-classic BlogPostItem --eject

```

```tsx
// src/theme/BlogPostItem/index.tsx
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';

export default function BlogPostItem({content}) {
  return (
    <article className={clsx('customBlogPostItem')}>
      <h2>{content.title}</h2>
      <p className="customExcerpt">{content.description}</p>
      <Link to={content.permalink}>Read Custom Styled Post →</Link>
    </article>
  );
}

```

## Summary

- **Swizzling** exports theme components from `@docusaurus/theme-classic` (or other themes) into your local `src/theme` directory for customization.
- The CLI implementation in [`packages/docusaurus/src/commands/swizzle/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/commands/swizzle/index.ts) orchestrates the process, while [`components.ts`](https://github.com/facebook/docusaurus/blob/main/components.ts) handles file generation.
- **Wrap mode** preserves upgrade safety by importing the original component via `@theme-original/*`, whereas **eject mode** copies the source directly.
- Safe components are guaranteed compatible across minor releases; unsafe components require `--danger` and manual maintenance.
- Webpack aliases configured in [`packages/docusaurus/src/webpack/aliases/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/webpack/aliases/index.ts) ensure your local files override theme defaults.

## Frequently Asked Questions

### What is the difference between wrap and eject when customizing Docusaurus themes?

**Wrap mode** creates a wrapper component that renders the original theme component as a child, allowing you to inject logic or styling while automatically receiving upstream bug fixes. **Eject mode** copies the entire source code of the component into your project, giving you complete control over the implementation but requiring you to manually merge changes when upgrading Docusaurus.

### Are swizzled components safe to use across Docusaurus upgrades?

It depends on the component's safety classification. Components marked as **safe** in [`packages/docusaurus-theme-classic/src/getSwizzleConfig.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts) maintain stable APIs across minor versions, making upgrades seamless. **Unsafe** components may undergo breaking changes in any release; if you swizzle these, monitor the Docusaurus changelog and test thoroughly after updating.

### How does Docusaurus prioritize my swizzled components over the default theme?

Docusaurus configures Webpack aliases in [`packages/docusaurus/src/webpack/aliases/index.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/webpack/aliases/index.ts) to resolve `@theme/*` imports to your local `src/theme` directory before falling back to the node_modules theme package. When using wrap mode, the system also creates an `@theme-original/*` alias that points to the genuine theme component, allowing your wrapper to import the base implementation.

### Can I swizzle multiple components or entire theme sections at once?

The CLI operates on individual components to ensure intentional customization decisions. While you can run the swizzle command multiple times for different components, you cannot bulk-eject entire directories. This granular approach, enforced by the component resolution logic in [`packages/docusaurus/src/commands/swizzle/components.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus/src/commands/swizzle/components.ts), prevents accidental maintenance burdens from unnecessary ejections.