A production-grade Playwright test automation framework — and the mentor that teaches you to use it.
PlaySensei is two things in one repo:
- A real Playwright + TypeScript framework — Page Object Model, fixtures, multi-browser config, the kind of setup you'd actually find in a test suite at work.
- An adaptive learning platform built on top of it — structured lessons, a CLI, and a full web app (PlaySensei Studio) where you write real code, run it against a real app, and ask an AI mentor about any Playwright topic, answered live from the official docs.
No paid API keys required anywhere. The AI mentor runs on a local, open-source LLM via Ollama.
Most testing frameworks assume you already know how to test. Most tutorials don't leave you with a real framework once you're done learning. PlaySensei is built so the thing you practice on is the thing you'd actually use — the same Page Object Model, fixtures, and Playwright config that power the example test suite are what the lessons teach you to write.
- 5 hands-on beginner lessons (
packages/curriculum) — each ships with a starter file containing a real, specific bug (a typo, a missinghover(), a strict-mode violation) and a solution used only for automated verification. Fix it, don't rewrite it. - PlaySensei Studio (
packages/studio) — a local web app with a resizable workspace: lesson/topic sidebar, docs on the left, editor + console on the right. Run your code and see real Playwright output, with a screenshot attached automatically on failure — no tab-switching to see what happened. - Real Monaco, self-hosted — a genuine code editor with working Playwright autocomplete (
page.,expect(...).etc.), not a syntax-highlighted textarea, and not fetched from a CDN. - Test mode or Script mode, JS or TS — write a real Playwright test (
test()/expect) or a standalone script that driveschromium.launch()itself (the shape Playwright's own codegen produces) — a toggle switches how "Run" executes your code, and another switches the starter template between JavaScript and TypeScript. - Ask anything — type any Playwright topic and get an answer synthesized by a local LLM from documentation fetched live from playwright.dev (not the model's stale training data, and not a hardcoded topic list).
- Focus mode & pop-out — collapse the sidebar/docs to just code + console for more room, or open the whole playground in its own browser tab, same state, one click.
- An AI mentor (
packages/mentor-ai) — explains why a test failed in plain language, behind a pluggableLLMProviderinterface so Ollama can be swapped for any other open-weights endpoint. - A
learnCLI for anyone who'd rather stay in the terminal.
Studio only ever drives Chromium (see packages/curriculum/playwright*.config.ts) — it never needs Firefox or WebKit, so you can skip downloading them entirely:
git clone <this-repo-url>
cd PlaySensei
npm run setup # = npm install && npx playwright install chromium
npm run studioOpen http://localhost:5173. That's it — 3 commands, one browser download (~150 MB, not ~450 MB for all three). No Ollama, no .env files, nothing else required; the AI mentor just falls back to raw doc excerpts/output until you set that up (see below).
- Node.js 20+ (the repo pins
20in.nvmrc— if you use nvm,nvm install && nvm usegets you the right version) - git
- Ollama — optional, only needed for AI-synthesized answers/explanations (see below); everything else works without it
The full setup additionally downloads Firefox and WebKit, needed only by npm test (the example framework suite, which runs cross-browser):
git clone <this-repo-url>
cd PlaySensei
nvm use # or just make sure `node -v` is >= 20
npm run setup:full # = npm install && npx playwright install (all 3 browsers)npm install is run once at the repo root — npm workspaces hoist and link packages/framework, packages/curriculum, packages/mentor-ai, and packages/studio together, so you never cd into a package and npm install separately.
npm run typecheck # every package, no emitted files — should exit clean
npm test # runs the example framework suite against a live TodoMVC appIf both pass, everything is wired up correctly.
npm run learn -- list # see all lessons and your progress
npm run learn -- next # what to work on next
npm run learn -- run 01-first-test
npm run learn -- status # your level at a glancenpm run studioOpen http://localhost:5173 — this starts the Vite dev server (frontend) and the Express API together (concurrently, see packages/studio/package.json). Stop with Ctrl+C.
Everything above works with zero setup — without an LLM, the mentor gracefully falls back to raw doc excerpts or raw Playwright output instead of failing. To get real AI-synthesized answers and failure explanations:
# install Ollama: https://ollama.com/download
ollama pull llama3.1 # or any model you prefer
ollama serveStudio and the CLI both auto-detect Ollama at http://localhost:11434. Copy packages/studio/.env.example to packages/studio/.env (and/or packages/mentor-ai/.env.example → .env) to point at a different model or a self-hosted OpenAI-compatible endpoint instead — nothing else in the codebase needs to change, since every AI call goes through the pluggable LLMProvider interface (packages/mentor-ai/src/providers/).
Docs and a console-style results panel next to a full-width editor — resizable, focusable (collapse the sidebar/docs to just code + console), and poppable into its own browser tab. Run a test and watch it fail or pass for real: the panel above is parsed straight from Playwright's own list-reporter output, with a screenshot attached automatically on failure, and the explanation underneath the failing line is the AI mentor reading that same output, not a canned message.
packages/
framework/ Playwright + TypeScript example suite — POM, fixtures, multi-browser config
curriculum/ Lessons (doc + starter + solution), progress tracking, the `learn` CLI
mentor-ai/ LLMProvider interface, Ollama implementation, live Playwright-docs
lookup (sitemap → fetch → extract → LLM), failure explainer
studio/ React + Vite frontend, Express API — the web app tying it all together
Each package is independently type-checked (npm run typecheck) and has its own package.json. framework and curriculum are independent — both target the same demo app but don't depend on each other. studio's server imports @playsensei/curriculum's core module directly (lesson loading, progress tracking, running tests) and @playsensei/mentor-ai's capabilities, so the web app and the CLI share one implementation instead of two.
packages/curriculum/lessons/<id>/starter.spec.ts— real Playwright code with one intentional bug.- You fix it (via the CLI + your own editor, or directly in Studio).
npm run learn -- run <id>(or Studio's Run button) executes it against the real target app (demo.playwright.dev/todomvc) with Playwright itself — no simulation.- Pass → progress recorded in
.playsensei/progress.json(local, gitignored). Fail → the raw Playwright output, or — if Ollama is running — a plain-language explanation of what went wrong and how to fix it. solution.spec.tsis never shown to the learner; it exists purely sonpm run learn -- verifycan confirm the curriculum itself isn't broken.
PlaySensei Studio is built to be self-hosted on a machine you control (your own server, a VM, a Raspberry Pi, whatever) rather than dropped onto a stateless serverless/static host. Two reasons:
- It spawns real processes. Running a test or script shells out to
npx playwright test/npx tsxon the host — that needs a persistent Node process with the Playwright browsers installed, not a stateless function. - It has local state. Lesson progress and your playground scratch files live on disk (
.playsensei/progress.json,packages/curriculum/playground/), and the optional AI mentor talks to Ollama overlocalhost. There's no database and no multi-tenant isolation — it's built for one person (or a trusted team sharing one instance), not the public internet.
With that in mind, here's the real, verified path — npm run build followed by npm run start runs one Express process serving both the API and the built frontend on a single port, which was tested end-to-end while writing this doc:
npm install
npx playwright install --with-deps # --with-deps also installs OS-level browser libraries, useful on a bare server
npm run build # tsc project check + `vite build` → packages/studio/dist/PORT=3001 npm run start # one process, serves the built frontend AND the APIpackages/studio/server/index.ts serves packages/studio/dist/ as static assets and falls back to index.html for any non-/api, non-/screenshots route (so a hard refresh on a deep link like /?focus=1&mode=playground still works), so there's nothing else to stand up — no separate static file host, no build step at request time.
Set env vars either by exporting them or via packages/studio/.env (loaded automatically):
| Variable | Default | Purpose |
|---|---|---|
PORT |
3001 |
Port the single Express process listens on |
OLLAMA_BASE_URL |
http://localhost:11434 |
Where to reach Ollama, if you want AI answers/explanations |
OLLAMA_MODEL |
llama3.1 |
Which pulled model to use |
npm run start is a foreground process — for a real deployment, put it under a process manager so it restarts on crash/reboot. With pm2:
pm2 start "npm run start" --name playsensei --cwd /path/to/PlaySensei
pm2 saveOr a systemd unit (/etc/systemd/system/playsensei.service):
[Unit]
Description=PlaySensei Studio
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/PlaySensei
ExecStart=/usr/bin/npm run start
Environment=PORT=3001
Restart=on-failure
User=playsensei
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now playsenseiReverse-proxy port 3001 with nginx or Caddy if you want a real domain and HTTPS. Caddy's whole config is one line:
playsensei.example.com {
reverse_proxy localhost:3001
}
Install Ollama on the same host (or point OLLAMA_BASE_URL at another machine on your network) and ollama pull <model> before starting the service — same setup as local dev, just running unattended. Without it, Studio still works; the mentor just falls back to raw doc excerpts and raw Playwright output instead of AI-synthesized answers.
| Piece | Choice |
|---|---|
| Test engine | Playwright + TypeScript (strict) |
| Monorepo | npm workspaces |
| Studio frontend | React + Vite + self-hosted Monaco Editor, react-resizable-panels, lucide-react |
| Studio backend | Express (dev: proxied behind Vite; production: serves the build + API on one port) |
| AI | Ollama (local, zero-cost) behind a swappable LLMProvider interface |
| Docs retrieval | Live fetch from playwright.dev's sitemap — no hardcoded topic list |
Built: the framework, the full curriculum + CLI, the AI mentor (failure explainer + live topic lookup), and PlaySensei Studio, including a real production build/start path.
Not yet built: ReportPortal reporting integration, GitHub Actions CI workflows, and a persisted/scheduled knowledge-base ingestion pipeline (mentor-ai currently fetches docs live per request rather than maintaining an ingested vector store). If you're picking this up, those are the natural next phases.
MIT

