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

web-audit-helper

v1.5.3

Published

Framework-agnostic web audit overlay for accessibility, SEO, semantic and responsive validation.

Downloads

2,602

Readme

WAH – Web Audit Helper 🧠

npm version License: MIT TypeScript

WAH is a framework-agnostic JavaScript/TypeScript library that helps developers audit web pages for accessibility, SEO, semantic HTML, responsive design, security, quality, performance, and form validation.

It provides real-time DOM analysis, a floating visual overlay, console diagnostics, and exportable reports without any runtime dependencies.


✨ Features

  • 75 Audit rules across 8 categories (Accessibility, SEO, Semantics, Responsive, Security, Quality, Performance, Forms)
  • 🧱 Semantic HTML analysis (proper elements, H1 hierarchy, main/nav/section structure)
  • 🔍 SEO best practices (title, meta description, viewport, canonical, Open Graph, Twitter Cards)
  • 📱 Responsive design heuristics (viewport meta, fixed-width, 100vh issues, overflow)
  • 🔒 Security checks (target=_blank, tabnabbing, mixed content, unsafe patterns)
  • Performance optimization (image optimization, lazy loading, async decode, script placement, caching, render-blocking resources)
  • 📋 Form validation (proper types, autocomplete, required indicators, label association)
  • 🎨 Interactive overlay with drag, hide, category filters, and issue focus
  • 📊 5 scoring modes (strict/normal/moderate/soft/custom) with auto-calibration
  • 📤 Export reports (JSON, TXT, HTML) with complete metadata
  • 🧩 Framework-agnostic (works with vanilla JS, React, Vue, Angular, etc.)
  • 🧹 Zero runtime dependencies (only dev dependencies)
  • Temporary hide system (hide overlay for X minutes or until next refresh)
  • 🧠 Console diagnostics with issue focusing and timestamps
  • 🌐 Internationalization with English and Spanish support

🚀 Installation

npm install web-audit-helper

📖 Quick Start

Documentation Map

Which Mode Should I Use?

| Mode | Best for | | --- | --- | | embedded | local development and direct app integration | | external | bookmarklet-driven audits on already-open pages |

Common use cases:

  • I am building a site/app and want continuous feedback: use embedded mode.
  • I want to audit any page from the browser quickly: use external mode.
  • I want CI/headless automation: planned for v2.0 CLI, not part of v1.5.0.

Browser (via CDN)

<script type="module">
  import { runWAH } from 'https://unpkg.com/[email protected]/dist/index.js';

    // Run with default configuration
    await runWAH();
</script>

Browser Bundlers (Vite / Create React App / Vue SPA)

⚠️ SSR Frameworks: If using Next.js, Nuxt, SvelteKit or similar, see the Next.js / SSR Frameworks section below.

import { runWAH } from 'web-audit-helper';

// Default configuration (recommended for development)
await runWAH();

// Custom configuration
await runWAH({
    logs: true,
    logLevel: 'full',
    issueLevel: 'all',
  auditMetrics: {
    enabled: true,
    includeInReports: false,
    consoleTopSlowRules: 10,
    consoleMinRuleMs: 0
  },
  rules: {
    'ACC-02': 'off',
    'ACC-22': { severity: 'warning', threshold: 14 },
    'ACC-10': 'critical',
    'ACC-25': { threshold: 5 },
    'UX-01': { threshold: 48 }
  },
    accessibility: {
        minFontSize: 12,
        contrastLevel: 'AA'
    },
    overlay: {
        enabled: true,
        position: 'bottom-right',
        hide: 0
    }
});

External Auditing (Bookmarklet)

WAH now includes a generated bookmarklet for external audits against already-open pages.

  1. Run build:
npm run build
  1. Copy the single line from dist/bookmarklet.txt.
  2. Create a browser bookmark and paste that line as URL.
  3. Open any target page and click the bookmark.

Runtime loading strategy:

  • Primary: IIFE runtime from jsDelivr (external-runtime.iife.js)
  • Fallback: ESM runtime from jsDelivr (external-runtime.mjs)

If CSP blocks both loads, WAH shows a clear error and aborts external execution.

Where is dist/bookmarklet.txt?

  • It is generated when building this repository (npm run build), because postbuild runs scripts/gen-bookmarklet.mjs.
  • If you are inside another app repo (for example React/PHP) and only installed WAH as dependency, you will not automatically get this repository build pipeline output.
  • For external auditing, use either:
    • bookmarklet from this repository build output, or
    • bookmarklet generated from the published version ([email protected]).

Detailed external auditing flow:

  1. Build local artifacts (npm run build).
  2. Install bookmarklet from dist/bookmarklet.txt.
  3. Open a target page already loaded in your browser.
  4. Trigger the bookmarklet.
  5. Export JSON/HTML from the overlay.
  6. Run a second audit and export again to validate run comparison.

v1.5 capabilities now available in external mode:

  • runtimeMode = external in exported metadata
  • Extended metadata (runId, targetUrl, executedAt, wahVersion, issueCountBySeverity, categoryScores, rulesExecuted, rulesSkipped, totalAuditMs)
  • Optional run comparison in JSON and HTML exports (overall score delta, severity delta, added/removed rule IDs, category deltas, timing delta when metrics exist)

Pre1.5 local validation flow (before npm publish):

  1. Build artifacts locally:
npm run build
  1. Start a local static server from repository root:
npx http-server . -p 4173 --cors
  1. Use a local bookmarklet URL that targets http://127.0.0.1:4173/dist.
  2. Validate permissive and blocking fixtures:
    • http://127.0.0.1:4173/examples/csp-permissive.html
    • http://127.0.0.1:4173/examples/csp-blocking.html

Post-publish real-page flow (release validation):

  1. Publish [email protected] to npm.
  2. Rebuild bookmarklet so it points to fixed jsDelivr @1.5.0 assets.
  3. Validate in at least one static target and one SPA target.
  4. Export JSON/HTML and verify meta.runtimeMode = external and run comparison block.

Release-gate checklist for real pages:

  1. Validate at least one static website and one SPA website.
  2. Confirm no fatal bootstrap error on successful targets.
  3. Confirm JSON export includes meta.runtimeMode = external.
  4. Confirm second-run export includes comparison diff in JSON/HTML.
  5. Record evidence (screenshots + console/network excerpts).

Quick FAQ (v1.5 external audits):

  • Why does external auditing fail on some pages?
    • Strict CSP can block script injection and dynamic imports. WAH aborts with a clear error in this case.
  • Does it work behind login?
    • Yes, if the page is already open and authenticated in the current tab/session.
  • Does it crawl multiple pages?
    • No. v1.5 audits only the currently open page.
  • Can I run it in CI headless mode?
    • Not in v1.5. That is planned for future CLI/headless milestones.

Troubleshooting matrix:

  • ERR_CONNECTION_REFUSED for 127.0.0.1:4173:
    • Local static server is not running. Start npx http-server . -p 4173 --cors.
  • Failed to load external-runtime.iife.js on real pages:
    • Usually strict CSP or blocked third-party script injection.
  • Failed to fetch dynamically imported module:
    • ESM fallback blocked by CSP/CORS/network policy.
  • Overlay appears on fixture but not on enterprise sites:
    • Expected for strict CSP sites. Use that as controlled failure evidence.

QA checklist for CSP permissive/blocking validation:

Evidence examples:

External overlay success

External CSP blocked error

HTML report comparison

JSON metadata with runtimeMode external

Next.js / SSR Frameworks

WAH runs in the browser only (requires DOM).

SSR frameworks must run it client-side using a Client Component + useEffect.

Use dynamic import to avoid window is not defined errors.

JavaScript Example (App Router)

// src/components/WahRunner.jsx
'use client';

import { useEffect } from 'react';

export default function WahRunner() {
  useEffect(() => {
    import('web-audit-helper')
      .then(({ runWAH }) => runWAH())
      .catch(console.error);
  }, []);

  return null;
}
// app/layout.js
import WahRunner from '@/components/WahRunner';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <WahRunner />
        {children}
      </body>
    </html>
  );
}

TypeScript Example (App Router)

// src/components/WahRunner.tsx
'use client';

import { useEffect, useRef } from 'react';

export default function WahRunner() {
  const ran = useRef(false);

  useEffect(() => {
    if (ran.current) return;
    ran.current = true;

    import('web-audit-helper')
      .then(({ runWAH }) => runWAH())
      .catch(console.error);
  }, []);

  return null;
}
// app/layout.tsx
import type { ReactNode } from 'react';
import WahRunner from '@/components/WahRunner';

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>
        <WahRunner />
        {children}
      </body>
    </html>
  );
}

Why dynamic import? It prevents the server from evaluating the module, eliminating window is not defined errors.

Why useRef in TypeScript? React Strict Mode runs useEffect twice in development; useRef ensures WAH only runs once.


⚙️ Configuration

WAH supports extensive configuration options for customization:

  • logs (boolean, default: true): Enable console logging.
  • consoleOutput ('none' | 'minimal' | 'standard' | 'detailed' | 'debug', default: 'standard'): Console output preset (controls logLevel, logging, scoreDebug, and auditMetrics).
  • issueLevel ('critical' | 'warnings' | 'all', default: 'all'): Filter which issues to report.
  • locale ('en' | 'es', default: auto): User-facing language (es if browser language is Spanish).
  • rules (Record<string, RuleOverrideValue>, default: undefined): Rule-level overrides by stable rule ID (disable, severity, threshold).
  • accessibility.minFontSize (number, default: 12): Minimum font size in pixels.
  • accessibility.contrastLevel ('AA' | 'AAA', default: 'AA'): WCAG contrast requirement level.
  • overlay.enabled (boolean, default: true): Show visual overlay interface.
  • overlay.position (string, default: 'bottom-right'): Overlay position (bottom-left/bottom-right/top-left/top-right).
  • overlay.hide (number, default: 0): Hide overlay for X milliseconds on load.

Rule overrides (rules field):

  • 'off' disables a rule entirely by ID — it is skipped at runtime.
  • Severity override — string: 'critical', 'warning', 'recommendation' — or object: { severity: 'warning' }.
  • threshold is supported for: ACC-21 (focus sample size), ACC-22 (min font size px), ACC-25 (min contrast ratio), ACC-26 (min line-height), UX-01 (min touch target px), RWD-01 (min width risk px), RWD-04 (min fixed/sticky overlap ratio), PERF-02 (max font resources), PERF-03 (max external scripts), PERF-06 (min static resources for cache reminder), PERF-08 (image sample size).
  • Threshold and severity can be combined: { severity: 'critical', threshold: 16 }.

Audit metrics options (auditMetrics field):

  • enabled (default: true): track total and per-rule execution time.
  • includeInReports (default: false): include metrics in JSON/TXT/HTML exports.
  • consoleTopSlowRules (default: 10): max slow rules shown in console timing table.
  • consoleMinRuleMs (default: 0): minimum ms threshold to appear in timing table.

Score debugging:

  • scoreDebug (default: false): shows detailed per-category score breakdown with multipliers and weighted contributions in the console.

Enhanced logging options (logging object):

  • timestamps (default: false): include timestamps in console logs.
  • groupByCategory (default: true only in detailed/debug presets): group issues by category.
  • showStatsSummary (default: true only in detailed/debug presets): display statistics tables.
  • useIcons (default: true in standard/detailed/debug): add visual icons (🔴 ⚠️ 💡) to issues.

Configuration Examples

// Full developer experience with all enhancements
await runWAH({
  scoreDebug: true,
  logging: {
    timestamps: true,
    groupByCategory: true,
    showStatsSummary: true,
    useIcons: true
  }
});

// Minimal clean output
await runWAH({
  logging: {
    timestamps: false,
    groupByCategory: false,
    showStatsSummary: false,
    useIcons: false
  }
});

// Custom rule configuration with metrics
await runWAH({
  rules: {
    'ACC-22': { threshold: 16 },  // Custom font size minimum
    'ACC-01': 'off',              // Disable html lang check
    'SEO-01': { severity: 'critical' }  // Upgrade to critical
  },
  auditMetrics: {
    enabled: true,
    consoleTopSlowRules: 5,
    consoleMinRuleMs: 1
  }
});

For complete configuration documentation, see Configuration Guide. Spanish version: Guia de Configuracion. Contribution guide: Contributing. Guia de contribucion: Contribuir.


📊 Scoring System

WAH calculates a score from 0-100 with letter grades A-F:

Scoring Modes

  • strict (25/10/5): Most aggressive penalties – catches all issues
  • normal (20/8/4): Balanced default – recommended for general use
  • moderate (20/8/0): Ignores recommendations – focuses on critical/warnings
  • soft (20/0/0): Only critical issues – strictest scope
  • custom: User-controlled filters with auto-calibrated multipliers

Custom Filters

Enable custom mode to filter by:

  • Severities: critical, warning, recommendation
  • Categories: accessibility, seo, semantic, responsive, security, quality, performance, form

Multipliers automatically calibrate based on active categories:

  • 1 category: 4x reduction
  • 2 categories: 2x reduction
  • 3-4 categories: 1.33x reduction
  • 5+ categories: no reduction

🎯 Audit Rules (75 Total)

WAH implements comprehensive audit rules across 8 categories:

Accessibility

Font size, alt text, labels, links, buttons, ARIA, skip links, headings, focus, contrast, line-height, etc.

Semantic HTML

H1 hierarchy, semantic elements (strong/em), main, nav, canonical structure

SEO

Title, meta description, viewport, canonical, Open Graph, Twitter Cards, charset, robots

Responsive Design

Viewport meta, fixed widths, overflow, fixed elements, 100vh issues

Security

Target=_blank security, mixed-content detection, transport safety

Quality

Inline styles, dummy links, duplicate controls, semantic naming

Performance

Image optimization, lazy loading, async decode, script placement, fonts, caching, render-blocking CSS

Forms

Submit buttons, required indicators, input types, autocomplete

For complete rules reference, see Rules Documentation. Quick index by rule ID: Rules Guide. Spanish version: Documentacion de Reglas. Indice rapido en espanol: Guia de Reglas.


🎮 Console Commands

WAH exposes global commands for interaction:

__WAH_FOCUS_ISSUE__(index)

Highlights a specific issue element in the DOM and logs its details.

__WAH_FOCUS_ISSUE__(0)  // Focus on first issue

__WAH_RESET_HIDE__()

Clears hide settings and reloads the overlay.

__WAH_RESET_HIDE__()  // Restore overlay immediately

__WAH_RERUN__()

Re-runs the audit after DOM changes without page reload.

__WAH_RERUN__()  // Refresh audit

⌨️ Keyboard Shortcuts

WAH overlay supports keyboard shortcuts for improved accessibility and productivity:

  • Escape: Toggle overlay collapse/expand
  • Ctrl/Cmd + E: Rerun audit
  • Alt + W: Focus on overlay (for keyboard navigation)
  • Tab/Shift+Tab: Navigate through overlay controls with focus trap

All interactive elements support keyboard navigation with visible focus indicators.


📤 Export Reports

Run WAH with logging enabled to export reports to the console:

await runWAH({
    logs: true,
    logLevel: 'full'
});

// Reports are printed to console as:
// - Table format (filtered by category and severity)
// - JSON export
// - TXT export (with detailed formatting)
// - HTML export (full report with styling)

Reports include:

  • Overall score and grade
  • Score by category
  • Detailed issue list with CSS selectors
  • Applied filters and scoring mode
  • Viewport and user agent info
  • Timestamp and WAH version

🎨 Overlay & Interface

The overlay provides a floating interface with:

  • Score badge: Displays overall score and grade
  • Category breakdown: Shows individual category scores
  • Issue list: Filterable by severity (critical/warning/recommendation) and category
  • Issue focus: Click to highlight elements in the DOM
  • Filters: Toggle severities and categories to customize scoring
  • Settings: Configure scoring mode, hide behavior, and language selector (en/es) with persistence across reloads
  • Export: Download audit reports in JSON, TXT, or HTML format
  • Hide: Temporarily hide overlay for X minutes or until next refresh

🏗️ Architecture

WAH is organized into clear modules:

  • core/: Audit engine with 60+ rules across 8 categories
  • overlay/: Visual UI components (Overlay, Popover, filters, drag)
  • reporters/: Export formats (JSON, TXT, HTML) with metadata
  • utils/: Shared utilities (console logging, DOM helpers)

For architecture details, see Architecture Guide. Spanish version: Guia de Arquitectura.


🔧 API Reference

runWAH(userConfig?: Partial<WAHConfig>): Promise<AuditResult>

Main entry point to run the audit.

Parameters:

  • userConfig (optional): Partial configuration object to override defaults

Returns:

  • AuditResult: Object containing issues array and overall score

Example:

const result = await runWAH({ logLevel: 'summary' });
console.log(`Score: ${result.score}%`);
console.log(`Issues: ${result.issues.length}`);

For complete API documentation, see API Reference. Spanish version: Referencia de API.


🌐 Internationalization

  • Built-in locales: en, es
  • Internal IDs and config keys remain in English
  • User-facing strings are localized (overlay, console, TXT/HTML reports, docs)
  • Locale resolution order: userConfig.locale -> persisted selector value -> browser detection (es* => es, otherwise en)
  • Runtime translations are loaded from JSON locale payloads in locales/<lang>/common.json
  • JSON reports stay in English for machine integrations
  • Overlay header title is fixed as WAH Report; report title is fixed as Web Audit Helper Report

For contribution workflow and community translation model, see Translations Guide.


❓ FAQ / Troubleshooting

Module not found: Can't resolve 'web-audit-helper'

Cause: Package not installed, workspace misconfigured, or lockfile inconsistency.

Solution:

rm -rf node_modules package-lock.json
npm install

Or verify the package is listed in package.json dependencies:

npm install web-audit-helper --save-dev

ReferenceError: window is not defined

Cause: You're importing or executing WAH during server-side rendering (SSR).

Solution: Use a Client Component with dynamic import:

'use client';
import { useEffect } from 'react';

export default function WahRunner() {
  useEffect(() => {
    import('web-audit-helper')
      .then(({ runWAH }) => runWAH())
      .catch(console.error);
  }, []);
  return null;
}

See the Next.js / SSR Frameworks section for complete examples.

WAH runs twice in development (React Strict Mode)

Cause: React Strict Mode intentionally double-invokes useEffect in development to detect side effects.

Solution: Use a useRef guard:

const ran = useRef(false);

useEffect(() => {
  if (ran.current) return;
  ran.current = true;
  
  import('web-audit-helper')
    .then(({ runWAH }) => runWAH())
    .catch(console.error);
}, []);

Issues detected vary between page refresh (F5) and re-run button

Cause: DOM state may differ between fresh page load and re-audit after dynamic changes.

Solution: Use __WAH_RERUN__() after significant DOM changes, or refresh the page (F5) for a clean audit.


🧪 Testing

npm run test        # Run tests once
npm run test:watch  # Watch mode
npm run test:ui     # Interactive UI

🤝 Contributing

We welcome contributions! Please read Contributing Guide and Guia de Contribucion for guidelines on:

  • Reporting issues
  • Submitting pull requests
  • Adding new rules
  • Code style and conventions

📋 Roadmap

Current and future roadmap is maintained in:

Release-by-release historical details are maintained in:


📄 License

MIT – See LICENSE for details