# Self-updating screenshots for docs

> James Adam wired headless Chrome into Jelly's docs build so a single command refreshes every help-center screenshot from Markdown directives.

Published: 2026-04-10
URL: https://daniliants.com/insights/self-updating-screenshots/
Tags: documentation, screenshots, automation, capybara, cuprite, rails, headless-chrome, help-center

---

## Summary

James Adam built a documentation pipeline for Jelly where screenshots are captured automatically from the running app via headless Chrome, driven by directives embedded in Markdown comments. A single `rails manual:build` command refreshes every screenshot in the help center, eliminating the slow drift between UI changes and stale documentation images.

## Key Insight

- **Embed capture instructions in Markdown.** HTML comments like `<!-- SCREENSHOT: team/page | element | selector=#id -->` sit next to the image they produce, so the Markdown source is self-documenting and reviewable in PRs.
- **Three capture modes cover most needs:** `element` (single DOM node by CSS selector), `full_page` (whole page, optional crop), `viewport` (visible area only).
- **The `click` option unlocks state capture**, clicking a button to open a popover/form before screenshotting, with `wait=200` to let animations settle. Without this, hidden UI states are uncapturable.
- **Group by login session:** the Rake task groups directives by team so it only logs into each demo account once per build. Smart batching turns a slow operation into a tolerable one.
- **Cosmetic options matter:** `hide` (remove dev toolbars / cookie banners), `torn` (CSS clip-path edge effect), and crop coordinates remove the "screenshot looks rough" excuse.
- **Stack:** Capybara + Cuprite (CDP-based, faster than Selenium) driving headless Chrome, Redcarpet for Markdown to HTML, ERB views in Rails.
- **Real win is friction removal, not novelty.** Author admits the edge cases (scrolling elements into view, popovers, cropping) took longer than the happy path, but now docs get updated *more often* because the cost dropped to near zero.
- **Code and docs ship in the same PR.** Co-located source means docs can never silently lag the feature.