Skip to content

React ​

React apps using Vite or webpack can use the <Heroshot> component to render screenshots with automatic light/dark mode and viewport switching.

Component Setup ​

Install heroshot:

bash
npm install heroshot

Vite Plugin Setup ​

If you're using Vite, add the plugin to your config:

ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { heroshot } from 'heroshot/plugins/vite';

export default defineConfig({
  plugins: [react(), heroshot()],
});

Then import the virtual manifest in your app entry:

tsx
// main.tsx or App.tsx
import 'virtual:heroshot-manifest'; // Auto-registers manifest

TypeScript support

Add "heroshot/virtual" to your tsconfig.json types for autocomplete:

json
{
  "compilerOptions": {
    "types": ["heroshot/virtual"]
  }
}

Manual Setup (No Plugin) ​

If you're not using Vite, wrap your app with HeroshotProvider:

tsx
import { HeroshotProvider } from 'heroshot/react';
import manifest from './.heroshot/config.json';

function App() {
  return <HeroshotProvider manifest={manifest}>{/* Your app */}</HeroshotProvider>;
}

Docusaurus

Docusaurus uses webpack, not Vite. See the Docusaurus integration for webpack-based setup.

Using the Component ​

Import and use the component anywhere:

tsx
import { Heroshot } from 'heroshot/react';

function DocsPage() {
  return (
    <article>
      <h1>Dashboard Overview</h1>
      <Heroshot name="dashboard" alt="Dashboard showing key metrics" />
    </article>
  );
}

The component handles everything:

  • Light/dark mode - Automatically switches based on your app's theme (detects data-theme="dark", .dark class, or prefers-color-scheme)
  • Responsive viewports - Uses <picture> with media queries when you have multiple viewport variants
  • Lazy loading - Images load lazily by default

Props ​

PropTypeDescription
namestringScreenshot name (as defined in heroshot config)
altstringAlt text for accessibility
classNamestringCSS class to apply to the image

Where to Put Screenshots ​

For Vite projects, put screenshots in public/:

my-app/
├── public/
│   └── heroshots/    # heroshot outputs here
├── src/
│   └── App.tsx
├── vite.config.ts
└── package.json

Set the output directory in heroshot config:

json
{
  "outputDirectory": "public/heroshots"
}

Reference them as /heroshots/dashboard.png in your app.

Dark Mode Detection ​

The component detects dark mode in this order:

  1. data-theme attribute - Used by Docusaurus (<html data-theme="dark">)
  2. .dark class - Used by Tailwind and many UI libraries (<html class="dark">)
  3. prefers-color-scheme - Browser/OS preference

It also watches for changes, so theme toggles work instantly without page reload.

tsx
import { Heroshot } from 'heroshot/react';

const screenshots = ['dashboard', 'settings', 'profile', 'analytics'];

function ScreenshotGallery() {
  return (
    <div className="grid grid-cols-2 gap-4">
      {screenshots.map(name => (
        <Heroshot
          key={name}
          name={name}
          alt={`${name} screenshot`}
          className="rounded-lg shadow-md"
        />
      ))}
    </div>
  );
}