Get started with Reshot

Set up screenshot automation in your project. Captures run against your production build locally — no credentials leave your machine until you choose to publish.

Prompt
Set up Reshot screenshot automation

I'm integrating Reshot into my project to automate product screenshots. Help me configure the CLI and create a working reshot.config.json for my app.

Prerequisites:
* Node.js 18+
* Google Chrome installed
* macOS, Linux, or Windows with WSL
* Create a branch from main if not already in one

Step 1: Install the Reshot CLI globally

Ask for the preferred package manager. For example, if the user wants npm:
npm install -g @reshotdev/screenshot

Verify with:
reshot --version

Step 2: Analyze the project before writing config

Scan the project to understand:

1. Framework — Identify the framework (Next.js, Vite, Remix, Astro, etc.) and the correct production build + start commands.
2. Routes — Find the app routes and identify which ones are public vs. protected behind authentication.
3. Target pages — Ask the user which pages they want to capture. If they are unsure, suggest the most important product routes you found.
4. Loading and error states — Identify loading text, generic error text, and empty-state text that should not appear in captures.
5. Existing readiness signals — Check whether the target pages already expose stable selectors or test IDs that can be used for capture readiness.

Step 3: Add readiness attributes to the pages being captured

For each target page, add a stable selector to the outermost container that should exist only when meaningful content is ready.

Recommended pattern:
1. data-testid="[page-name]-content"
2. data-loaded="true" once the page is actually ready

Recommended selector:
[data-testid='page-name-content'][data-loaded='true']

If the page only renders after data is ready, a simple [data-testid='page-name-content'] selector is acceptable.

Example:

export default function DashboardPage({ data, isLoading }) {
  return (
    <div
      data-testid="dashboard-content"
      data-loaded={!isLoading && data ? "true" : undefined}
    >
      {isLoading ? <Skeleton /> : <DashboardContent data={data} />}
    </div>
  );
}

If the page needs a custom readiness signal, use a dedicated selector such as:

<div data-reshot-ready="playground-ready">

Step 4: Create reshot.config.json in the project root

Write the config based on the project analysis. Use this structure:

{
  "$schema": "https://reshot.dev/schemas/reshot-config.json",
  "version": "2.0",
  "baseUrl": "http://localhost:3000",
  "defaultWaitUntil": "networkidle",
  "headless": true,
  "viewport": {
    "width": 1440,
    "height": 900,
    "deviceScaleFactor": 2
  },
  "quality": {
    "forbidText": [
      "Loading...",
      "Something went wrong",
      "Error",
      "Sign in"
    ]
  },
  "scenarios": []
}

Populate forbidText with the loading, error, and auth text found during analysis.

Add one scenario per target page.

Public page example:

{
  "key": "landing-page",
  "name": "Landing Page",
  "url": "/",
  "requiresAuth": false,
  "readySelector": "[data-testid='landing-content'][data-loaded='true']",
  "readyTimeout": 15000,
  "steps": [
    { "action": "wait", "ms": 1000 },
    {
      "action": "screenshot",
      "key": "landing-hero",
      "description": "Landing page after content has loaded"
    }
  ]
}

Protected page example:

{
  "key": "dashboard-overview",
  "name": "Dashboard Overview",
  "url": "/dashboard",
  "captureClass": "live-auth",
  "requiresAuth": true,
  "readySelector": "[data-testid='dashboard-content'][data-loaded='true']",
  "readyTimeout": 30000,
  "steps": [
    { "action": "wait", "ms": 2000 },
    {
      "action": "screenshot",
      "key": "dashboard-overview",
      "description": "Dashboard with primary content loaded"
    }
  ]
}

Rules:
- Every scenario must have a unique key and a human-readable name.
- url is the target route. Do not add a goto step.
- Protected routes use captureClass: "live-auth" and requiresAuth: true. Do not script the login form.
- screenshot steps need a unique key and description.
- Prefer page-owned readiness selectors over long fixed waits.
- Use waitForSelector when waiting on a specific element inside a scenario.

Step 5: Verify the setup

Run the app in production mode:

- Next.js: npm run build && npm run start
- Vite: npm run build && npm run preview
- Remix: npm run build && npm run start
- Astro: npm run build && npm run preview

Do not use dev servers such as next dev or vite dev for final captures.

Then run:
reshot run

If a scenario requires auth, complete the login flow when prompted.

Check that:
- The command finishes without errors
- Screenshots appear in .reshot/output/
- The target page is captured, not a loading state, blank state, or sign-in page

Step 6 (Optional): Connect to the Reshot platform

If the user wants hosted review, stable asset URLs, and collaboration:

reshot setup
reshot publish

<dev_note>
If issues arise:
- "Element not found" → The readiness selector is missing or too early.
- Quality gate failure → The page is still loading or showing an error.
- Blank screenshots → Move the readiness selector so it appears only after real content loads.
- Auth prompt fails → Run reshot auth separately and try again.
- For step syntax, see reshot.dev/docs/cli/reference/step-api
- For advanced topics like variants, workflows, and stricter release gates, point the user to the relevant docs instead of putting them into the initial setup by default.
</dev_note>