Docs Automation Plan — Automated Refresh After Releases

Status: Phase 1 complete · Phase 2 screenshot coverage complete: 83 automated and 86 skipped Date: 2026-09-04 Owner: Docs / Frontend

Resuming work? Jump to Current state & next steps at the bottom — it lists exactly what is done, what is next, and the workflow for adding new screenshot entries.

Goal

After each saas-frontend release, automatically:

  1. Re-capture screenshots of the platform used in the docs.
  2. Detect stale content — factual claims in the docs (button names, column headers, menu labels) that no longer match the live UI.
  3. Keep image assets tidy — no broken references, no orphaned files.
  4. Deliver everything as a pull request for human review. Nothing is published automatically.

Non-goals (for now)

Why

Two manual audits (DOCS_AUDIT_2026-07-31.md, FAQ_AUDIT_2026-08-18.md) each took days of human effort and found ~30 stale screenshots, dozens of outdated statements, and orphaned images. This system runs that audit automatically after every release.

Architecture

flowchart LR
    A[saas-frontend release] -->|repository_dispatch| B[docs-refresh workflow]
    B --> C[Playwright capture run<br/>HAR replay — no live backend]
    C --> D[screenshot-manifest.json<br/>route + steps + selector per image]
    D --> E[pixelmatch diff vs<br/>committed PNGs]
    E -->|changed| F[Auto-commit new PNGs]
    B --> G[claims-check run<br/>assert UI text matches docs claims]
    G -->|drift| H[Drift report]
    B --> I2[reference hygiene<br/>broken refs + orphans]
    F & H & I2 --> I[PR to firetail-documentation<br/>human reviews & merges]

The core pattern: screenshots and factual claims stop being static assets and become build artifacts generated from manifests — the same approach this repo already uses for API specs, tags, findings and dynamic variables (scripts/*/download-*.js + build-*.js).

Phases

Phase 1 — Reference hygiene ✅ (implemented)

Static analysis, zero risk, pure win.

Phase 2 — Screenshot manifest + capture runner ✅ (complete)

Make every doc screenshot reproducible from a recipe.

Implemented (pilot, 2026-08-21):

Scaled out — workforce section complete (2026-08-21):

Workload screenshots (2026-09-02):

Dashboard screenshots (2026-09-02):

Alerts, FAQ download and integrations catalogue screenshots (2026-09-04):

Current screenshot inventory (2026-09-04):

Lessons learned in the pilot:

Projects and organizations screenshots (2026-09-04):

Getting-started and posture-management screenshots (2026-09-04):

Integration forms and suggested checks (2026-09-04):

Remaining: add the docs-refresh workflow — see Current state & next steps.

Phase 3 — Claims manifests (stale-content detection)

Turn fragile factual claims in the docs into machine-checkable assertions.

Phase 4 — Expand generated content

Anything that is a list of facts should be rendered by Eleventy from downloaded data, like findings/specs/tags already are. Candidates from the audits:

Once generated, this content can never go stale.

Trigger & delivery

What stays manual

The system detects all three (manifest coverage vs. app routes, failing claims, orphaned images) and surfaces them in the PR report.

Future: LLM slot

When/if an LLM is added, it slots between drift report → PR: given the precise, grounded drift findings, it drafts the prose updates for human review. All the manifest/diff infrastructure built here is exactly the grounding it needs — nothing is throwaway.

Rollout estimate

Phase Effort Status
1 — Reference hygiene days ✅ Implemented
2 — Screenshot capture via HAR replay (~170 PNGs, staged) 1–2 weeks ✅ Complete; 83 automated, 86 skipped; triage complete
3 — Claims manifests (high-churn pages first) 1 week after P2 Planned
4 — Generated content ongoing Planned

Non-technical summary

flowchart TB
    A["🚀 New product release goes live"] --> B["🤖 Docs Checker starts automatically"]
    B --> C["📸 Re-takes every screenshot<br/>by clicking through the product,<br/>exactly like a user would"]
    B --> D["🔍 Reads the docs and checks<br/>every fact against the product<br/>(button names, menus, columns...)"]
    B --> E["🧹 Tidy-up check:<br/>finds broken or unused images"]
    C --> F{"Did anything change?"}
    D --> F
    E --> F
    F -- "No" --> G["✅ Docs are up to date.<br/>Nothing to do."]
    F -- "Yes" --> H["📦 Prepares an update package:<br/>• fresh screenshots<br/>• list of outdated sentences<br/>• list of images to remove"]
    H --> I["🧑‍💻 A person reviews the package<br/>and approves with one click"]
    I --> J["📚 Documentation website<br/>is updated"]

Current state & next steps

Everything needed to resume this work in a fresh session.

Repos & key files

What Where
This plan firetail-documentation/internal-reports/DOCS_AUTOMATION_PLAN.md
Screenshot manifest (docs-owned) firetail-documentation/screenshots/manifest.json (+ manifest.schema.json)
Complete image inventory firetail-documentation/screenshots/image-inventory.json (+ image-inventory.schema.json)
Capture runner saas-frontend/e2e/docs-screenshots/capture.spec.ts (+ own playwright.config.ts)
HAR fixtures (app-owned, sanitized) saas-frontend/e2e/docs-screenshots/fixtures/<entry-id>.har
HAR replay helper (shared with e2e) saas-frontend/e2e/utils/harReplay.ts
HAR sanitizer saas-frontend/e2e/scripts/sanitize-har.mjs [harDir] (credentials) + beautify-docs-fixtures.mjs [harDir] (PII); both run by npm run docs:screenshots:sanitize
Capture report (PR-body input) saas-frontend/e2e/docs-screenshots/capture-report.md
Image hygiene check (Phase 1) firetail-documentation/scripts/images/check-image-refs.js (yarn check:images)

Environment prerequisites (record mode only)

Workflow: adding a new screenshot entry

  1. Find the doc image and its context: which page/state does it show? (grep -rn "<image>.png" firetail-documentation/docs/)
  2. Explore the live UI with playwright-cli -s=firetail-sandbox-authenticated-session (or npm run e2e:auth) to find the route, step selectors (role/name), and the dialog's accessible name.
  3. Add an entry to screenshots/manifest.json. Prefer deep routes over tab clicking; use within to scope steps inside drawers; pick capture.target: viewport (full page), role (a dialog only), or clip (rectangle).
  4. Record: npm run docs:screenshots:record (records HAR + captures + sanitizes). To re-record a single entry: UPDATE_HAR=1 npx playwright test --config=e2e/docs-screenshots/playwright.config.ts -g "<entry-id>" && npm run docs:screenshots:sanitize A record run never writes the PNG — it only proves the recipe resolves and produces the fixture.
  5. Verify: run npm run docs:screenshots twice — everything must pass and all PNG hashes must be identical (shasum docs/**/images/*.png). If a change only affects text, delete the output PNG first — the diff threshold treats it as unchanged.
  6. Visually review the changed PNGs on the rendered docs page (yarn dev in the docs repo) — data, framing, crop.
  7. Check the HAR has no unfinished entries: node -e "console.log(JSON.parse(require('fs').readFileSync('e2e/docs-screenshots/fixtures/<id>.har','utf8')).log.entries.filter(e=>e.response.status<0).length)" (should print 0).

Image inventory workflow

Done so far (2026-09-04)

Next steps (in order)

  1. Docs-refresh GitHub Actions workflow (lives in saas-frontend — it has the runner, fixtures and app build; triggered by release + nightly cron): checkout both repos → build/serve frontend → npm run docs:screenshots (replay) → if PNGs changed, open a PR against firetail-documentation with the changed images + capture-report.md as the PR body. Never auto-merge.
  2. Phase 3 — claims manifests (see section above); reuse the same runner infra and HAR fixtures.
  3. Phase 4 — move fact-lists into the Eleventy generated-content pipeline.

Branch/PR state (as of 2026-09-04)