UI Visual Debugging
Core Rules
- Use a browser-controlled or headless context for routine web UI checks. Do not open tabs in the user's existing browser unless explicitly asked.
- Save screenshots, traces, and throwaway Playwright scripts under
.context/; do not commit them. - Use Peekaboo only when the task needs the real macOS desktop, native windows, a visible browser session, or Accessibility tree inspection.
- For local startup details, use
running-and-testing-locallyas the source of truth.
Nango Targets
| Surface | URL | Common command |
|---|---|---|
| Dashboard webapp | http://localhost:3000 |
npm run dev:watch:web |
| API server | http://localhost:3003 |
npm run server:dev:watch |
| Connect UI | http://localhost:3009 |
npm run dev:watch:web or npm run connect-ui:dev:watch |
For most frontend work, run:
npm run dev:docker
npm run dev:watch
npm run dev:watch:webnpm run dev:watch and npm run dev:watch:web are long-running commands. Keep them in separate sessions and wait for the initial TypeScript build before browser testing.
Standard Screenshot Workflow
Start or reuse the relevant local services.
Capture a desktop baseline with a browser-controlled tool. If a Playwright MCP/browser tool is available, use it. Otherwise use headless Playwright without modifying repo dependencies:
npx playwright screenshot --browser=chromium --viewport-size=1512,862 http://localhost:3000 .context/nango-webapp-desktop.pngFor Connect UI:
npx playwright screenshot --browser=chromium --viewport-size=1512,862 http://localhost:3009 .context/nango-connect-desktop.pngIf Playwright reports that the Chromium executable is missing, install the browser cache without adding repo dependencies:
npx playwright install chromiumInspect screenshots with
view_image, then edit the smallest relevant files.Verify after edits:
npm run ts-buildFor webapp-only visual work,
cd packages/webapp && npm run buildis also useful. For Connect UI, runnpm run connect-ui:build.Capture fresh desktop screenshots and compare them before finishing.
Headless Interaction
For clicks, form filling, authentication flows, or multi-step checks, create a temporary Playwright script in .context/, run it, and save screenshots there.
Use stable selectors and visible text where possible. Avoid relying on the user's browser state.
Common flows:
- Dashboard sign-in/sign-up at
http://localhost:3000. - Dashboard pages after authentication: Integrations, Connections, Logs, Metrics, and Environment settings.
- Connect UI at
http://localhost:3009.
When auth is needed, follow the local credentials and verification-log workflow in running-and-testing-locally.
Startup Troubleshooting
If server startup fails with a Knex error like The migration directory is corrupt, the following files are missing, the local database has migrations from another branch (see Migration mismatch in running-and-testing-locally to tell a branch behind master from an unmerged one). Do not reset the user's database without confirmation. For visual validation only, use a temporary database:
docker exec nango-db psql -U nango -d postgres -c "DROP DATABASE IF EXISTS nango_ui_skill_validation WITH (FORCE)"
docker exec nango-db psql -U nango -d postgres -c "CREATE DATABASE nango_ui_skill_validation"
NANGO_DB_NAME=nango_ui_skill_validation npm run dev:watch:webAfter stopping the dev server, clean up the temporary database:
docker exec nango-db psql -U nango -d postgres -c "DROP DATABASE IF EXISTS nango_ui_skill_validation WITH (FORCE)"Peekaboo Workflow
Use Peekaboo only after checking permissions:
peekaboo permissions statusRequired:
Screen Recording (Required): Granted
Accessibility (Required): GrantedPrefer targeted captures by window id. Capturing by app name can hang.
peekaboo list windows --app "Google Chrome" --json
peekaboo image --mode window --window-id <window_id> --retina --path .context/nango-window.png --json-output
peekaboo see --app "Google Chrome" --json-outputAvoid peekaboo open http://... --app "Google Chrome" for routine checks because it creates tabs in the user's existing browser.
Review Checklist
- Baseline screenshot captured before UI edits when layout risk is meaningful.
- Desktop screenshots captured after edits.
- Screenshots, traces, and throwaway scripts stay under
.context/. - Browser automation does not depend on the user's existing browser state.
-
npm run ts-buildor the relevant package build was run after frontend changes.