DEV Community

Ondrej Machala
Ondrej Machala

Posted on

Dark Mode Screenshots in Docusaurus (That Actually Switch)

Docusaurus has dark mode built in. Your docs adapt. Your code blocks adapt.

Your screenshots don't.

You know the look - a crisp white UI screenshot glowing in the middle of someone's dark mode docs. Jarring.

The Workaround Nobody Wants to Do

You could maintain two versions of every screenshot. Light and dark. Then write custom React components to toggle between them based on color scheme. CSS media queries, theme context hooks, the works.

Or:

npm install heroshot
Enter fullscreen mode Exit fullscreen mode

How It Works

Heroshot has a Docusaurus plugin that handles theme switching automatically. One component, zero JavaScript gymnastics.

Add the plugin to your config:

// docusaurus.config.js
const { heroshot } = require('heroshot/plugins/docusaurus');

module.exports = {
  plugins: [heroshot()],
  // ... rest of config
};
Enter fullscreen mode Exit fullscreen mode

Use it in your MDX:

import { Heroshot } from 'heroshot/docusaurus';

# Getting Started

<Heroshot name="dashboard" alt="Dashboard overview" />
Enter fullscreen mode Exit fullscreen mode

That's it. The component:

  • Finds both light and dark variants of your screenshot
  • Watches the Docusaurus theme toggle
  • Switches images instantly when someone clicks the moon icon
  • No page reload. No flash.

Setting Up Screenshots

First, capture them. Run the visual picker:

npx heroshot config
Enter fullscreen mode Exit fullscreen mode

Start your Docusaurus dev server in another terminal. Navigate to it in the heroshot browser. Click elements you want to capture. Name them. Close when done.

Heroshot saves a config file. Then capture everything:

npx heroshot
Enter fullscreen mode Exit fullscreen mode

This generates files like:

static/heroshots/dashboard-light.png
static/heroshots/dashboard-dark.png
Enter fullscreen mode Exit fullscreen mode

Both variants captured automatically.

The Full Setup

Your project structure:

my-docs/
├── docs/
│   └── intro.mdx
├── static/
│   └── heroshots/     # screenshots go here
├── .heroshot/
│   └── config.json
└── docusaurus.config.js
Enter fullscreen mode Exit fullscreen mode

Your heroshot config:

{
  "outputDirectory": "static/heroshots",
  "browser": {
    "deviceScaleFactor": 2
  },
  "screenshots": []
}
Enter fullscreen mode Exit fullscreen mode

The deviceScaleFactor: 2 gives you retina-quality images. Worth it for docs.

Multiple Viewports

Need mobile and desktop versions?

{
  "name": "dashboard",
  "url": "https://myapp.com/dashboard",
  "viewports": ["mobile", "desktop"]
}
Enter fullscreen mode Exit fullscreen mode

The component generates <picture> elements with media queries. Small screens see the mobile shot, large screens see desktop. Each with proper light/dark variants.

Updating Screenshots

UI changed? One command:

npx heroshot
Enter fullscreen mode Exit fullscreen mode

Every screenshot regenerates. Both color schemes. All viewports. Your docs stay accurate.

How the Theme Detection Works

Docusaurus uses <html data-theme="dark"> when someone toggles dark mode. The component watches this attribute. Light screenshot shows by default, dark version swaps in when the theme changes.

Works with Docusaurus's built-in toggle. Works with any theme that follows the same pattern.

CI Integration

Add it to your build pipeline:

- run: npx heroshot
- run: npm run build
Enter fullscreen mode Exit fullscreen mode

Screenshots update before every deploy. Documentation never goes stale.


heroshot - automatic screenshots for Docusaurus docs.

Top comments (0)