Playwright smoke tests. These exist because curl proves the server responds but
cannot see client-side failures — a broken frontend can sit behind a stack where
every endpoint returns 200.
cd e2e
npm install # first time only
node smoke.mjs # loads /, /auth/signup, /auth/login; reports console errors + HTTP >=400
node peek.mjs # screenshot + dump page text. Use this FIRST when something looks broken.
node routes.mjs # enumerates real admin nav routes (needs an account)
node theme.mjs <tag> # screenshots light+dark and samples the live colour tokens
node devshot.mjs <tag> [url] # same, against `next dev` (default :3010)
node landing.mjs [url] # /app/home: card list + both click targets, against `next dev`
node flow.mjs # ⚠️ REGISTERS AN ACCOUNT. First account becomes admin.Credentials in .env.local (gitignored). Screenshots land in shots/.
These all target http://localhost:3003, resolved once in base.mjs. If the
stack was brought up on another port, pass the same ATHENA_PORT you gave
Compose — or BASE_URL for a host that isn't localhost:
ATHENA_PORT=3007 node smoke.mjs
BASE_URL=http://box.local:3007 node smoke.mjsdevshot.mjs and landing.mjs are the exception: they point at the next dev
server on :3010 and take the URL as an argument.
404 /api/enterprise-settings→ the frontend hard-depends on this route. Without it every page renders "problem loading your Onyx settings."- 502 +
text/htmlon/api/*→ nginx holds a stale upstream IP. Restart nginx. - 403 on
/api/me,/api/settings,/api/notificationswhile logged out → normal, ignore.
Check the actual rendered page with peek.mjs before reporting a regression.
Three "outages" during the enterprise-code removal were all bad diagnostics —
a grep matching a "Create an Account" link, and a selector assuming
input[type="email"] when the login inputs aren't that type.