Accessibility Inspector
Runs axe-core against the user app, lists WCAG A/AA violations in a Solid panel, and highlights the element on hover.
Package: @devframes/plugin-a11y · framework: Solid + Vite

Hover to highlight the offending element

Generate prompts to fix issues
What it does
Three pieces, two browser-side:
| Piece | Runs in | Role |
|---|---|---|
| Page script | the user app's page | runs axe-core, owns the report state, draws the highlight ring |
| Panel | the devtools iframe | Solid SPA: lists violations, highlights on hover |
| Node side | the Node process | the get-config RPC (impact taxonomy), baked in static builds |
The page script and the panel talk over the in-page channel, so the loop works live or static. The page script is the author-provided bridge (the panel has no reach into the user app's DOM) — one module script scans, reports, and highlights.
In a hub
The definition declares the page script as its dock client script, so mounting by package name just works:
initHub({ devframes: ['@devframes/plugin-a11y'] })The hub serves the bundle same-origin and a client runtime imports it into the host page. Each scan also mirrors into the hub's messages feed — a summary plus one per rule.
A host can also mount the module itself — e.g. a Vite host via /@fs/:
import createA11yDevframe, { a11yPageScriptBundlePath } from '@devframes/plugin-a11y'
await ctx.install(createA11yDevframe(), {
dock: { clientScript: { importFrom: `/@fs/${a11yPageScriptBundlePath}` } },
})Outside a hub, a <script type="module"> boots the page script (no feed mirror).
Standalone
pnpx @devframes/plugin-a11yRuns the panel alone at /__devframes_plugin_a11y/; load the page script into a real page.
Mount into a Vite host
In Vite DevTools:
// vite.config.ts
import createA11yDevframe from '@devframes/plugin-a11y'
import { createPluginFromDevframe } from '@vitejs/devtools-kit/node'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
createPluginFromDevframe(createA11yDevframe()),
],
})Or swap in devframeVite(createA11yDevframe()) from @devframes/vite/single.
Programmatic
createA11yDevframe(options) returns a definition for any adapter:
import { createA11yDevframe } from '@devframes/plugin-a11y'
export default createA11yDevframe({
port: 9899,
})RPC
Namespaced devframes:plugin:a11y:*:
| Function | Type | Returns |
|---|---|---|
get-config | static | The impact taxonomy and the in-page channel coordinates. |
Run the demo
The demo serves a broken page and panel from one origin:
pnpm -C plugins/a11y build # build the panel + the page-script bundle
pnpm -C plugins/a11y demo # dev: live WebSocket RPC
pnpm -C plugins/a11y cli:build # bake the static deploy (dist/static)
pnpm -C plugins/a11y demo:build # static: baked RPC dump, no serverHover a row to highlight the matching element.