All 25 checks with why-it-matters prose, severity, and cross-references to related audits.
Serving over HTTP exposes every request to network-level eavesdropping and man-in-the-middle attacks — credentials, session cookies, and form data transit in plaintext. OWASP A02 (Cryptographic Failures) and NIST SP 800-53 SC-8 both cite unencrypted transport as a baseline failure. Beyond confidentiality, modern browsers mark HTTP pages as 'Not Secure', and Google penalizes them in search rankings. Sites that accept HTTP alongside HTTPS without redirecting give attackers a trivial downgrade path: intercept a single HTTP request, strip the redirect, and own the session. CWE-319 directly captures this: cleartext transmission of sensitive information.
Why this severity: Critical because plaintext HTTP exposes credentials, cookies, and form payloads to any network observer without requiring any exploit beyond passive interception.
site-health-check.security-posture.https-enforcedSee full patternWithout HSTS, browsers will happily downgrade to HTTP on any request where the redirect is absent or stripped — a trivial attack on public Wi-Fi. HSTS instructs browsers to refuse HTTP connections entirely for the specified duration, eliminating the window where a man-in-the-middle can intercept the initial plaintext request. NIST SP 800-53 SC-8 and OWASP A02 (Cryptographic Failures) both flag the absence of HSTS as a transport security gap. A `max-age` below one year (31536000 seconds) leaves users exposed for shorter periods after each visit — insufficient to meaningfully protect repeat visitors. CWE-311 captures the failure: missing encryption of sensitive data in transit.
Why this severity: High because a missing or short-lived HSTS header leaves a downgrade window open on every first visit or after the max-age expires, enabling interception without any vulnerability in the application itself.
site-health-check.security-posture.hsts-headerSee full patternWithout a Content Security Policy, browsers trust every script origin a page loads — including any injected by XSS. An attacker who finds a single injection point can exfiltrate session cookies, rewrite page content, or silently redirect users, because there is no browser-enforced allowlist to stop arbitrary script execution. OWASP A03 (Injection) and CWE-79 (Cross-Site Scripting) both identify missing CSP as a failure to implement available defenses. A `Content-Security-Policy-Report-Only` header monitors but enforces nothing — it does not satisfy this check. Even a minimal CSP with `default-src 'self'` eliminates an entire class of exfiltration attacks by blocking off-origin resource loads.
Why this severity: High because the absence of an enforcing CSP leaves XSS attacks completely unrestricted — any injection vulnerability directly enables session hijacking, credential theft, or defacement.
site-health-check.security-posture.csp-headerSee full patternBrowsers with MIME sniffing enabled attempt to guess a file's content type by reading its bytes, ignoring the `Content-Type` header. Attackers exploit this to serve malicious payloads in files uploaded or hosted as innocuous types — a file labeled `text/plain` containing JavaScript can be executed as a script. This crosses directly into CWE-79 (XSS) territory and OWASP A03 (Injection). The `X-Content-Type-Options: nosniff` header is a single-line fix that disables this guessing. It costs nothing to send and eliminates an entire class of content-type confusion attacks on every browser that honors it, which is all major browsers.
Why this severity: Low because MIME sniffing attacks require an attacker-controlled upload or hosting vector, making exploitation dependent on other weaknesses being present first.
site-health-check.security-posture.x-content-type-optionsSee full patternClickjacking embeds your site invisibly inside an attacker-controlled iframe. A user sees the attacker's page, but their clicks land on your site's buttons — authorizing transfers, changing account settings, or submitting forms without knowing. CWE-1021 (UI Redress Attack) and OWASP A05 (Security Misconfiguration) both classify missing frame protection as a preventable failure. The fix is cheap: one header. Without it, any page on your site that performs sensitive actions is vulnerable to this class of social-engineering attack targeting legitimate authenticated sessions.
Why this severity: Low because clickjacking requires the victim to be tricked into visiting a malicious page, reducing realistic attack surface, but zero mitigation headers make it trivially exploitable when targeted.
site-health-check.security-posture.frame-protectionSee full patternThe title tag is the single most weighted on-page signal Google uses to rank and display your page. A missing, placeholder, or truncated title means search result listings show the URL or an auto-generated fragment, tanking click-through rate and destroying findability for branded and unbranded queries alike. Shipping with defaults like "React App" or "Create Next App" signals an abandoned or unfinished site to both users and crawlers.
Why this severity: High because a broken title directly suppresses organic search visibility and click-through for every indexed page.
site-health-check.seo-discoverability.title-tagSee full patternWithout a meta description, Google synthesizes a snippet from scraped page text — usually the first paragraph or a nav fragment — which rarely matches searcher intent and costs measurable click-through rate. A present but default-placeholder description like "Web site created using create-react-app" is worse: it broadcasts that nobody finished the site, which users read as a trust signal before they click. Findability depends on controlling that snippet.
Why this severity: High because the description drives CTR on every search impression and defaults broadcast abandonment.
site-health-check.seo-discoverability.meta-descriptionSee full patternWhen a URL is pasted into Slack, Discord, LinkedIn, X, or iMessage, the preview card is generated entirely from Open Graph tags. Without `og:title` and `og:description`, shared links render as a naked URL with no thumbnail — dramatically lowering click-through on the most common viral distribution channel. This is findability via social graph rather than search, and it costs nothing to fix but directly gates every shared-link impression.
Why this severity: Medium because the impact is limited to social-share surfaces rather than search ranking, but preview collapse kills CTR.
site-health-check.seo-discoverability.open-graphSee full patternWithout a canonical URL, Google treats `https://example.com/page`, `https://www.example.com/page`, and `https://example.com/page?utm_source=x` as three separate URLs competing for the same ranking slot. Link equity fragments across variants, duplicate-content filters kick in, and the version Google indexes is nondeterministic. A canonical tag consolidates signals to one preferred URL and eliminates an entire class of ranking self-harm.
Why this severity: Medium because duplicate-content dilution degrades rankings over time but rarely triggers a hard penalty on its own.
site-health-check.seo-discoverability.canonical-urlSee full patternGooglebot, Bingbot, and every AI-crawler (GPTBot, ClaudeBot, PerplexityBot) check `robots.txt` first to learn what they're allowed to fetch, and they discover deep URLs through `sitemap.xml`. Missing both forces crawlers to spider links one hop at a time from the homepage, which means deep pages get crawled late or not at all. For GEO (Generative Engine Optimization), an unreachable sitemap means your pages don't make it into AI answer sets.
Why this severity: Info because crawlers will eventually find most pages anyway, but missing files slow indexing and hurt AI discoverability.
site-health-check.seo-discoverability.robots-sitemapSee full patternUncompressed HTML, CSS, and JavaScript responses force users to download 3–5x more bytes than necessary. For a 200 KB uncompressed page, enabling Brotli or gzip typically reduces transfer to 40–80 KB — a direct reduction in time-to-interactive, especially on mobile connections. ISO 25010 performance-efficiency is directly impacted: slow load times increase bounce rate, hurt Core Web Vitals scores, and degrade SEO rankings. Compression is a server-side toggle that costs negligible CPU and delivers guaranteed bandwidth savings. Its absence signals misconfigured infrastructure rather than an intentional choice.
Why this severity: High because missing compression directly increases page load time by 3–5x for text assets, with measurable impact on Core Web Vitals, bounce rate, and SEO rankings on every page load.
site-health-check.performance-signals.compression-enabledSee full patternGoogle's research shows 53% of mobile users abandon pages that take over 3 seconds to load. Response time directly determines first-byte latency — everything else (rendering, JavaScript hydration, asset loading) starts after this baseline. A server that takes 4 seconds to respond has wasted the entire user's attention budget before a single pixel renders. ISO 25010 performance-efficiency captures this: response time is the most fundamental performance metric because it gates every subsequent interaction. Slow response times also hurt Lighthouse performance scores and Core Web Vitals, compounding SEO and conversion impact.
Why this severity: Critical because a response time over 3 seconds causes majority user abandonment before the page renders, making the site effectively unusable for a large share of real-world visitors.
site-health-check.performance-signals.response-timeSee full patternWithout `Cache-Control` headers, browsers fall back to heuristic caching — typically caching responses for 10% of their apparent age, or not at all. Every repeat visitor re-downloads content that hasn't changed, wasting bandwidth and adding latency on every navigation. Properly configured caching reduces server load, speeds up repeat visits, and improves CDN hit rates. ISO 25010 performance-efficiency identifies caching as a core mechanism for resource utilization. The absence of cache headers forces both browsers and CDNs into conservative or undefined behavior, leaving significant performance on the table.
Why this severity: Medium because missing cache headers cause preventable latency on repeat visits and increase server load, but the site remains functional — users are slowed, not blocked.
site-health-check.performance-signals.cache-headersSee full patternImages are typically the largest assets on a page. Without lazy loading, every image below the fold downloads on initial page load — including images the user may never scroll to. On an image-heavy page, this can add multiple megabytes to the initial payload, directly increasing Time to Interactive. ISO 25010 performance-efficiency applies: loading offscreen resources wastes bandwidth and delays rendering of visible content. The `loading='lazy'` attribute is a native browser feature with no JavaScript dependency, universally supported in modern browsers, and requires zero additional infrastructure to use.
Why this severity: Info because the performance cost depends on image count and sizes — pages with few or small images see negligible impact, making this an optimization opportunity rather than a guaranteed defect.
site-health-check.performance-signals.lazy-loadingSee full patternSynchronous scripts in `<head>` block the HTML parser — the browser stops building the DOM and waits for each script to download, parse, and execute before continuing. On slow connections, 8+ blocking scripts can add multiple seconds to Time to First Paint. ISO 25010 performance-efficiency identifies render-blocking as a direct impairment to perceived responsiveness. The fix is attribute-level: adding `defer` or `async` costs nothing and eliminates the blocking behavior. Scripts that lack these attributes are typically there by accident — legacy integrations, copy-pasted snippets, or tools that don't set them by default.
Why this severity: Info because the actual impact depends on script count and sizes — a single small inline script is negligible, but this rating reflects the pattern rather than guaranteed high cost.
site-health-check.performance-signals.minimal-blockingSee full patternWithout `<meta name="viewport" content="width=device-width">`, mobile browsers render the page at desktop width (typically 980px) and scale it down — text becomes unreadable, tap targets become too small, and users must pinch-zoom to navigate. WCAG 2.2 SC 1.4.4 (Resize Text) requires content to remain usable when scaled to 200%, and section 508 requires equivalent mobile access. Setting `user-scalable=no` or `maximum-scale=1` blocks pinch-to-zoom entirely, which is an accessibility violation that fails WCAG 1.4.4 — a separate and more serious defect than a missing viewport tag.
Why this severity: High because a missing viewport meta tag renders the entire page unusable on mobile devices — content appears at desktop scale with no readable text or functional tap targets.
site-health-check.accessibility-mobile.viewport-metaSee full patternScreen readers depend on the `lang` attribute to select the correct language engine for text-to-speech pronunciation. Without it, a screen reader may attempt to pronounce English content using French or Japanese pronunciation rules — producing incomprehensible audio for users who are blind or have low vision. WCAG 2.2 SC 3.1.1 (Language of Page) is a Level A requirement: the lowest, most foundational conformance level. Section 508 (2018 refresh) 504.2 also mandates language identification. A missing `lang` attribute is an automatic WCAG failure that makes the page non-compliant with accessibility law in the US, EU, and most jurisdictions.
Why this severity: Medium because the impact is targeted — screen reader users bear the full cost of incorrect language detection, while sighted users are unaffected — but it represents a clear WCAG Level A failure.
site-health-check.accessibility-mobile.html-langSee full patternScreen reader users navigate pages by jumping between headings — it is their primary orientation mechanism on unfamiliar content. A missing `<h1>` leaves no entry point. Heading levels that skip (h1 directly to h3) break the expected hierarchy, causing confusion about content relationships. WCAG 2.2 SC 1.3.1 (Info and Relationships) requires structural information to be programmatically determinable, and SC 2.4.6 (Headings and Labels) requires headings to describe their section. Improper heading structure also confuses search engine crawlers, which use heading hierarchy to understand page topic and section weight.
Why this severity: Medium because heading structure failures directly impair screen reader navigation — the most common assistive technology orientation mechanism — but the page remains technically operable for sighted users.
site-health-check.accessibility-mobile.heading-hierarchySee full patternScreen readers announce images using the `alt` attribute. When `alt` is absent entirely — not empty, but missing — most screen readers announce the image filename or URL instead, producing output like 'img-2847-final-v3.jpg' read aloud to a user who cannot see the image. WCAG 2.2 SC 1.1.1 (Non-text Content) is a Level A requirement that mandates text alternatives for all non-decorative images. Section 508 (2018 refresh) 504.2 applies the same obligation. An empty `alt=""` is correct for decorative images — it signals 'skip this.' The missing-attribute case is distinct and always a failure regardless of intent.
Why this severity: Info because missing alt text affects screen reader users specifically, but does not degrade the experience for sighted users — severity reflects targeted impact rather than universal failure.
site-health-check.accessibility-mobile.image-alt-textSee full patternHTML built entirely from `<div>` and `<span>` elements has no machine-readable meaning. Screen readers cannot distinguish navigation from content from footers — everything is an undifferentiated block. Semantic elements like `<nav>`, `<main>`, `<header>`, and `<footer>` expose ARIA landmark roles automatically, letting screen reader users jump directly to the content region they need. WCAG 2.2 SC 1.3.1 (Info and Relationships) and SC 4.1.2 (Name, Role, Value) both require structure to be programmatically determinable. Search engines also use semantic structure to understand page organization, affecting how content is indexed and ranked.
Why this severity: Info because semantic elements improve assistive technology navigation significantly but their absence does not prevent page functionality — the visual experience is unaffected for sighted users.
site-health-check.accessibility-mobile.semantic-htmlSee full patternThe default framework 404 page — Next.js's plain "404 | This page could not be found," nginx's white error screen, or a bare "Cannot GET /path" — breaks the site's visual identity at the worst possible moment: when a user has just hit a dead link and is deciding whether to leave. A custom 404 with navigation recovers the session; a default 404 bounces the user. It also signals an unfinished build to anyone who stumbles onto it.
Why this severity: Medium because default 404s directly increase bounce rate at dead links and erode perceived polish on every broken URL.
site-health-check.trust-polish.custom-404See full patternA missing favicon shows a generic document icon (or browser-default globe) in every browser tab, bookmark entry, history row, and pinned tab. When a user has five tabs open and yours is the only blank one, yours is the one they close. It's the cheapest trust signal on the web and the easiest to ship, which makes its absence a direct signal that the site was never taken past the MVP stage.
Why this severity: Info because the missing icon does not break functionality, but it visibly degrades brand presence in every browser surface.
site-health-check.trust-polish.faviconSee full patternGDPR Article 13 requires informing users about data collection at the point of collection. CCPA §1798.100 grants California residents the right to know what data is collected and to opt out — both rights are only exercisable if users can find your privacy policy. Beyond legal requirements, major ad networks (Google, Meta), payment processors (Stripe, PayPal), and app stores (Apple, Google) require a linked privacy policy to approve accounts and maintain access. Launching without visible legal links exposes the business to regulatory fines, platform bans, and loss of payment processing — not just reputational risk.
Why this severity: Critical because absent legal links constitute a regulatory compliance failure under GDPR and CCPA, and trigger automatic rejection or suspension by ad networks, app stores, and payment processors.
site-health-check.trust-polish.legal-linksSee full patternAn `<img src="">` or `<a href="">` is not a no-op — browsers resolve the empty string against the current document's URL and fire a second request for the page itself. That doubles server load on every page view, pollutes analytics with phantom pageviews, breaks Lighthouse audits, and in image contexts renders a broken-image placeholder users see. It's an AI-authored bug pattern: a conditional branch that forgot to drop the attribute when the value is missing.
Why this severity: Medium because empty attributes waste bandwidth, trigger self-referential page loads, and visibly break image and link rendering.
site-health-check.trust-polish.no-empty-srcSee full pattern"Lorem ipsum," "TODO," "[Your Company Name]," or "Coming soon" in shipped body copy tells every visitor — and every AI answer-engine scraping your page — that the site is unfinished. Conversion collapses on any page containing visible placeholder text, and GEO retrieval will happily quote the placeholder back in an AI answer card. This is the most unambiguous trust-killer in the check suite and the one users notice first.
Why this severity: Info in severity only because detection is probabilistic; actual user impact on trust and conversion is immediate and severe.
site-health-check.trust-polish.no-placeholder-contentSee full patternRun this audit in your AI coding tool (Claude Code, Cursor, Bolt, etc.) and submit results here for scoring and benchmarks.
Open Site Health Check