SulayIO is an open-source platform for verifying how websites behave across screen sizes and auditing their quality. It drives real browsers with Playwright to capture screenshots, detect UI issues, score audits, and present everything in a dashboard — so you stop manually opening dev tools and switching viewports.
Enter URL → Configure pages & viewports → Run → Screenshots + validations + scores → Dashboard
⚠️ SulayIO can log in to target sites and store credentials. Use dedicated demo accounts only — never store production passwords.
- Responsive testing — screenshot each page × viewport (e.g. Home × Mobile/Tablet/Desktop) and validate horizontal overflow, broken images, console errors, and failed requests.
- Authentication — public pages or login-form auth; the worker logs in before visiting protected routes.
- Saved credentials — store reusable private-page logins encrypted at rest (AES-256-GCM) under Settings → Private Pages, then reuse them across audit and responsiveness runs.
- Audits (each its own module/endpoint/analyzer on its own queue):
- Audits: performance, network, JS & page errors, accessibility (axe-core), SEO, broken images, forms, security.
- Visual: click heatmap, visual regression (pixel-diff vs. baseline).
- Tools: route discovery, broken links, redirect tracer, tech-stack detection, cookie scanner, header inspector.
- Audit scoring — every graded audit gets a configurable 0–100 score
shown in the tables. Weights/thresholds live in a seeded
ScoringConfigcollection, editable viaGET/PUT /scoring(admin). Tools are diagnostic and intentionally not scored. - Dashboard — area/donut/bar charts for activity, run status, audit-score distribution, and audits-by-type.
- Projects & tags — group runs under a color-coded project (sidebar switcher); tag any run and filter lists by tags + URL search.
- Settings — manage projects, private-page credentials, and change your password.
- i18n & theming — English / Filipino, light/dark toggle, green brand accent.
client (React + Vite)
│
▼
core-service (Express API)
│
▼
BullMQ ──▶ Redis
│
▼
worker (Playwright)
│
├──────────────┐
▼ ▼
MongoDB storage/screenshots
| Layer | Tech |
|---|---|
| Frontend | React + Vite, TypeScript, Mantine + Tailwind, Zustand, React Query, React Router, i18next |
| Charts | @mantine/charts (Recharts) |
| API | Express.js + TypeScript |
| Queue | BullMQ (Redis) |
| Browser automation | Playwright |
| Database | MongoDB |
| Storage | Local filesystem |
apps/core-service Express API — runs, audits, auth, scoring, queueing
apps/worker Playwright worker — screenshots, validations, analyzers, scoring
apps/client React + Vite dashboard
packages/types Shared TypeScript contracts (incl. scoring defaults)
docker/ docker-compose: all services on one network
storage/ Generated screenshots
docs/ Documentation
.env.example Config template (copy to .env for production)
development.env Local dev defaults (zero-config)
See docs/project-structure.md for details.
Requires Node ≥ 20 and Docker (for MongoDB + Redis). In dev, Docker runs only the infrastructure; the three apps run on the host for hot reload.
git clone https://github.com/<your-org>/sulayio.git
cd sulayio
npm run setup # install deps, install Playwright Chromium, start infra (mongo + redis)
npm run seed # seed admin user, viewport presets, and scoring config
npm run dev # run core-service + worker + client together- Client: http://localhost:5173
- API: http://localhost:4000
Run apps individually with npm run dev:core, npm run dev:worker,
npm run dev:client.
Two Compose profiles:
dev— infra only (mongo,redis); apps run on the host.prod— full containerized stack (infra + core-service + worker + client).
npm run infra:up # dev: mongo + redis only
npm run prod:up # prod: build + run everythingThe prod profile builds the images from source — no external registry. See
docker/README.md.
All settings live in one root env file — development.env (dev, committed with
safe defaults) or .env (production, gitignored). Copy the template to start:
cp .env.example .envBackend apps load it via configs/env; the client injects VITE_* vars at build
time. In Docker, values come from the compose environment: blocks.
Required in production (the app refuses to boot otherwise):
| Variable | Purpose |
|---|---|
TOKEN_SECRET |
Signs JWTs. Use a long random string (openssl rand -base64 48). |
CREDENTIALS_SECRET |
Encrypts saved credentials at rest. Same generation. |
Two roles: admin and user. Public registration always creates a
user. Scoring config edits require an admin.
Default accounts seed from seeds/users.seed.json (gitignored; copy the
template). The admin can also be set via ADMIN_EMAIL / ADMIN_PASSWORD.
cp seeds/users.seed.json.example seeds/users.seed.json
npm run seed| Role | Password | |
|---|---|---|
| admin | admin@sulayio.local |
admin12345 |
| user | user@sulayio.local |
user12345 |
Change these before any production-like run.
npm run seed also seeds device viewport presets (GET /viewports) and the
per-audit-type scoring config.
This is a personal open-source project, shared under the MIT license for others
to learn from and build on. Fork it and make it your own — pull requests are
not being accepted, and please don't push to this repository. See
CONTRIBUTING.md for local setup (npm run dev, npm run build).
MIT © France Patrick Lodonia