Instant, evidence-based website audits — every score backed by a real, live check.
This is the original work of Zelvior, open-sourced at github.com/zelvior/audityxe. Licensed under the custom Audityxe Custom Open-Source License — free to use, modify, and redistribute, provided Zelvior is always credited as the original author with a link back to the canonical repository. The software is provided as-is, with no warranty, and Zelvior is not responsible for anything arising from its use. Read
LICENSE.mdin full before forking, deploying, or redistributing.
- What Audityxe is
- What makes it different
- Audit engine: what actually gets checked
- Scoring model
- Exports
- Tech stack
- Getting started
- Environment variables
- PageSpeed Insights (Lighthouse) setup
- Payments (NOWPayments)
- Project structure
- Plans and limits
- Design system
- Scripts
- Deploying
- Contributing
- Security
- Credits
- License
Paste in a URL. Audityxe fetches the live page, scores it across six categories plus a large multi-area deep audit, attaches real evidence to every finding, hands back exact code fixes for the weakest spots, and packages the result into shareable social copy, a downloadable banner, an embeddable badge, and PDF/JSON/Markdown exports.
No crawl queue, no "results in 24 hours", no account required for your first audit.
| Typical audit tool | Audityxe | |
|---|---|---|
| Data source | Cached scans, screenshots, or an LLM guessing from a page description | Real HTTP requests made the moment you click Analyze |
| Reproducibility | Score drifts between runs | Deterministic — same page, same score |
| Evidence | "Improve your SEO" | The exact header, tag, DNS record, or selector that triggered the finding |
| Limits | Silently omits what it can't measure | States explicitly what it couldn't check, and excludes it from scoring |
| Storage | Full reports retained server-side | Nothing stored beyond a domain + score + date for the badge |
Every check below runs for free, with no paid third-party API, on every audit.
SEO & crawlability
- Title tag presence, length, and duplicate
<title>detection - Meta description presence and truncation risk
- Canonical tag presence and duplicate/conflicting canonical detection
- Heading hierarchy (single H1, logical H2/H3 order, duplicate heading text)
robots.txt— fetched live: existence, rules, blanket-disallow detection, sitemap cross-referencesitemap.xml— validity, URL count, freshness- Open Graph + Twitter Card completeness (
og:imageverified live,twitter:creator,twitter:image,fb:app_id) - JSON-LD structured data — parsed, validated, and typed (Organization, Product, Article, FAQPage, BreadcrumbList, LocalBusiness, WebSite)
- Broken internal links (live-sampled, not assumed)
AI Crawler Readiness (GEO)
Generative Engine Optimization — whether AI answer engines can read and cite the site, which is a different question from classic SEO:
- Named AI crawler blocking in
robots.txt(GPTBot, ChatGPT-User, ClaudeBot, Claude-Web, anthropic-ai, PerplexityBot, Google-Extended, CCBot, Bytespider, Applebot-Extended) llms.txtpresence and whether it has real contentX-Robots-TagHTTP header indexing blocks — invisible to any checker that only reads HTML- Conflicts between the header-level and meta-tag-level robots directives
noai/noimageaiAI-training opt-out signals
Security & headers
- Full security header audit: CSP (including
unsafe-inline/unsafe-eval/wildcard strength analysis), HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP/COEP/CORP, Clear-Site-Data - Per-cookie
Secure/HttpOnly/SameSiteflags, session vs persistent, tracking-cookie heuristics - CORS misconfiguration (wildcard origin, wildcard + credentials)
- Mixed content detection
- Server/
X-Powered-Byversion disclosure - Dangerous HTTP methods (safe, read-only probing)
- Exposed
.env,.git, and config-file scanning - Directory listing detection
- Subresource Integrity coverage on cross-origin scripts and stylesheets
- Publicly exposed JavaScript source maps
target="_blank"tabnabbing risk (missingrel="noopener")- Forms posting to insecure (
http://) endpoints
TLS & DNS
- Live TLS handshake: protocol version, cipher, issuer, validity window, days-to-expiry, self-signed detection, hostname match, SAN count, key type/size, weak-protocol flagging
- SPF, DKIM, DMARC email authentication records
- DNSSEC validation
- CAA certificate-issuance restriction records
- Subdomain takeover detection against 20+ known vulnerable service fingerprints
- Nameserver redundancy / zone health
security.txtvulnerability disclosure policy
Accessibility
- Image
altcoverage, plus generic/placeholder alt-text detection - Form input label association
- Button and link accessible names
- Generic link text detection ("click here", "read more")
- Keyboard focus visibility — flags CSS suppressing the focus outline with no visible replacement
- Skip-to-content link presence
<html lang>declaration- Landmark regions (
header/nav/main/footer) and content sectioning - Positive
tabindexmisuse,aria-hiddenon root elements <iframe>titles- Color-contrast heuristics
Performance & mobile
- Real browser-rendered Lighthouse pass via Google PageSpeed Insights (Core Web Vitals: LCP, CLS, TBT, FCP, Speed Index)
- Real-world CrUX field data when Google has enough traffic on the origin — distinguished from lab data
- Render Proof — the actual Chrome screenshot(s) Lighthouse captures, embedded in the report. Two independent captures (mobile viewport from the primary pass, desktop viewport from a small parallel best-effort call) are fetched, and the viewer's own device picks which renders via CSS — a phone gets the sharp native mobile capture, a desktop visitor gets the larger, higher-resolution desktop one, instead of one fixed low-res image stretched to fit everyone
- Compression, cache headers, image format/sizing/lazy-loading, inline-base64 bloat
- Render-blocking resources, web-font weight
- Viewport configuration, tap-target sizing, responsive-class signals
- Apple touch icons, web app manifest, Safari mask-icon
Content, UX & intelligence
- Flesch-Kincaid readability grade, reading time, duplicate heading detection
- Legal & trust page detection (privacy, terms, contact, refund, etc.) scored against detected site type
- Monetization signals (ad networks, affiliate links, payment processors, donation platforms, cart/checkout, pricing)
- Technical stack fingerprinting (framework, CMS, hosting, analytics, tag managers, chat widgets)
- AI-generated / "vibe-coded" pattern detection — emoji-heavy headings, buzzword density, em-dash frequency, stock gradient/blur/grain patterns, default font pairings, lorem ipsum
- Multi-page same-origin crawl: internal link graph, orphan pages, extended broken-link coverage
- HTML validity: doctype, duplicate IDs, deprecated tags, div-ratio, comment volume
Scores are deterministic, not model-generated.
- Each finding is
pass/warn/fail, with a severity (critical/high/medium/low). - A module's 0–10 score is
10 − (weighted severity loss / scored findings) × 10. - Unverifiable findings never affect the score. If a DNS lookup times out or PageSpeed Insights fails, that's recorded as "we couldn't check this" and excluded from the math — it is not scored as a failure.
- If every finding in a module is unverifiable, the module reports
—(not scored) rather than inventing a number from zero data. criticalfindings force a module tocriticalstatus regardless of the arithmetic.
| Format | Contents |
|---|---|
| Full branded report — score donut, category breakdown, every module and finding with evidence, Lighthouse lab + field data, embedded render screenshot | |
| JSON | Complete machine-readable payload — every module, finding, severity, confidence, and evidence string |
| Markdown | Copy-to-clipboard / download, for pasting into GitHub Issues, Notion, or a PR |
| Badge | Embeddable "Audited by Audityxe" SVG badge with live verification |
| Social | Auto-generated X/LinkedIn post copy and a downloadable share banner |
- Next.js 14 (App Router) · React 18 · TypeScript
- Tailwind CSS with a fully CSS-variable-driven token system
- Framer Motion for animation
- Firebase — Auth + Firestore (accounts, plans, badge records, admin config)
- lucide-react icons · jsPDF exports
- Google PageSpeed Insights API for the real-browser pass
- NOWPayments for crypto checkout
git clone https://github.com/zelvior/audityxe.git
cd audityxe
npm install
cp .env.example .env.local # fill in the values below
npm run devOpen http://localhost:3000.
Running an audit requires a signed-in, email-verified account, or
/api/auditwill reject every request with a 401/403. Create an account locally and verify it before testing.
| Variable | Required | Purpose |
|---|---|---|
.env.example is the single source of truth — it documents every variable |
||
| with click-by-click instructions for where to obtain each key, including the exact Google Cloud | ||
| setting that breaks PageSpeed Insights if you get it wrong. Start there: |
cp .env.example .env.localSummary:
| Variable | Required | Purpose |
|---|---|---|
NEXT_PUBLIC_FIREBASE_* (6 vars) |
✅ | Firebase web config — public by design |
FIREBASE_PROJECT_ID / FIREBASE_CLIENT_EMAIL / FIREBASE_PRIVATE_KEY |
✅ | Firebase Admin service account (secret) |
BYOK_ENCRYPTION_KEY |
✅ | Encrypts user-supplied API keys at rest |
IP_HASH_SALT |
✅ | Salts IP hashes for anonymous rate limiting (no raw IPs stored) |
PAGESPEED_API_KEY |
➖ | Lighthouse module. Without it PSI uses a shared quota that rate-limits hard |
AI_API_KEY / AI_BASE_URL / AI_MODEL |
➖ | Written verdict + promo copy. Scores never depend on this |
GEMINI_API_KEY / GEMINI_MODEL |
➖ | Alternative AI provider |
NOWPAYMENTS_API_KEY |
➖ | Enables crypto checkout |
NOWPAYMENTS_IPN_SECRET |
Mandatory if the API key is set — checkout refuses to start without it | |
NEXT_PUBLIC_DONATION_URL |
➖ | Footer Sponsor button target |
ADMIN_EMAILS / ADMIN_PASSWORD |
➖ | Enables /admin. Unset = admin panel disabled |
CRON_SECRET |
➖ | Protects /api/cron/* endpoints |
GOOGLE_SITE_VERIFICATION |
➖ | Search Console verification |
AUDITYXE_KILL_SWITCH / *_MESSAGE |
➖ | Emergency maintenance mode without redeploying code |
The Lighthouse module needs a Google API key. It's free, no billing required.
- Go to console.cloud.google.com and sign in.
- Create a new project via the project picker at the top.
- Enable the PageSpeed Insights API.
- Go to APIs & Services → Credentials → + Create Credentials → API key.
⚠️ Set "Application restrictions" toNone.
Why
Nonematters: an HTTP referrer restriction only validates requests that carry a browserRefererheader. Audityxe calls PSI server-side, which sends no referrer — so a referrer-restricted key is rejected with a 403 on every single request, permanently. An IP address restriction is also unsafe here, because serverless hosting uses non-fixed outbound IPs. This is enforced by Google's API gateway and cannot be worked around in application code.
Users can also add their own key in Settings, which is validated against the live API at save time and grants unlimited Lighthouse passes (their own Google quota) instead of the shared 1/week cap.
Crypto checkout uses the NOWPayments hosted invoice flow — NOWPayments hosts the currency picker, wallet address, QR code, and confirmation states, so no wallet address ever touches this codebase.
Flow:
POST /api/payments/nowpayments/create— authenticated; prices the plan server-side (never trusts a client-sent amount) and creates an invoice.- User is redirected to the NOWPayments hosted checkout.
- NOWPayments
POSTs status updates to/api/payments/nowpayments/ipn. - The webhook verifies the callback, then credits the plan.
Setup:
- Create a NOWPayments account and add a payout wallet.
- Copy your API key →
NOWPAYMENTS_API_KEY. - In Store Settings → Instant Payment Notifications, generate an IPN secret →
NOWPAYMENTS_IPN_SECRET. - Set the IPN callback URL to
https://your-domain.com/api/payments/nowpayments/ipn.
Also supported (see .env.example for full setup steps):
- Recurring subscriptions — monthly-only auto-renewal via NOWPayments' email-subscription flow (
/api/payments/nowpayments/subscribe, wired into the pricing page as "auto-renew monthly by email"). There is no annual tier — one recurring period, 30 days, matching the one-off price exactly. RequiresNOWPAYMENTS_EMAIL/NOWPAYMENTS_PASSWORD(subscription endpoints use a short-lived Bearer JWT minted on demand, not the API key directly) plus aNOWPAYMENTS_PLAN_STANDARD/NOWPAYMENTS_PLAN_PROplan id from the dashboard. - Donations —
/donateembeds the real NOWPayments donation widget viaNEXT_PUBLIC_NOWPAYMENTS_DONATION_KEY(a public, funds-safe key — not the same asNOWPAYMENTS_API_KEY). The footer's Sponsor button links there. The donation<iframe>requiresnowpayments.ioto be allowed in this app'sframe-srcContent-Security-Policy (next.config.js) — without it the browser blocks the widget outright with "This content is blocked." - Live payment status page —
/payment/statuspolls the app's own backend (never NOWPayments directly from the browser) every few seconds after checkout, showing "waiting for confirmation" until the IPN webhook actually credits the plan, then a clear confirmation. This is thesuccess_urlfor both one-off invoices and subscriptions. - Single price source of truth — all pricing (the pricing page, the manual "pay another way" email flow, and crypto checkout) reads from
PLANSinlib/plans.ts. There used to be a second, separate price table hardcoded in the NOWPayments integration that had silently drifted from the real advertised prices — fixed, and structurally can't drift again since there's only one table now.
Getting "INVALID_API_KEY" (HTTP 403) with a key that looks completely correct? This exact NOWPayments error message covers three different causes — see the full checklist in .env.example (API access must be separately enabled in dashboard Settings, a payout wallet must be configured, and sandbox keys are rejected by the production endpoint this app calls). The app also defensively trims the key value in case a stray newline was pasted into an env var.
Verified against multiple independent sources before shipping — the official NOWPayments Postman docs, their own nowpayments-sdk-nodejs GitHub repo, and their blog's subscriptions documentation all agree on the request field names and the IPN signing algorithm used here (JSON.stringify of a recursively key-sorted payload, HMAC-SHA512). This is as far as the integration can be verified without live credentials — see the warning below.
Security properties of the IPN handler:
- Signature is HMAC-SHA512 over the recursively key-sorted JSON payload, compared against the
x-nowpayments-sigheader using a constant-time comparison. - Verified against the raw request body — re-serializing a parsed object first can reorder keys and silently break verification.
- A missing IPN secret is a hard failure, never a skipped check. Without this, the endpoint would let anyone POST "payment finished" and grant themselves a paid plan.
- Crediting is idempotent and transactional — NOWPayments retries callbacks, so the payment ID is recorded and reprocessing is a no-op rather than stacking extra paid days.
- Paid time stacks onto remaining time rather than overwriting it.
- Transient Firestore failures return
500so NOWPayments retries, rather than silently swallowing a real payment.
⚠️ Verify before going live. Payment integrations must be tested against your own account. Run a small real payment end-to-end and confirm the plan is credited before accepting real money.
See the Refund Policy for refund handling, including why crypto refunds are sent as new transactions.
app/
api/
audit/ # the main audit endpoint
payments/
nowpayments/ # create invoice + IPN webhook
settings/ # account settings, BYOK key validation
admin/ # admin-only endpoints
(legal pages)/ # privacy, terms, license, refund-policy, credits, …
status/ # live service status
components/ # UI — all Tailwind token-driven, light/dark aware
lib/
analyze.ts # orchestrates a full audit
audit-modules.ts # turns signals into scored modules + findings
deep-signals.ts # HTML/DOM signal extraction
pagespeed.ts # PSI client, error translation, screenshot extraction
dns-security.ts # DNSSEC, CAA, subdomain takeover
dns-email-auth.ts # SPF, DKIM, DMARC
tls-check.ts # live TLS handshake inspection
nowpayments.ts # invoice creation + IPN HMAC verification
pdf-export.ts # PDF report builder
export-payload.ts # JSON report builder
| Free | Standard | Pro | |
|---|---|---|---|
| All 6 categories + full deep audit | ✅ | ✅ | ✅ |
| Daily audits | 2 | more | most |
| Competitor comparison | — | ✅ | ✅ |
| Bulk audit (up to 20 URLs) | — | — | ✅ |
| Real-browser Lighthouse pass | — | — | 1/week shared · unlimited with your own key |
Every plan runs the identical engine — nothing is dumbed down on Free.
- Palette: warm editorial — paper/rust, fully token-driven via CSS custom properties
- Light/dark: automatic, follows
prefers-color-scheme. No toggle, no flash, no JS - Type: Fraunces (display) + Public Sans (body)
- Motif: hand-drawn SVG underlines, highlights, and circles on key headings
- No shadows or glows — flat borders and background tints only
- Respects
prefers-reduced-motionthroughout
npm run dev # development server
npm run build # production build
npm run start # serve the production build
npx tsc --noEmit # type check
npx next lint # lintIssues and pull requests are welcome. Before opening a PR:
npx tsc --noEmit && npx next lint && npm run buildAll three must pass. Please keep new audit checks deterministic and evidence-backed — if a check can't state why it failed with a real artifact from the page, it doesn't belong in the engine.
Found a vulnerability? Please don't open a public issue. Email zelvior@proton.me directly.
Never commit .env.local, Firebase service-account keys, ENCRYPTION_KEY, or NOWPayments
credentials.
Audityxe is built on the work of many others — see the full Credits page for every tool, framework, font, and interactive-component source used, with attribution.
Audityxe Custom Open-Source License — use it, modify it, ship it, build a business on it. Just credit Zelvior as the original author, clearly and visibly, with a link back to github.com/zelvior/audityxe.