Skip to content
xwebanalysisPublic

About

Web quality auditor — Core Web Vitals, WCAG, structured data

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Tengu

Web quality auditor — Performance, SEO, Accessibility, Best Practices

Tengu : XWA submodule focused on web quality auditing


Overview

Tengu is a web quality auditor that evaluates web applications across four dimensions:

Category Scope
Performance Page weight, Core Web Vitals (LCP, CLS, INP), resource waterfall, image optimization, font loading, cache policy, compression, third-party impact
SEO Title tags, meta descriptions, heading hierarchy, canonical URLs, Open Graph, Twitter Cards, JSON-LD, sitemaps, robots.txt, hreflang, redirect chains, broken links
Accessibility Alt text, heading structure, ARIA attributes, landmarks, color contrast (WCAG AA/AAA), keyboard navigation, form labels, link text, tables, iframes, viewport configuration
Best Practices HTTPS enforcement, security headers (HSTS, CSP, XFO, etc.), cookie audit, GDPR banner detection, doctype validation, deprecated HTML, mixed content, SRI, console errors

Local-first: SQLite persistence by default, no external services required. The backend is Python 3.12+ (FastAPI + httpx + BeautifulSoup/lxml).

Quick Start

Native (no Docker) — recommended

./tengu.sh            # same as: ./tengu.sh local

Starts the Python backend on http://localhost:8070 with a SQLite database at <repo>/tengu.db and serves the prebuilt Angular frontend when present (static/browser/ or frontend/dist/). The script uses uv to create the backend environment on first run; install it with:

curl -LsSf https://astral.sh/uv/install.sh | sh

Python directly

cd backend
uv sync
TENGU_DB_PATH=/tmp/tengu.db uv run python -m tengu --port 8070

Frontend (development)

The SPA is Angular 22 (standalone, zoneless, TypeScript 6, @angular/build, Vitest). Node 24 is required.

export PATH="$HOME/.local/share/mise/installs/node/24/bin:$PATH"
cd frontend
npm ci                        # reproducible install from package-lock.json
npm test                      # Vitest unit tests (api, WS Event parsing, severity, exports)
npm run build                 # production build -> ../static (outputHashing: none)
npm start                     # dev server on :4270, talks to :8070

The production build is written to <repo>/static/browser and served by the FastAPI SPA fallback (STATIC_DIR). outputHashing: none keeps main.js/styles.css stable so the backend can serve them without a manifest. The backend never compiles the frontend; use ./tengu.sh build or the npm commands above.

Docker Compose

docker compose up -d --build

Web UI and API: http://localhost:8070. The SQLite database lives in the tengu_data volume at /data/tengu.db.

Launch Script

./tengu.sh                        # local (default): SQLite native, :8070
./tengu.sh local                  # explicit local mode
./tengu.sh docker                 # docker compose (persistent volume)
./tengu.sh docker --rm            # ephemeral container
./tengu.sh build                  # build frontend only
./tengu.sh export [file]          # start + export audits to ./exports/
./tengu.sh import <file>          # start + import audits from file
./tengu.sh clean                  # delegate to ./clean.sh
./tengu.sh -b                     # force frontend rebuild before starting

The script prefers Node 24 from mise (~/.local/share/mise/installs/node/24/bin) when building the frontend. It runs npm ci (falling back to npm install only if the lockfile is missing) when frontend/node_modules is absent.

Environment Variables

Variable Default Description
PORT 8070 HTTP listen port (XWA standard)
STATIC_DIR static/browser Directory served by the SPA fallback
TENGU_DB_PATH tengu.db (/data/tengu.db in Docker) SQLite database file
TENGU_MAX_HISTORY 100 Maximum persisted audits (retention)
TENGU_API_KEY — Optional API key (X-API-Key or Authorization: Bearer)
TENGU_HTTP_TIMEOUT 30 HTTP client timeout (seconds)
TENGU_HTTP_MAX_REDIRECTS 10 Redirect limit
TENGU_HTTP_RETRY 2 Retries with exponential backoff + jitter
TENGU_USER_AGENT Tengu/0.2.0 (+https://github.com/xwebanalysis/tengu) Crawler user agent
TENGU_RATE_LIMIT_PER_MINUTE 120 REST + WS token bucket rate
TENGU_RATE_LIMIT_BURST 30 Token bucket burst
TENGU_MAX_CONCURRENT 3 Concurrent audits
TENGU_MAX_PAGES 50 Maximum pages per full-site crawl
TENGU_CRAWL_DEPTH 2 Crawl depth from the entry URL
TENGU_CRAWL_DELAY_MIN_MS / _MAX_MS 200 / 800 Delay with jitter between crawl requests
TENGU_ROBOTS_TXT 1 Respect robots.txt during crawls (0 disables)
XWA_CORS_ORIGINS localhost/LAN Comma-separated allowed origins (credentials always disabled)

API Endpoints

Method Path Description
GET /api/health JSON health: {"status","service","version","database"}
GET /api/metrics Prometheus text metrics
GET /api/audit/live WebSocket streaming xwa-sdk Event envelopes
GET /api/audits List persisted audits (legacy shape)
GET /api/audits/{id} Get an audit (legacy shape)
DELETE /api/audits/{id} Delete an audit
DELETE /api/audits/clear Clear all audits
GET /api/audits/export Export all audits as JSON
POST /api/audits/import Import audits from JSON
GET /api/analyses List analyses as xwa-sdk Analysis
GET /api/analyses/{id} Analysis + findings (xwa-sdk contract)
DELETE /api/analyses/{id} Delete an analysis
GET /api/analyses/{id}/export?format=json|csv Download analysis (Content-Disposition)

WebSocket Protocol (xwa-sdk Event)

GET /api/audit/live?url=<target>&mode=<single|fullsite|batch>&checks=...

Every frame is a JSON Event from xwa-sdk 0.2.0:

{
  "seq": 3,
  "type": "item_found",
  "tool": "tengu",
  "analysis_id": "df2c…",
  "ts": "2026-09-12T10:00:00Z",
  "payload": {
    "tool": "tengu",
    "severity": "medium",
    "title": "Missing alt attribute",
    "description": "…",
    "category": "accessibility",
    "check": "alt_text",
    "target_url": "https://example.com/",
    "evidence": {"snippet": "<img src=\"…\">"}
  }
}

Event flow: analysis_started → analysis_progress* → item_found* → log (pretty-printed HTML source) → analysis_completed (with summary) or analysis_error (with the xwa-sdk error envelope).

Severity mapping: Pass → pass, Info → info, Warning → medium, Error → high. The Angular client parses every frame with parseEvent() (frontend/src/app/core/events.ts) and rebuilds exactly what the legacy text protocol provided: meta/log lines in the terminal, crawled pages from [PAGE] <url> progress messages, findings from item_found, the pretty HTML from the log/html_source payload (data.html), and completion/error state from analysis_completed/analysis_error.

Respectful Crawling

Full-site mode honors robots.txt by default, paces requests with a random 200–800 ms delay, caps the crawl with TENGU_MAX_PAGES/TENGU_CRAWL_DEPTH, and retries transient failures with exponential backoff + jitter.

Project Structure

tengu/
├── backend/
│   ├── pyproject.toml       # Python 3.12+ dependencies (uv)
│   ├── uv.lock              # Reproducible backend environment
│   ├── tengu/
│   │   ├── main.py          # CLI entry point
│   │   ├── api.py           # FastAPI REST + WebSocket + SPA fallback
│   │   ├── config.py        # Environment configuration
│   │   ├── models.py        # xwa-sdk 0.2.0 contracts
│   │   ├── storage.py       # SQLite persistence (legacy schema compatible)
│   │   ├── events.py        # xwa-sdk Event emitter
│   │   ├── http.py          # httpx client, retries, robots/crawl/batch
│   │   └── audit/           # Performance, SEO, a11y, best-practices engines
│   └── tests/               # pytest suite (API, WS, storage, auditors)
├── frontend/                # Angular 22 SPA (zoneless, Nothing Design, Vitest)
│   ├── src/app/core/        # api, ws/event parsing, theme, i18n, exports
│   ├── src/app/shared/      # terminal, html-viewer, metric-card, tags, exports
│   └── src/app/features/    # audit, history
├── docs/                    # Technical documentation
├── Dockerfile               # Multi-stage Python + Angular build
├── docker-compose.yml       # Single service with persistent SQLite volume
├── tengu.sh                 # Local-first launch script (uv + Python)
└── clean.sh                 # Local + Docker cleanup (removes tengu.db*)

Backend Dependencies

FastAPI, Uvicorn, httpx, BeautifulSoup 4, lxml, and the Python standard library sqlite3. The backend is managed by uv; see backend/pyproject.toml and docs/python-libraries.md.

Related Documents

Document Description
docs/manual.md Deployment and usage manual
docs/ui-architecture.md Frontend architecture overview
docs/python-libraries.md Python backend dependency inventory
ROADMAP.md Development phases and milestones
CHANGELOG.md Release history and version log
SECURITY.md Security policy and reporting

X

X Web & X Github Profile & Xscriptor web

License

Proprietary — All rights reserved. See LICENSE for the full terms. For permission requests: x@xscriptor.com

About

Web quality auditor — Core Web Vitals, WCAG, structured data

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages