Screenshot the dashboard SPA

SkillWeb & browsing

Capture desktop + mobile, dark + light screenshots of the kube-coder dashboard SPA for visual QA of a UI change. Use when the user wants to see a frontend change rendered in a real browser rather than just unit-tested.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Screenshot the dashboard SPA skill

What this skill tells your AI

The instructions your AI receives, as published by imran31415/kube-coder in .claude/skills/kc-screenshot/SKILL.md and read by ahel’s review.

Drives a headless Chromium across desktop (1280x800) and mobile (390x844) viewports in dark + light themes, against a local dev harness that stubs auth. Useful for changes that can't be fully unit-tested (terminal iframe, layout, theming). Read the resulting PNGs with the Read tool — they render inline.

How it works

  • charts/workspace/web/dev_server.py <port> — a thin harness that imports the real charts/workspace/server.py and monkeypatches check_claude_auth to always return True, so the SPA can hit /api/* without the OAuth proxy. The production dashboard on 6080 is untouched.
  • charts/workspace/web/scripts/shoot.mjs — drives Chromium via playwright-core and writes phaseN-<view>-<viewport>-<theme>.png files. Sibling variants exist for specific surfaces: shoot-hv.mjs (hypervisor), shoot-msgchat.mjs, shoot-docs.mjs, shoot-toolbar-paste.mjs.

Steps

1. Build the SPA (the dev server serves dist/)

yarn --cwd charts/workspace/web build

Rebuild after any source edit — the dev server picks up the new dist/ on the next request, no restart needed.

2. Start the dev server on port 7070

cd /home/dev/kube-coder
nohup python3 charts/workspace/web/dev_server.py 7070 > /tmp/dev_server.log 2>&1 &
disown
sleep 2
curl -sf http://localhost:7070/ >/dev/null && echo "dev server up" || tail -20 /tmp/dev_server.log

3. Ensure a Chromium binary is installed

The shoot scripts auto-discover the Playwright Chromium via scripts/chromium-path.mjs (checks $KC_CHROMIUM, then the highest-revision chromium-<rev> under any ms-playwright cache root), so you don't hardcode or symlink anything. Just make sure one is installed:

ls -d ~/.cache/ms-playwright/chromium-*/chrome-linux*/chrome 2>/dev/null \
  || yarn --cwd charts/workspace/web exec playwright install chromium

If it lives somewhere unusual, point the scripts at it explicitly with KC_CHROMIUM=/path/to/chrome.

4. Run the shoot script

OUT="${ARGUMENTS:-/home/dev/screenshots}"
cd /home/dev/kube-coder/charts/workspace/web   # must run where node_modules is
node scripts/shoot.mjs "$OUT"
ls -t "$OUT"/*.png | head

Then Read a couple of the output PNGs to visually confirm the change.

Gotchas

  • Onboarding modal — a first-run .ob-scrim overlay covers the page and eats clicks. The shoot scripts suppress it with addInitScript(() => localStorage.setItem('kc.onboardingDone','true')). If you script a capture by hand, do the same.
  • Theme forcing — Chromium ignores prefers-color-scheme here; the scripts set data-theme="dark" on <html> after navigation so the tokens.css dark rules apply. Don't rely on the OS media query.
  • Routes 404 in-browser but 200 via curl — usually dev_server.py's auth monkeypatch went stale against a server.py signature change. Check /tmp/dev_server.log for a TypeError in check_claude_auth; the stubs should swallow *args, **kwargs.

Cleanup

pkill -f "dev_server.py 7070" 2>/dev/null || true

Signals

GitHub stars
354
Forks
32
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
kc-screenshot
Source
github.com/imran31415/kube-coder