Skip to content

Configuration

Eqo is configured through a file named rgaa.config.ts (or .js, .mjs, .json) at the root of your project. The file exports a default configuration object validated by a Zod schema at startup — if your config is invalid, Eqo reports a clear error and exits before running any analysis.

FormatWhen to use
rgaa.config.tsTypeScript projects. Requires jiti (~223 KB lazy-loaded chunk) for transpilation.
rgaa.config.jsRecommended. No extra dependency. Identical results to .ts.
rgaa.config.mjsExplicit ESM-only JavaScript without TypeScript.
rgaa.config.jsonMinimal setups with no programmatic logic (no comments, no expressions).

The defineConfig helper provides full TypeScript inference on the configuration object:

rgaa.config.ts
import { defineConfig } from "@kodalabs-io/eqo";
export default defineConfig({
// Your editor will autocomplete every field and flag type errors
});

defineConfig is a zero-overhead identity function — it returns the object you pass in without modification. Its only purpose is to trigger TypeScript’s type narrowing.


rgaa.config.ts
import { defineConfig } from "@kodalabs-io/eqo";
export default defineConfig({
baseUrl: "http://localhost:3000",
projectName: "Service Public Numérique",
locale: "fr-FR",
pages: [
{ path: "/", name: "Home" },
{ path: "/contact", name: "Contact" },
{ path: "/mentions-legales", name: "Legal Notices" },
{ path: "/accessibilite", name: "Accessibility Declaration" },
{ path: "/recherche", name: "Search" },
],
output: [
{ format: "json", path: "./public/rgaa-report.json" },
{ format: "html", path: "./reports/rgaa.html" },
{ format: "sarif", path: "./reports/rgaa.sarif" },
{ format: "markdown", path: "./reports/rgaa.md" },
{ format: "junit", path: "./reports/rgaa.junit.xml" },
],
thresholds: {
complianceRate: 80,
failOn: "threshold",
},
exemptions: [
{
criterion: "4.1",
reason: "No video content is published on this site. Criterion 4.1 is not applicable.",
},
],
static: {
include: ["src/**/*.{tsx,jsx,ts,js}", "components/**/*.tsx"],
exclude: ["**/*.test.*", "**/*.spec.*", "**/*.stories.*", "**/node_modules/**"],
},
});

baseUrl: string

The base URL of your running Next.js application. Must use http:// or https:// protocol. Used exclusively by the runtime (Playwright) phase to construct full page URLs.

baseUrl: "http://localhost:3000" // local development
baseUrl: "https://staging.example.fr" // staging environment

The server at baseUrl must be running and reachable when you run eqo analyze (unless you use --static-only). Eqo does not start or wait for your server.

Validation: Must be a valid URL starting with http:// or https://. Zod will reject bare hostnames (localhost:3000) or file paths.


pages: Array<{
path: string; // must start with "/"
name?: string; // human-readable label shown in reports
}>

The list of pages to audit during the runtime phase. Each path is appended to baseUrl to form the full URL.

pages: [
{ path: "/", name: "Home" },
{ path: "/about", name: "About" },
{ path: "/contact", name: "Contact" },
]

Validation: Each path must start with /. At least one page is required.


output: Array<{
format: "json" | "html" | "sarif" | "markdown" | "junit";
path: string; // relative to project root
minify?: boolean; // JSON only, default: false
}>

One or more output formats. At least one entry is required.

FormatBest forKey notes
jsonYour /accessibility pageWrite to ./public/ so Next.js serves it statically. Type it as RGAAReport from @kodalabs-io/eqo.
htmlVisual review by your teamInteractive, filterable. Open in any browser — no server needed.
sarifGitHub Code ScanningDisplays inline annotations on PR diffs in the Security tab.
markdownPR commentsPaste into PR descriptions or pipe into a GitHub comment bot.
junitCI dashboardsCompatible with Jenkins, CircleCI, GitLab CI test reporters.

Recommended minimum for most projects:

output: [
{ format: "json", path: "./public/rgaa-report.json" }, // powers /accessibility
{ format: "sarif", path: "./reports/rgaa.sarif" }, // GitHub Code Scanning
],

Production optimization — minify JSON:

{ format: "json", path: "./public/rgaa-report.json", minify: true }

The minify option applies only to JSON. It strips whitespace from the output file, reducing its size by ~40% — useful when the report is served as a static asset.


thresholds?: {
complianceRate?: number; // 0–100, default: 0
failOn?: "error" | "threshold" | "none"; // default: "threshold"
}

Controls whether Eqo exits with code 1 (CI failure) after the audit.

Decision guide: which strategy fits your situation?

Section titled “Decision guide: which strategy fits your situation?”
Your situationRecommended config
First audit on an existing project — you don’t know your current ratecomplianceRate: 0 — never blocks, report is still generated
Want to prevent new errors without a rate targetcomplianceRate: 0, failOn: "error" — blocks only on error-severity issues
Established project with a known baseline (e.g., 72%)complianceRate: 72, failOn: "threshold" — fails if you drop below 72%
Targeting full automated compliancecomplianceRate: 100, failOn: "threshold" — fails if any criterion is invalidated
Reporting only, CI must never breakcomplianceRate: 0, failOn: "none" — always exits 0
failOncomplianceRateResult
"threshold"0Never blocks. Equivalent to "none". Report is generated, CI continues.
"threshold"80Exits 1 if compliance rate < 80%.
"threshold"100Exits 1 if any applicable criterion is invalidated.
"error"anyExits 1 if any issue with severity "error" is found — regardless of rate.
"none"anyNever blocks. Always exits 0.

exemptions?: Array<{
criterion: string; // format: "X.Y" — e.g., "4.1"
reason: string; // minimum 10 characters
}>

RGAA criteria that are intentionally excluded from analysis because they are genuinely not applicable to your site or service.

exemptions: [
{
criterion: "4.1",
reason: "No video content is published on this site. Criterion 4.1 is not applicable.",
},
{
criterion: "4.3",
reason: "No audio-only content is published. Criterion 4.3 does not apply.",
},
{
criterion: "13.7",
reason: "No animated content or flashing elements are present on any page.",
},
],

Validation: The criterion field must match the format X.Y (e.g., "4.1", "11.9"). The reason must be at least 10 characters.


locale?: "en-US" | "fr-FR" // default: "en-US"

The language for report messages, remediation guidance, and console output.

locale: "fr-FR" // all messages and reports in French

The locale can be overridden at runtime with the --locale CLI flag without modifying the config file.


projectName?: string

A human-readable name for your project, shown in HTML and JSON report headers. Defaults to the name field from your package.json.

projectName: "Service Public Numérique — Portail Citoyen"

static?: {
include?: string[]; // glob patterns for files to analyze
exclude?: string[]; // glob patterns for files to skip
}

Controls which files are included in the static (AST) analysis phase.

Defaults:

static: {
include: ["src/**/*.{tsx,jsx,ts,js}"],
exclude: ["**/*.test.*", "**/*.spec.*", "**/node_modules/**"],
}

Override when your project layout differs from the Next.js standard:

static: {
include: [
"src/**/*.{tsx,jsx}", // Next.js app directory
"components/**/*.tsx", // shared component library
"app/**/*.tsx", // Next.js 13+ App Router
],
exclude: [
"**/*.test.*",
"**/*.spec.*",
"**/*.stories.*", // Storybook files
"**/node_modules/**",
"**/__tests__/**",
"**/e2e/**",
],
},