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:
npm install heroshotVite Plugin Setup
If you're using Vite, add the plugin to your config:
// 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:
// main.tsx or App.tsx
import 'virtual:heroshot-manifest'; // Auto-registers manifestTypeScript support
Add "heroshot/virtual" to your tsconfig.json types for autocomplete:
{
"compilerOptions": {
"types": ["heroshot/virtual"]
}
}Manual Setup (No Plugin)
If you're not using Vite, wrap your app with HeroshotProvider:
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:
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",.darkclass, orprefers-color-scheme) - Responsive viewports - Uses
<picture>with media queries when you have multiple viewport variants - Lazy loading - Images load lazily by default
Props
| Prop | Type | Description |
|---|---|---|
name | string | Screenshot name (as defined in heroshot config) |
alt | string | Alt text for accessibility |
className | string | CSS 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.jsonSet the output directory in heroshot config:
{
"outputDirectory": "public/heroshots"
}Reference them as /heroshots/dashboard.png in your app.
Dark Mode Detection
The component detects dark mode in this order:
data-themeattribute - Used by Docusaurus (<html data-theme="dark">).darkclass - Used by Tailwind and many UI libraries (<html class="dark">)prefers-color-scheme- Browser/OS preference
It also watches for changes, so theme toggles work instantly without page reload.
Example: Image Gallery
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>
);
}