npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

axe-hud

v0.1.0

Published

In-page accessibility HUD that runs axe-core against the current page and surfaces findings in a floating widget, report sidebar, and per-page modal.

Readme

axe-hud

CI license

In-page accessibility HUD powered by axe-core. It audits the page you're looking at and surfaces findings in-context — a floating widget and a report sidebar — re-auditing automatically as you navigate.

🔎 Live demo → · 📚 API reference →

axe-hud widget and report sidebar

Framework-agnostic core with an optional React binding. The library has no environment logic — you decide where it runs by deciding where you load it (so it ships nothing to production).

Status: early development (pre-1.0). The public API may change before 1.0.0.

Why

Accessibility regressions are easiest to catch while you're actually using the app. axe-hud gives developers and QA live, in-context feedback against the EU-required baseline (EN 301 549 ≈ WCAG 2.1 A + AA) without leaving the page or opening devtools.

Features

  • 🧭 Runs axe-core against the currently rendered page.
  • 🔴🟢 Floating widget with a live violation count — neutral while auditing, red on violations, green when clean.
  • 📋 Report sidebar grouped by impact, with severity filters, doc links, and click-to-highlight.
  • 🔁 Re-audits on SPA navigation (History API, popstate, hashchange) and on demand.
  • 🧱 Isolated in a Shadow DOM — never leaks styles into, or scans, your app's own UI.
  • 🎛️ No env gating in the library — load it where you want it; guard the import and it never ships to production.
  • ⚡ axe-core is lazy-loaded on first audit, and code-split so a guarded import drops it from prod bundles.
  • ♿ The HUD itself is keyboard accessible (focus management, Escape to close, reduced-motion aware).

Install

npm install axe-hud
# or: pnpm add axe-hud / yarn add axe-hud

Quick start

createAxeHud() mounts the HUD immediately. The library has no environment gating, so you decide where it runs by deciding where you load it.

Vanilla

import { createAxeHud } from 'axe-hud'

const hud = createAxeHud()

// Imperative control if you need it:
hud.audit() // re-run on demand
hud.open() // open the report sidebar
hud.destroy() // tear everything down

React

import { AxeHudProvider } from 'axe-hud/react'

export function App() {
  return (
    <AxeHudProvider>
      <YourApp />
    </AxeHudProvider>
  )
}

Access the controller anywhere below the provider with useAxeHud().

Loading it for the right environments

Keep axe-hud out of production by not importing it there. A guarded dynamic import is the reliable way — the bundler drops the whole chunk (axe-hud + axe-core) from builds where the branch is statically false, so nothing ships to production.

// Load only in local + staging. `import()` keeps it out of the prod bundle entirely.
const APP_ENV = import.meta.env.VITE_APP_ENV // your own build-time variable

if (APP_ENV === 'development' || APP_ENV === 'staging') {
  const { createAxeHud } = await import('axe-hud')
  createAxeHud()
}
// Vite's built-in dev flag (local dev server only):
if (import.meta.env.DEV) {
  const { createAxeHud } = await import('axe-hud')
  createAxeHud()
}
// Node-style env (webpack, etc.):
if (['development', 'staging'].includes(process.env.APP_ENV)) {
  import('axe-hud').then(({ createAxeHud }) => createAxeHud())
}

For React, gate the provider (or its import) the same way. See docs/environments.md for more patterns.

Configuration

| Option | Type | Default | Description | | ------------ | -------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------- | | axe | AxeLike | lazy import('axe-core') | Inject a custom/pinned axe instance. | | axeOptions | axe.RunOptions | { runOnly: { type: 'tag', values: ['EN-301-549'] } } | Options passed to axe.run (rule set). | | axeContext | axe.ElementContext | excludes the HUD's own root | Context passed to axe.run. | | runOn | { initial?: boolean; navigation?: boolean } | { initial: true, navigation: true } | Which events trigger an audit. | | debounceMs | number | 250 | Debounce window for navigation-triggered audits. | | position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Corner the widget is anchored to. | | onAudit | (outcome) => void | (none) | Callback fired with every completed audit outcome. |

Controller

createAxeHud() returns a controller:

| Method | Description | | ----------- | ---------------------------------------------- | | audit() | Run an audit of the current page now. | | open() | Open the report sidebar. | | close() | Close the report sidebar. | | destroy() | Remove the HUD and restore all global patches. |

Rule set

The default targets the EU legal baseline via axe-core's EN-301-549 tag (which incorporates WCAG 2.1 A + AA). Widen or narrow it through axeOptions:

// Add best-practice rules and WCAG 2.2 AA on top of the EU baseline:
createAxeHud({
  axeOptions: { runOnly: { type: 'tag', values: ['EN-301-549', 'best-practice', 'wcag22aa'] } },
})

Performance

axe-core is imported lazily on the first audit and runs debounced and deferred to browser idle time. Navigation re-audits are coalesced, and superseded runs are discarded. When you load axe-hud behind a guarded dynamic import, it and axe-core are code-split out of production builds entirely, so end users never download either.

Browser support

Modern evergreen browsers (Chromium, Firefox, Safari). axe-hud is a development/QA aid and is not intended to ship to end users in production.

Documentation

Contributing

See CONTRIBUTING.md. Issues and PRs welcome.

License

MIT