| name | browser-auth |
| description | Drives an authenticated browser session on synthex.social (or localhost) WITHOUT the flaky Chrome extension. The reliable path is a committed Playwright script (scripts/browser/dashboard-audit.mjs) that logs in with the SYNTHEX_TEST_EMAIL / SYNTHEX_TEST_PASSWORD test account and audits every integration surface. Use whenever asked to "log in", "authenticate", "audit the dashboard", "check what's connected", or before browser-verify / site-smoke-test on /dashboard/* routes. |
| metadata | {"author":"synthex","version":"2.0","type":"action-skill","triggers":["log in to browser","authenticate","sign in","browser session","audit the dashboard","check what's connected","dashboard audit","authentication required"]} |
| context | fork |
Browser Auth — the reliable, extension-free path
FIRST: are you trying to check "what's connected"? Don't log in.
The dashboard is gated to Google-SSO CEO accounts (OWNER_EMAILS) — there is no
email/password test account, so the Playwright login below cannot sign in as a real
owner, and Claude can't drive a Google SSO flow. To answer "is X connected / why is the
dashboard empty / are tokens expired", use the [[token-health]] skill — it reads the
live connection state straight from the DB (authorised, read-only; see memory
prod-connection-health-read-authorised). That's the reliable path and needs no browser.
Only use the browser login below for verifying rendered UI on /dashboard/*, and only
once a dedicated email/password test account exists (see One-time setup).
Why this skill exists (read once)
Synthex has two ways to drive a browser. They are NOT equal:
| Path | Needs | Reliability |
|---|
Playwright script (scripts/browser/dashboard-audit.mjs) | node + installed Playwright + test creds | ✅ Deterministic. No bridge, no extension, no human clicks. Use this. |
Chrome extension / computer_use (mcp__Claude_in_Chrome__*) | a per-session sign-in + tab toggle that drops | ⚠️ Flaky. The cause of recurring "browser broke again". Fallback only. |
computer_use and the Chrome extension are the same bridge — if list_connected_browsers is empty or tabs_context_mcp says "not connected", computer will fail identically. Do not burn time toggling it. Reach for the script.
One-time setup (eliminates the recurring friction)
The script needs a dedicated test account (never a real customer login, never Phill's personal account). Put its creds in .env.local (plaintext, gitignored):
SYNTHEX_TEST_EMAIL=test@… # a Synthex test account Phill creates
SYNTHEX_TEST_PASSWORD=… # stored in .env.local only
Claude cannot create the account or type the password (prohibited actions). This is the single human step — once done, every future dashboard audit is fully autonomous. If the creds are missing the script exits 2 with a clear message; surface that to Phill and stop.
Run it
The test creds live in Vercel (Production), not locally — pull them into a
gitignored .env.local first, then run with Node's built-in --env-file
(Node 20+, no extra deps — do NOT use npx dotenvx, the unscoped package 404s):
npx vercel env pull .env.local --environment=production --yes
node --env-file=.env.local scripts/browser/dashboard-audit.mjs [baseUrl]
PWDEBUG_HEADED=1 node --env-file=.env.local scripts/browser/dashboard-audit.mjs
The creds must be set on the Production Vercel environment (that's where
vercel env pull --environment=production reads them). support@…-style
mailboxes created via "Continue with Google" have NO email/password and will
fail with "Invalid login credentials" — use an account with a real password.
Output: a JSON report on stdout + full-page screenshots in .artifacts/browser-audit/. Each surface is classified connected / notConnected / empty / error from its visible text. Read the JSON, open the screenshots, and report exactly which integrations are live vs broken.
Exit codes: 0 ok · 2 missing creds · 3 login failed (see login-failed.png) · 4 runtime/launch error.
Login contract (verified 2026-05-30)
- Login page:
<base>/login — form renders client-side, so wait for the selector, not networkidle (the dashboard holds connections open and never goes idle).
- Selectors: email
#email, password #password, submit button:has-text("Sign in") (there are two submit buttons — "Watch Tutorial" and "Sign in").
- Success: URL moves to
/dashboard (existing user) or /onboarding (new user). A Supabase sb-* session cookie is set.
- Auth errors surface as Sonner toasts (
[data-sonner-toast]), not [role="alert"].
Maintenance (keep this skill true)
This skill drifts in exactly two places. When the dashboard changes, update them and re-verify — don't let it rot:
- Login selectors (
SEL in the script). If login starts failing with exit 3, re-probe:
node -e "import('playwright').then(async({chromium})=>{const b=await chromium.launch();const p=await b.newPage();await p.goto('https://synthex.social/login',{waitUntil:'domcontentloaded'});await p.waitForSelector('input');console.log(await p.evaluate(()=>[...document.querySelectorAll('input,button')].map(e=>({tag:e.tagName,type:e.type,id:e.id,text:(e.textContent||'').trim().slice(0,30)}))));await b.close();})"
Update SEL.email / SEL.password / SEL.submit to match.
- Audit routes (
ROUTES in the script). Add/rename as /dashboard/* surfaces change (find app/dashboard -maxdepth 1 -type d).
- After any edit, re-verify the no-creds gate (
node scripts/browser/dashboard-audit.mjs → must print MISSING_CREDS and exit 2), and run the full audit once with creds.
Bump the version and the "verified" date above whenever you touch the selectors.
Security rules
- Never log or print password values.
- Never use Phill's personal credentials — dedicated test account only.
- Never create a Supabase account (prohibited — Phill does this).
- Screenshots may contain client data — they live in
.artifacts/ (gitignored); never commit them.
- List session-cookie names only, never values.