docs/assets/screenshots/ are captured from a real, running control plane. They show real deployed containers, real metrics, and real log lines, with no mocking or hand-editing.
Screenshots are produced by scripts/screenshots/capture.sh, a manual maintainer tool (not a CI job). Deploying real containers and accumulating metrics takes a couple of minutes, too slow for every PR. Re-run it by hand whenever the dashboard changes significantly and existing screenshots look stale.
Prerequisites
Prerequisites
- Docker, running locally (
docker infoshould succeed) - Go and Node.js/npm (to build the control plane, CLI, and frontend)
- Python 3 with Playwright installed, and shot-scraper:
Running it
Full pipeline details
Full pipeline details
- Build fresh binaries into a scratch directory
- Start a control plane against a separate scratch data directory
- Deploy two real apps from public images, plus a real managed Postgres database
- Trigger real redeploys to build deploy history
- Send real HTTP traffic to the apps
- Set an example secret, a domain, and a load balancer so the environment, domains, and load balancer pages aren’t empty
- Wait about 75 seconds for metrics to accumulate at 15-second resolution
- Log in through the real
/loginform - Capture screenshots with
shot-scraper
KEEP_SCRATCH=1 to leave the scratch directory (binaries, data dir, server log, session state) in place after a run, useful for debugging a failed capture.Why not dev-mode's fixed tokens?
Why not dev-mode's fixed tokens?
The control plane binary builds with
-tags embedweb to serve the real built frontend (same as a user would run). This also compiles out the APP_DEV_MODE bypass, so dev-mode’s fixed tokens aren’t available.Instead, the script:- Bootstraps a real admin account using
APP_ADMIN_USERNAME/APP_ADMIN_PASSWORD - Logs into the browser through the actual login form
- Authenticates the CLI using the real device-login flow (
levelrail-cli auth login --device) - Approves the login through the browser
Files
scripts/screenshots/shots.yml: theshot-scraper multiconfig, one entry per PNG.scripts/screenshots/login_state.py: logs into a running control plane through the real login form and saves the session as a Playwright storage state file, reused across every shot.scripts/screenshots/capture.sh: orchestrates the whole pipeline.
Screens that need more than one node
Some screens do not exist on a single node: the multi-node topology view, cross-node ingress routing, a second node’s own health.capture.sh does not cover them. Capture these by hand from a real multi-node cluster you control, with a logged-in browser session, and save the PNGs to docs/assets/screenshots/ with a multi-node- prefix so their source is obvious. Embed them in Multi-node or Network topology.
If you lose access to the admin account on a cluster you own, sudo APP_DATA_DIR=<data dir> levelrail recover-admin resets or creates the first admin directly against the local database (add -username and -password to pin either, otherwise both are generated). It changes a live credential, so rotate or remove it once you are done.
See also
- Getting started for building and running the control plane locally
- Identity and access for device login flow details
- Feature catalog to understand which dashboard pages are captured