Sphinx
Want to see it working? Check out the full example on GitHub - a minimal Furo setup you can clone and run.
Sphinx is what Python itself uses for documentation. If you're documenting a serious Python library, chances are you're using Sphinx. The heroshot extension gives you a .. heroshot:: directive that handles theme switching automatically - just drop it in and it works with Furo, PyData, and anything that uses prefers-color-scheme.
Getting Started
Install heroshot with Sphinx support:
pip install heroshot[sphinx]Then run it (requires Node.js):
npx heroshotThis opens a browser with the visual picker. Start your Sphinx dev server (I'd recommend sphinx-autobuild), navigate to it in the heroshot browser, click on elements you want to capture, and close when done.
Where to Put Screenshots
Sphinx serves static assets from _static/. Put screenshots in _static/heroshots/:
my-project/
├── docs/
│ ├── conf.py
│ ├── index.rst
│ └── _static/
│ └── heroshots/ # heroshot outputs here
├── Makefile
└── requirements.txtSet the output directory in heroshot's toolbar (Settings), or edit .heroshot/config.json:
{
"outputDirectory": "docs/_static/heroshots"
}Setting Up the Extension
Add heroshot.sphinx to your extensions in conf.py:
extensions = ['heroshot.sphinx']That's it. The extension registers the directive and injects the CSS for theme switching.
Using the Directive
Basic theme-aware screenshot in RST:
.. heroshot:: dashboard
:alt: Dashboard overviewThis renders both light and dark variants. When the user switches themes (Furo's toggle, PyData's switcher, or OS preference), the screenshot switches too.
With sizing and alignment:
.. heroshot:: sidebar
:alt: Sidebar navigation
:width: 400px
:align: centerFor screenshots without theme variants, use heroshot-single:
.. heroshot-single:: architecture
:alt: System architecture diagram
:width: 600pxMyST Markdown
If you're using MyST Parser for Markdown in Sphinx, the directive works the same way:
```{heroshot} dashboard
:alt: Dashboard overview
```Or without theme variants:
```{heroshot-single} architecture
:alt: System architecture
:width: 600px
```Responsive Viewports
If you've captured multiple viewport sizes, pass them as a comma-separated list:
.. heroshot:: hero
:alt: Hero section
:viewports: mobile, tablet, desktopThis generates a <picture> element with media queries - the browser picks the right size automatically. Each viewport also gets light/dark variants, so you get full theme + responsive coverage.
Theme Support
The extension works with any Sphinx theme that supports dark mode:
Furo - Uses data-theme attribute. The most popular modern Sphinx theme with built-in dark mode toggle. Works out of the box.
PyData Sphinx Theme - Used by NumPy, Pandas, and the scientific Python ecosystem. Also uses data-theme. Works out of the box.
Read the Docs Theme - The classic. Doesn't have a dark mode toggle, so only light screenshots are shown. You can still use heroshot-single for these projects.
Any theme with prefers-color-scheme - If the theme respects the OS dark mode preference, heroshot picks up on that automatically.
Configuration
You can customize paths and naming in conf.py:
extensions = ['heroshot.sphinx']
# All optional - these are the defaults:
heroshot_path = '_static/heroshots' # where screenshots live
heroshot_light_suffix = '-light' # suffix for light variants
heroshot_dark_suffix = '-dark' # suffix for dark variants
heroshot_format = 'png' # image formatDevelopment Workflow
For local development, I'd recommend two terminals:
# Terminal 1 - live-reloading Sphinx
pip install sphinx-autobuild
sphinx-autobuild docs docs/_build/html# Terminal 2 - capture screenshots
npx heroshotNavigate to http://localhost:8000 in the heroshot browser, capture what you need. The screenshots land in _static/heroshots/ and sphinx-autobuild picks them up.
Makefile Target
Most Sphinx projects already have a Makefile. Add a target for screenshots:
screenshots:
npx heroshot sync
.PHONY: screenshotsThen just:
make screenshots