Skip to main content

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.
Root-level files:

Package Manager: pnpm Workspaces

pnpm v9.15.2 — Node ≥ 20.14.0 required. The root package.json exposes shorthand scripts to run commands scoped to a specific workspace:

Code Quality Tooling

Run: pnpm lint from repo rootPlugins enabled:
  • typescript-eslint — TypeScript-aware linting
  • eslint-plugin-react + eslint-plugin-react-hooks — React rules
  • eslint-plugin-react-refresh — Fast Refresh compatibility
  • eslint-plugin-prettier — Prettier as an ESLint rule
Run: pnpm format from repo rootConfig lives in .prettierrc.json at the repo root. Default: double quotes, consistent indentation.
Every git commit automatically triggers:
  1. eslint --fix on all staged **/*.{js,ts,tsx} files
  2. prettier --write on all other staged files
The hook is defined in .husky/pre-commit and configured via lint-staged in the root package.json.
Every commit message must follow the format:
Valid types: feat · fix · docs · style · refactor · test · chore · perf

How Packages Are Shared

Apps reference shared packages via the pnpm workspace protocol — no build or publish step needed during development:
pnpm symlinks these automatically. Changes in packages/common are immediately reflected in both apps.

Build Pipeline

Each app is built with Vite 7 + SWC:
The @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.tsnever 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).
All variables must be prefixed with VITE_ to be accessible in the browser. Unprefixed variables are undefined at runtime.
See the full variable lists for each app: