What’s in the Monorepo
The frontend is a pnpm workspace monorepo with two deployable apps and two shared packages.apps/full-suite
Main auditing dashboard — accessibility, performance, SEO, uptime, RUM, billing, and team management. Runs on port 5173.
apps/a11y
Standalone accessibility-only SaaS app with simplified onboarding. Runs on port 5174.
packages/common
Shared React UI library — components, hooks, types, utilities, and icons consumed by both apps.
packages/focus-order
@webyes/focus-order — published dual ESM/CJS library that visualises keyboard focus order in web pages.Package Manager: pnpm Workspaces
pnpm v9.15.2 — Node ≥ 20.14.0 required. The rootpackage.json exposes shorthand scripts to run commands scoped to a specific workspace:
Code Quality Tooling
ESLint 9.27.0 (flat config)
ESLint 9.27.0 (flat config)
Run:
pnpm lint from repo rootPlugins enabled:typescript-eslint— TypeScript-aware lintingeslint-plugin-react+eslint-plugin-react-hooks— React ruleseslint-plugin-react-refresh— Fast Refresh compatibilityeslint-plugin-prettier— Prettier as an ESLint rule
Prettier 3.5.3
Prettier 3.5.3
Run:
pnpm format from repo rootConfig lives in .prettierrc.json at the repo root. Default: double quotes, consistent indentation.Husky + lint-staged (pre-commit)
Husky + lint-staged (pre-commit)
Every
git commit automatically triggers:eslint --fixon all staged**/*.{js,ts,tsx}filesprettier --writeon all other staged files
.husky/pre-commit and configured via lint-staged in the root package.json.Commitlint (Conventional Commits)
Commitlint (Conventional Commits)
Every commit message must follow the format:Valid types:
feat · fix · docs · style · refactor · test · chore · perfHow Packages Are Shared
Apps reference shared packages via the pnpm workspace protocol — no build or publish step needed during development:packages/common are immediately reflected in both apps.
Build Pipeline
Each app is built with Vite 7 + SWC:@tanstack/router-vite-plugin runs automatically during every build and dev session:
1
Scan routes folder
Reads all files inside
src/routes/ and derives the URL structure from the file names.2
Generate route tree
Writes
src/routeTree.gen.ts — never edit this file manually, it is always overwritten.3
Enable code splitting
Routes ending in
.lazy.tsx are split into separate JS chunks, loaded only when visited.TypeScript Setup
Each app has its own
tsconfig.json. The packages/common package is consumed directly from source — no separate compile step during development.
Environment Variables
Each app has its own.env (gitignored) and .env.sample (committed).