Accessibility scanning SaaS for ADA/WCAG workflows.
This repo is a Turborepo monorepo with:
- a Next.js web app (
apps/web) - a worker app (
apps/worker) - shared scanner/types utilities (
packages/shared)
Current MVP flow is web-first: core scan and AI routes run from apps/web.
Worker/queue deployment is phase-based and can be added when you enable background processing.
- Purpose: scan websites for accessibility issues and provide fix guidance.
- Primary stack: Next.js + TypeScript + Drizzle + Neon Postgres.
- Shared package:
@shared/typesis consumed by both web and worker. - Active API routes in web app now:
POST /api/scanPOST /api/fix-guidePOST /api/ai-scan
apps/
web/ # Next.js app + API routes
worker/ # Queue/worker app (phase-based)
packages/
shared/ # Shared types/scanner/scoring utilities (@shared/types)
docs/
PROJECT.md # Architecture and project context
PHASES.md # Phase-by-phase implementation plan
- Node.js
>=20(see rootpackage.jsonand.nvmrc) - npm (workspace-aware; repo uses npm workspaces)
- Optional but recommended for full setup:
- Neon Postgres account
- Redis provider (Railway Redis / Upstash) for queue phases
git clone <your-repo-url>
cd ada-wasg-test
npm installCreate local env file:
cp .env.example .env.localStart dev mode (all workspaces via turbo):
npm run devOpen:
- Web app:
http://localhost:3000
Copy from .env.example and fill what you need for your current phase.
| Variable | Required Now | Notes |
|---|---|---|
DATABASE_URL |
Yes (for DB-backed routes) | Neon pooled connection string |
NEXTAUTH_SECRET |
For auth flows | NextAuth secret |
NEXTAUTH_URL |
Yes | Local default is http://localhost:3000 |
APP_URL |
Yes | Used by report-related flows; local default http://localhost:3000 |
| Variable | Required | Notes |
|---|---|---|
REDIS_URL |
When queue/worker is enabled | Redis connection URL |
| Variable | Required | Notes |
|---|---|---|
ANTHROPIC_API_KEY |
Optional (future model routing) | |
OPENAI_API_KEY |
Optional fallback | |
WAVE_API_KEY |
Optional | Enables WAVE checks when used |
DISABLE_INSECURE_TLS_FALLBACK |
Optional | Local/dev only toggle for /api/ai-scan TLS retry behavior |
| Variable | Required | Notes |
|---|---|---|
BLOB_READ_WRITE_TOKEN |
When PDF/blob flow is enabled | Vercel Blob token |
| Variable | Required | Notes |
|---|---|---|
STRIPE_SECRET_KEY |
When billing enabled | |
STRIPE_WEBHOOK_SECRET |
When billing enabled | |
RESEND_API_KEY |
When email enabled |
drizzle.config.ts points to:
- schema:
./apps/web/src/db/schema.ts - output:
./drizzle
Run migrations:
npm run db:generate
npm run db:migrateOptional DB studio:
npm run db:studioRoot (Turborepo):
npm run dev
npm run build
npm run test
npm run lintWorkspace-specific:
# web
npm run dev --workspace=@app/web
npm run build --workspace=@app/web
npm run lint --workspace=@app/web
# worker
npm run dev --workspace=@app/worker
npm run build --workspace=@app/worker
npm run lint --workspace=@app/worker
npm run test --workspace=@app/workerapps/webis the active runtime for scanning and AI routes in the current setup.apps/workerexists for queue/background architecture and is phase-based.packages/shared(@shared/types) is shared by both apps to keep scanner/types logic consistent.
Recommended production split:
apps/web-> Vercelapps/worker-> Railway- Postgres -> Neon
- Redis -> managed Redis (Railway/Upstash)
Deployment model:
- One GitHub repository
- Separate deploy targets per app (
apps/webandapps/worker) - Shared code (
packages/shared) comes from the same commit for both services
Start-cheap path:
- Deploy only
apps/webfirst (if queue/worker is not enabled yet) - Add worker + Redis when you move to background scan execution
If you see a certificate-chain error like local issuer issues during HTML fetch, this project includes a dev-friendly fallback retry path for non-production.
If needed, set:
DISABLE_INSECURE_TLS_FALLBACK=falseNever disable TLS verification behavior in production.
In a fresh setup, next lint may prompt for ESLint initialization in apps/web. Complete that once, then rerun lint commands.
- Missing
DATABASE_URL: DB routes/migrations fail. - Missing AI keys: AI endpoints return configuration errors.
- Incorrect
NEXTAUTH_URLorAPP_URL: auth/report-related behavior can break.
Main:
Recent scan:
Scan result:
Scan result (detail):