"Captures clean, demo-masked uzi web UI screenshots in BOTH light (Dawn) and dark (Ember) themes for the blog and README, fast and deterministically. Drives a logged-in Chrome over CDP - ensures demo mode on, flips instance branding to vanilla (built-in uzi mark, no powered-by) then restores it, forces each theme, leak-scans, and captures the app viewport at 2x with no browser chrome. shots.json is the manifest of every screenshot and where it lands. Use when capturing or refreshing uzi UI screenshots for the blog or README. Triggers include uzi screenshots, blog screenshots, readme screenshots, refresh the screenshots, screenshot the uzi UI, regenerate screenshots."
Resources
2Install
npx skillscat add vtmocanu/uzi/ui-screenshots Install via the SkillsCat registry.
ui-screenshots — capture uzi web UI screenshots (light + dark)
Regenerate publication-ready uzi UI screenshots in both themes, straight from a
logged-in Chrome over CDP. The engine captures the app viewport only (no browser
chrome, no crop) at deviceScaleFactor 2, so light and dark both come out crisp.shots.json is the single source of truth: every screenshot, how to capture it, and
whether it lands in the README, the blog, or both.
The instance URL is always an argument (or read from uzi auth status), never
hardcoded — this repo is public, so no instance host belongs in a script or commit.
Prerequisites
- macOS + Google Chrome at
/Applications/Google Chrome.app. - node on PATH (run.sh self-provisions
playwright-coreinto a cache dir~/.cache/uzi-ui-screenshots, kept out of the skill tree). uziCLI logged in (uzi auth status) — used only to resolve the instance URL.- Admin on the instance — the branding vanilla-flip uses
PUT /api/admin/settings. Without admin, pass--no-brandingand set branding by hand first.
Flow
launch-chrome.sh <url> # app-mode Chrome + CDP + persistent profile; log in ONCE
-> run.sh [--only …] [--repo …] [--run …] # stages <slug>-light.png / <slug>-dark.png, leak-scans
-> review every staged PNG (Read it): layout right, nothing sensitive leaked
-> publish-shots.mjs # copies reviewed pairs to README + blog dirs
-> swap-markup.mjs (first time only) # README <img> -> <picture>, blog html.dark swapLaunch + log in once:
<skill dir>/scripts/launch-chrome.sh "$(uzi auth status | awk '/^URL/{print $2}')"Log in in that window if the SSO page shows; the profile persists the session.
Capture (stages both themes, leak-scans):
<skill dir>/scripts/run.sh --stage /tmp/uzi-ui-shots --only dashboard,schedules,mobile-overview,mobile-runs,mobile-navOmit
--onlyto shoot everyautoshot plus anyrepo-board/run-detailwhose
id you pass. run.sh resolves the URL, ensures demo mode on, flips branding to
vanilla and restores it, and prints a leak-scan summary.Review — mandatory.
Readeach staged PNG. Confirm demo masking (no real
email, repo owner, or forge host), vanilla branding (uzi factory mark, no "powered
by"), correct theme, and clean layout. Any⚠from the leak scan must be resolved
before publishing.Publish the reviewed pairs:
node <skill dir>/scripts/publish-shots.mjs --manifest <skill dir>/shots.json --stage /tmp/uzi-ui-shots --only <slugs>--blog-dirdefaults to~/stuff/gitrepos/wxs/wxs/hai/static/images/uzi; README
dir is<repo>/.github/readme.--dry-runpreviews.
The manifest (shots.json)
Each row: slug, kind, route, viewport, themed, targets, and (for
non-auto) needs + state. Add a row and it flows to both consumers. kind:
- auto — deterministic route, captured with no extra input (dashboard, schedules, mobile-*).
- repo-board — needs
--repo <id>(/repos/<id>/board). - run-detail — needs
--run <id>and a live run in the right state; several also need scrolling to a panel or expanding a transcript (thearrangefield). These are operator judgment (see below). - terminal —
uzi tui, captured by hand; not a web shot, not theme-swapped.
Themes are light: dawn / dark: ember. denylist drives the leak scan (the
instance host is added automatically); extend per-run with --deny a,b,c.
Run-detail + board shots (operator judgment)
run-cost, run-judge, run-plan-gate, milestones, activity, andlead-transcript are panels/states of one run page, and board needs a repo. They
depend on live data: a plan gate needs a run parked at approval; the activity feed
and in-progress milestones need a run in flight. Pick a run that shows the panel
well, pass --run <id> (and --repo <id> for the board), and compare each new
shot against the current published image — keep the better one (a board with
several populated columns beats one with two). Because a theme switch reloads the
page, arrange the panel (scroll/expand) after the theme is applied, per theme.
Themes on the two consumers
- README (
.github/readme/):<picture>with aprefers-color-scheme: darksource and the light PNG as the<img>fallback. This is GitHub's theme signal. - Blog (
static/images/uzi/): the blog theme is a manual toggle (html.dark), notprefers-color-scheme, so swap with CSS keyed offhtml.dark(mirrors the existing archify diagram).swap-markup.mjssets this up once; after that, regens reuse the same filenames and need no markup change.
Known gap
Demo mode does not mask the run working-dir path (github.com+<owner>+<repo>+issue-N)
shown briefly in the recent-runs list before the summary streams in. The capture
settles 1.6s to avoid the flash and the leak scan catches it; a proper fix is to mask
that field in demo mode (uzi web).