Meo is an internal record-and-replay testing platform:
- A Chrome extension records tester actions on the target site.
- The extension uploads actions as test cases to the backend.
- The backend replays those cases with Playwright on a schedule.
- A web console lets you inspect recorded steps and replay outcomes.
- Failures produce artifacts and alerts.
apps/server: Fastify API + Playwright replay engine + scheduler.apps/extension: Chrome MV3 extension (recorder + popup UI).apps/web: React web console for case/run monitoring.packages/shared: Shared protocol types between extension and server.docs/business-plan-meo.md: Business plan.docs/execution-freeze-v1.md: Locked product and engineering decisions.
- Node.js 20+
- npm 10+
- Install dependencies:
npm install
- Configure backend env:
cp apps/server/.env.example apps/server/.env
- Generate Prisma client and initialize database:
npm --workspace @meo/server run prisma:generate npm --workspace @meo/server run prisma:migrate
- Start backend:
npm run dev:server
- Start web console:
npm run dev:web
- Build extension:
npm run build:extension
- Load extension from
apps/extension/distin Chrome.
GET /api/cases: list cases with step/run summaryPOST /api/cases: create test caseGET /api/cases/:caseId: query case with recorded stepsPOST /api/cases/:caseId/actions: upload recorded actionsPOST /api/cases/:caseId/schedule: create scheduleGET /api/projects: list projectsGET /api/projects/:projectId: query project summaryPUT /api/projects/:projectId/login-credentials: upsert encrypted login credentialsGET /api/runs: list replay runsPOST /api/runs: trigger replay runGET /api/runs/:runId: query run result
All /api/* routes require:
Authorization: Bearer <MEO_BEARER_TOKEN>
Recorder input mapping is pluggable. Extension-side plugins decide whether an input value is stored inline or as inputValueRef.
- Default extension plugins:
apps/extension/src/input-mapping/plugins.ts - Default server resolver plugins:
apps/server/src/lib/mask.ts - Shared ref format helpers:
packages/shared/src/input-binding.ts
Default behavior:
generalmode (default): sensitive fields map tosecret:input.<sanitized_field_hint>loginmode: maps login aliases tosecret:login.username,secret:login.password,secret:login.otp- Non-sensitive fields keep inline values in both modes
Sensitive values are encrypted and stored at project scope in database (ProjectCredential), not in env.
Configure encryption key in apps/server/.env:
MEO_SECRET_ENCRYPTION_KEY=<64-char-hex>You can save project login credentials from:
- Web console: Case Detail -> Project Login Credentials panel
- API:
PUT /api/projects/:projectId/login-credentials
If a referenced value is missing, replay fails with INPUT_VALUE_MISSING:secret:<KEY>.
To extend behavior, add a plugin to pluginsForMode(...) in extension mapping or to defaultInputValueResolverPlugins on server.