BlogEngineering Practices

Documentation Screenshot CI: The Scenario Manifest Pattern

How to structure documentation screenshot automation around scenario manifests, CI artifacts, review states, and conservative publishing.

A CI job that takes screenshots is not a screenshot system.

It is a camera. Useful, fast, and very capable, but still a camera. The system begins when every screenshot has a scenario: the route, state, viewport, ready condition, capture target, output path, docs usage, and owner that explain why the image exists.

That scenario manifest is the pattern that turns documentation screenshots from ad hoc files into maintained artifacts.

Browser automation is already strong. Playwright can capture pages and locators. GitHub Actions can run workflows and store artifacts. shot-scraper shows how approachable CLI-driven screenshot capture can be. The missing layer is usually the manifest.

Why do CI screenshots become hard to trust?

Most teams start with a script: start the app, open a URL, wait a bit, take a screenshot, upload the PNG. That works until someone asks ordinary maintenance questions. Which docs page uses this image? Which account state was captured? Why is it full-page instead of cropped? Who approves replacement? What changed since the previous approved asset?

If the answer lives in a developer's memory, the screenshot is not maintainable. The manifest moves those answers into the repo.

The manifest defines the artifact

A scenario manifest should be boring and explicit. It does not need to describe every browser instruction. It needs to define the screenshot's contract.

YAML
id: settings-api-keys-one-active-key
docsPage: docs/api-keys/create.mdx
route: /settings/api-keys
fixture: team-workspace-one-active-key
viewport:
  width: 1440
  height: 900
theme: light
ready: '[data-docs-ready="api-keys"]'
target: '[data-docs-shot="api-keys-panel"]'
output: static/img/api-keys/create-key.png
owner: docs-platform
publish: review-required

The exact shape can be JSON, YAML, TypeScript, or another structured format. The important thing is that the manifest is the source of truth, not the screenshot file name and not a comment inside a Playwright test.

Where should implementation details live?

The manifest should not become a second programming language. Put policy and identity in the manifest. Put browser mechanics in the runner.

The runner can translate the manifest into Playwright calls: create or select the fixture, navigate to the route, set viewport and theme, wait for the ready signal, capture the target, and write the image plus metadata. This keeps scenarios readable to non-specialists. A docs lead can review whether the scenario represents the right page. An engineer can maintain the runner. A product marketer can see what assets are connected to a launch flow.

Should you trigger screenshots by dependency or by panic?

Screenshot sweeps happen when screenshots are disconnected from change. A manifest lets CI decide which screenshots are suspect, which is how teams stop doing screenshot sweeps before every launch.

Track scenario dependencies in the manifest or in a nearby index. A docs page dependency might point to docs/api-keys/create.mdx, a product dependency to app/settings/api-keys/**, a fixture dependency to fixtures/team-workspace-one-active-key.json, and a component dependency to the shared table or panel used in the screenshot. When one of those inputs changes, CI can run the related scenario. When unrelated code changes, the screenshot job can stay quiet.

GitHub Actions workflow syntax supports path-based triggers and job conditions, but many teams eventually add a small dependency resolver so they can map changed files to scenario IDs. The resolver does not need to be clever. It only needs to prevent "run every screenshot for every commit" from becoming the default.

Store the generated image and the decision record

A screenshot without metadata is hard to review. Once your docs screenshot is a build artifact, it carries provenance. Store the generated image beside a small decision record that includes the scenario ID, commit SHA, workflow run ID, docs page, product route, fixture, viewport, output path, previous approved asset, diff status, and review state.

GitHub Actions artifacts are useful for build-time storage. If the team wants longer-lived review, move the artifact into a review system or asset store after the CI run. Either way, do not force reviewers to reconstruct context from logs.

Why use review states instead of pass/fail only?

Documentation screenshot changes are not only pass or fail.

A changed screenshot may be correct because the product UI changed. An unchanged screenshot may still be wrong because the docs copy moved on. A failed capture may be a scenario problem, a fixture problem, or a real product bug.

Use review states that match documentation work: generated, unchanged, changed, approved, rejected, docs edit needed, and scenario fix needed. This language keeps the workflow honest without pretending every screenshot difference is a broken test. CI can tell you what happened. People decide what belongs in the docs.

Add a publishing rule per scenario

Not every screenshot needs the same level of caution. The manifest should include a publishing policy.

The default should be review required, especially for public setup flows, billing settings, security settings, and anything behind login. Internal test artifacts should never publish. Low-risk generated reference images can earn lighter rules later, but only after the team has enough history to know the scenario is stable.

How can failures improve the manifest?

The first screenshot CI failures are usually informative. A route needs seeded data. A ready signal is too vague. A capture target is unstable. A viewport does not match the docs layout. An animation or toast overlaps the target. Auth state expires. A feature flag differs from production.

Do not treat these as one-off CI annoyances. Each failure should improve the manifest or runner. Add the fixture. Tighten the ready condition. Capture the locator instead of the full page. Pin the theme. Add an owner.

This is how the screenshot system gets more reliable without pretending every product surface is deterministic on day one.

Use Reshot to keep the manifest and review together

Reshot is designed around this pattern: scenario manifests, generated capture artifacts, review decisions, and approved outputs.

You can keep Playwright as the browser runner. You can keep GitHub Actions as the CI layer. Reshot keeps the screenshot from becoming an anonymous PNG. The workflow is straightforward: define the scenario, run it when dependencies change, store the generated image with metadata, review changed artifacts with context, and publish approved assets to the docs path.

The scenario manifest is the handoff object. It gives Reshot enough context to show what changed, why it ran, who owns it, and whether it can replace the public docs image. That is how the manifest keeps visual debt from accumulating between releases.

Sources

Start with one screenshot workflow.

Run one real docs capture on the free tier and see whether the maintenance disappears.

Start for free