Out of Order

GitHub
Getting started

From install to overlay in a minute

Install one package, call one function. This page walks the four ways to run Out of Order: the trace() overlay on your own page, the Chrome extension on any page you are looking at, audit() in a test or CI, and the CLI against any URL. What the rules catch, and how to re-grade or disable one, is on the rules page.

See it before you install

The playground is every focus and keyboard bug the analyzer catches, each one wired to break then get fixed live, with the overlay tracing the real tab path.

See it: @out-of-order/trace

The framework-agnostic overlay. Import it and call trace(), and you have numbered tab stops, the path between them, and every finding ringed in place.

import { trace } from "@out-of-order/trace";

const overlay = trace();

// Later, tear it down. This removes the layer, observers, and listeners.
overlay.destroy();

The overlay re-analyzes itself on every DOM mutation, so most pages need nothing beyond the mount. You can scope it to a subtree, hide and show it, or feed it rule overrides through trace(options). See the trace API.

See it anywhere: @out-of-order/extension

The Chrome side panel. Open it on any tab and it audits the page you are looking at. Each finding lists its rule, severity, and message, plus a possible fix.

Load it from the extension README. Reach for it when you want to check a page in the browser without touching its code.

Check it: @out-of-order/core

The analyzer on its own, no overlay. It gives you the verdict as plain data, which is what you assert in a test or CI, or feed into your own UI. Its own install, with no framework or test-runner deps.

import { audit, formatViolations } from "@out-of-order/core";

const result = audit();

result.valid; // boolean, true when there are no error-severity violations
result.sequence; // elements in tab order, each with tabIndex + rect
result.violations; // one entry per element: { element, selector, orderIndex, issues }

if (!result.valid) {
  // formatViolations renders a ready-to-print string from the structured result.
  console.log(formatViolations(result, "text"));
}

valid only goes false on an error. Warnings are advisory and never flip it. core API for every field.

Scan it: @out-of-order/cli

The same audit against any URL, without touching the page's code. It launches headless Chromium, runs the analyzer on the live page, and prints the findings, with an exit code that fails on errors so it can gate CI. Use it on a deployed site, a staging URL, or someone else's page.

npx playwright install chromium # once per machine

npx @out-of-order/cli https://example.com                  # prints findings, fails on errors
npx @out-of-order/cli https://example.com --format json    # the full result as JSON
npx @out-of-order/cli https://example.com --wait "[role=dialog]" # let a JS-heavy page settle
npx @out-of-order/cli https://example.com --overlay        # opens a browser with the overlay

For a page behind a login, run npx @out-of-order/cli login <url> once and sign in by hand. The session is saved, and every later audit of that host picks it up. The full option list is in the CLI README.