Route discovery and planning¶
Routes are the URLs a11yst audits in the browser. You can list them explicitly in config, discover them from your application source, or combine both. Before a11yst audit plans runs, resolved routes are merged according to routeDiscovery.mode.
This page describes application route discovery in your project under audit—not how the a11yst documentation site is built.
Explicit routes¶
List routes on each web project as path strings or objects with id, name, and path:
projects: [
{
name: "web",
platform: "web",
framework: "react",
baseUrl: "http://127.0.0.1:5173",
routes: ["/", "/settings", "/checkout"],
},
],
Explicit routes always take precedence over discovered routes with the same path. In merge mode, duplicates are deduplicated so each path appears once.
When routeDiscovery.mode is "off", only explicit routes are used. Validation requires at least one route in that mode.
Route discovery modes¶
| Mode | Default | Behavior |
|---|---|---|
off |
no | Explicit routes only; no adapter discovery |
fallback |
yes | Discovery runs when routes is empty; ignored when explicit routes exist |
merge |
no | Combines explicit routes with discovered routes (deduped by path) |
Precedence when paths overlap (highest first):
- explicit — configured in
routes - dynamic-sample — from
routeDiscovery.samples - filesystem / react-jsx-route / react-router-object — adapter discovery
- adapter-default — framework fallback (usually
/)
Additional config keys:
| Key | Purpose |
|---|---|
routeDiscovery.include |
Glob filters (reserved for future filtering) |
routeDiscovery.exclude |
Glob filters (reserved for future filtering) |
routeDiscovery.samples |
Map dynamic patterns to concrete paths to audit |
See Configuration for the full schema.
Framework-aware route discovery¶
Each web framework uses a matching adapter. Discovery behavior depends on the adapter—not on a generic site crawler.
| Framework | Discovery strategy | Fallback when empty |
|---|---|---|
| HTML | Filesystem scan for .html entry files |
none (uses discovered paths) |
| React | Static React Router AST scan | / with diagnostic |
| Next.js | App Router + Pages Router scan | uses discovered paths |
| Nuxt | pages/ filesystem scan |
/ when no pages found |
| Vue | none in this phase | / with diagnostic |
| Angular | none in this phase | / with diagnostic |
Adapters do not execute your application or evaluate modules at runtime. Discovery is static analysis of source and project layout.
Dynamic segments (for example /blog/:slug) are recorded as skipped patterns with reason requires configured value. Provide concrete paths in routeDiscovery.samples when you want them audited:
routeDiscovery: {
mode: "merge",
samples: {
"/projects/:slug": ["/projects/demo"],
},
},
React route discovery¶
React projects receive dedicated static React Router analysis in @a11yst/adapters. This is the most capable discovery path in the current release.
Supported patterns¶
| Pattern | Example | Origin |
|---|---|---|
JSX <Route> |
<Route path="/about" /> |
react-jsx-route |
| Nested JSX routes | Parent /projects + child featured → /projects/featured |
react-jsx-route |
| Index routes | <Route index /> under /projects → /projects |
react-jsx-route |
createBrowserRouter([...]) |
Route objects with path / children |
react-router-object |
createHashRouter([...]) |
Same object form as browser router | react-router-object |
useRoutes([...]) |
Inline or const-bound route arrays |
react-router-object |
| Local path constants | const ROOT = "/projects"; path={ROOT} |
Resolved when the value is a static string in the same file |
Router detection requires evidence from package.json (react-router / react-router-dom) and/or source imports and factory calls. React framework detection alone is not enough.
Dynamic routes and fallback¶
- Dynamic segments such as
/projects/:slugbecome skipped patterns; a11yst does not invent slug or id values. /fallback (origin: adapter-default) is used only when no React Router evidence exists or no auditable static/discovered routes are found.- When only dynamic patterns are discovered (with static
/), fallback is not used—the skipped patterns count as auditable discovery output. - When explicit routes are configured on the project, the React adapter skips discovery entirely (returns empty discovery).
Inspect discovery:
a11yst routes --explain
React limitations¶
- No general-purpose crawler or link extraction (
href,Link to, API strings, assets). - No runtime route generation, lazy module evaluation, or spread route configs.
- Non-static
pathexpressions are reported as unresolved, not guessed. - Custom routers or heavy runtime composition require explicit
routes.
Route fallback¶
Adapter fallback adds a single / route when an adapter cannot discover auditable paths:
| Adapter | Diagnostic code | When |
|---|---|---|
| React | REACT_ROUTES_EXPLICIT_RECOMMENDED |
No router routes discovered |
| React | REACT_ROUTER_NOT_DETECTED |
No router evidence |
| Vue | VUE_ROUTES_EXPLICIT_RECOMMENDED |
No filesystem discovery |
| Angular | ANGULAR_ROUTES_EXPLICIT_RECOMMENDED |
No filesystem discovery |
Fallback routes use origin: adapter-default. Configure explicit routes when fallback is too coarse for your app.
Mode fallback is a config setting, not the same as adapter fallback: it means “use discovery only when routes is empty.”
Route planning¶
Audit planning consumes resolved routes—not raw config alone.
prepareAuditConfig(in@a11yst/core) callsresolveProjectRoutesForProjectfor each web project. Adapter discovery and merge modes run here; diagnostics include skipped patterns asROUTE_PATTERN_SKIPPED.createAuditPlanexpands each resolved route × profile × viewport into planned runs. Flow checkpoints are planned separately.
Example: five discovered React routes with one profile and one viewport produce five route runs. See the react/comprehensive fixture tests below.
Explicit routes configured with routeDiscovery.mode: "off" skip discovery entirely during planning.
Route explanation (a11yst routes --explain)¶
The routes command resolves routes the same way as audit planning, without starting a browser.
a11yst routes [--json] [--config <path>] [--cwd <path>] [--project <name>] [--explain]
| Flag | Output |
|---|---|
| (default) | Human-readable resolved routes per project |
--json |
Structured JSON on stdout (no ANSI) |
--explain |
Adds discovery strategy, router evidence, origins, skipped patterns, explicit routes, and fallback status |
JSON fields include routes (with origin, optional sourceFile / sourceLine), skippedPatterns, diagnostics, explain, and explicitRoutes.
Human --explain output includes sections such as Explain, Router detected, discovered route sources, and unresolved patterns marked with !.
See CLI reference.
Inspecting routes before an audit¶
a11yst routes
a11yst routes --json
a11yst routes --explain --project web
Use this to confirm discovery, dynamic pattern skips, and fallback before a long audit.
Tests and fixtures¶
Behavior is covered by unit and integration tests in the a11yst repository.
Unit tests¶
| Area | Test file |
|---|---|
| React discovery | tests/unit/adapters/react-discovery.test.ts |
| HTML discovery | tests/unit/adapters/html-discovery.test.ts |
| Next.js discovery | tests/unit/adapters/next-discovery.test.ts |
| Nuxt discovery | tests/unit/adapters/nuxt-discovery.test.ts |
| Merge / precedence | tests/unit/adapters/merge.test.ts |
Adapter / fallback |
tests/unit/adapters/fallback-adapters.test.ts |
| Config validation | tests/unit/config/route-discovery-config.test.ts |
| Core resolution + planning | tests/unit/core/route-resolution.test.ts |
CLI integration¶
| Test | File |
|---|---|
a11yst routes JSON, --explain, --project |
tests/integration/cli/routes-cli.test.ts |
Fixtures (tests/fixtures/adapters/)¶
| Fixture | Exercises |
|---|---|
react/jsx-routes |
JSX <Route> paths |
react/nested-routes |
Nested and index routes |
react/create-browser-router |
createBrowserRouter / hash router objects |
react/use-routes |
useRoutes arrays and local constants |
react/dynamic-route |
Skipped :slug / :id patterns |
react/false-positives |
Ignores href, API, and asset strings |
react/no-router |
Adapter / fallback |
react/comprehensive |
Mixed JSX + dynamic pattern + audit planning |
html/ |
Filesystem HTML entry discovery |
next/app-router |
App Router pages + skipped dynamic segments |
nuxt/ |
pages/ scan |
Run directed tests:
pnpm vitest run tests/unit/adapters/react-discovery.test.ts \
tests/unit/adapters/merge.test.ts \
tests/unit/adapters/html-discovery.test.ts \
tests/unit/adapters/next-discovery.test.ts \
tests/unit/adapters/nuxt-discovery.test.ts \
tests/unit/adapters/fallback-adapters.test.ts \
tests/unit/config/route-discovery-config.test.ts \
tests/unit/core/route-resolution.test.ts \
tests/integration/cli/routes-cli.test.ts