Find what Lighthouse misses before your users do.

metaweave checks the things you usually discover after deploying: a missing og:image, a favicon that 404s, a leftover noindex, a robots.txt that blocks everything. One command, 71 checks, plain-language fixes.

Built for the checks nobody remembers

Beyond LighthouseLighthouse is great at speed and basic SEO. It will not tell you that your share image is 404, your canonical points at localhost or your sitemap lists the staging domain.

Before productionPoint it at localhost:3000 or a preview deploy. Checks that only make sense on a live site are skipped for local servers, so you don't get noise.

Fixes, not just flagsEvery finding says what is wrong and how to fix it. metaweave explain tells you why the check exists.

Install

metaweave is a single binary written in Rust. You need Rust 1.85 or newer.

# install straight from GitHub
cargo install --git https://github.com/nazimcanislam/metaweave

# or build from a clone
git clone https://github.com/nazimcanislam/metaweave
cd metaweave
cargo install --path .

Shell completions: metaweave completions bash (also zsh, fish, powershell, elvish).

Usage

# check a live page, or your dev server (http is assumed for localhost)
metaweave https://example.com
metaweave localhost:3000

# several pages in one run; site-wide checks run once per origin
metaweave example.com example.com/pricing example.com/blog

# focus on some areas, or silence checks you don't care about
metaweave example.com --only seo,social,assets
metaweave example.com --skip links --ignore 'sec/*' -i seo/h1

# learn about a check
metaweave explain og-image

Options

Option What it does
-f, --format text (default), json or markdown
--only / --skip Comma-separated categories: seo, social, a11y, perf, sec, assets, links, html
-i, --ignore Silence checks by id; prefixes like sec/* work
--fail-on Exit with 1 at this severity or above: error (default), warning, info, never
--max-links How many links to verify (default 100)
--timeout Per-request timeout in seconds (default 15)
--insecure Accept self-signed certificates on dev or staging servers
-v / -q List passed checks / show only errors and warnings
--no-color Plain output; NO_COLOR is respected too

Exit codes

0 nothing at or above --fail-on · 1 findings at or above it · 2 a page could not be fetched or an argument was invalid.

What it checks

71 checks in eight categories. Each has an id you can pass to --ignore or metaweave explain. Checks that need extra requests (icons, robots.txt, links…) run in parallel.

SEO8 checks
seo/title
Document has a <title> of a sensible length (10–60 chars)The title is the headline in search results and browser tabs; long titles get truncated.
seo/description
Meta description is present and 50–160 charsSearch engines use it as the result snippet; auto-generated ones are often poor.
seo/canonical
Canonical URL is declared, absolute and points at the right hostPrevents duplicate content and stops localhost/staging URLs from leaking into search.
seo/h1
Page has exactly one <h1>The h1 tells users and crawlers what the page is about.
seo/indexable
Page is not blocked from indexing (noindex)A leftover noindex from staging silently removes the page from search results.
seo/structured-data
JSON-LD structured data is present and valid JSONStructured data enables rich results (breadcrumbs, articles, products, FAQs).
seo/viewport
Responsive viewport meta tag is setWithout it mobile browsers render a zoomed-out desktop page; Google indexes mobile-first.
seo/link-text
Links use descriptive text (no “click here”)Generic link text carries no meaning for crawlers or screen-reader users.
Social previews10 checks
social/og-title
og:title is setIt is the headline of link previews on Facebook, LinkedIn, Slack, WhatsApp, Discord…
social/og-description
og:description is setIt provides the preview text shown under the title.
social/og-image
og:image is set to an absolute, public URLPosts without an image get far less attention; relative or localhost URLs can't be fetched by crawlers.
social/og-image-alt
og:image:alt describes the preview imageAlt text makes link previews accessible on platforms that support it.
social/og-url
og:url is set and matches the canonical URLIt tells platforms which URL to attribute likes and shares to.
social/og-type
og:type is setIt defines how the page is represented (website, article, product…).
social/og-site-name
og:site_name is setIt shows the brand name next to the preview on some platforms.
social/og-image-reachable
og:image URL is reachable and is an imageA 404 or HTML response means the preview card silently has no picture.
social/og-image-size
og:image has a suitable format and size (1200×630 recommended)Small or oddly shaped images are cropped, blurry or ignored; SVG is unsupported.
social/twitter-card
twitter:card is set to a valid valueX/Twitter needs twitter:card to render a rich preview; other tags fall back to Open Graph.
Accessibility13 checks
a11y/lang
<html> has a valid lang attributeScreen readers pick pronunciation rules from it; browsers use it for translation and hyphenation.
a11y/img-alt
Every <img> has an alt attributeWithout alt, screen readers read out the file name and blind users miss the content.
a11y/link-name
Every link has an accessible nameIcon-only or empty links are announced as just “link”.
a11y/button-name
Every button has an accessible nameUnlabelled buttons are unusable with a screen reader.
a11y/form-label
Every form field has a labelPlaceholders disappear and are not labels; unlabelled fields can't be identified by assistive tech.
a11y/heading-order
Headings are non-empty and do not skip levelsScreen-reader users navigate by headings; skipped levels break the outline.
a11y/viewport-zoom
Pinch-zoom is not disabledUsers with low vision rely on zooming.
a11y/duplicate-id
id attributes are uniqueDuplicate ids break label associations, anchors and ARIA references.
a11y/landmarks
Page has a <main> landmarkLandmarks let assistive-tech users jump straight to the content.
a11y/iframe-title
Every <iframe> has a titleThe title tells screen-reader users what the frame contains.
a11y/video-captions
Videos provide captions or subtitlesDeaf and hard-of-hearing users need captions (WCAG 1.2.2).
a11y/tabindex
No positive tabindex valuesPositive tabindex overrides the natural focus order and confuses keyboard users.
a11y/skip-link
A “skip to content” link is availableKeyboard users otherwise tab through the whole navigation on every page.
Performance11 checks
perf/ttfb
Server responds quickly (TTFB ≤ 600 ms)A slow first byte delays everything else, including Largest Contentful Paint.
perf/html-size
HTML document is lean (< 100 KB)Large HTML delays parsing and first render.
perf/compression
HTML is served compressed (gzip/brotli/zstd)Compression typically cuts text transfer by 70% or more.
perf/redirects
Page is reached without redirect chainsEach redirect adds a full round trip before content starts loading.
perf/render-blocking
Scripts in <head> are async, defer or modulesSynchronous scripts block HTML parsing and delay first paint.
perf/img-dimensions
Images declare width and heightWithout dimensions the layout jumps when images load (Cumulative Layout Shift).
perf/img-lazy
Below-the-fold images are lazy-loadedLazy loading saves bandwidth and speeds up the initial render.
perf/img-format
Modern image formats (WebP/AVIF/SVG) are usedWebP and AVIF are often 25–50% smaller than JPEG/PNG.
perf/dom-size
DOM is reasonably small (< 1500 elements)Large DOMs slow down style calculation, layout and memory use.
perf/cache-headers
Static assets have cache headersWithout caching, repeat visits re-download every file.
perf/img-weight
Images are reasonably sized (< 500 KB each)Oversized images are the most common cause of slow pages.
Security12 checks
sec/https
Site is served over HTTPS and http:// redirects to itHTTPS protects users and is required for many modern browser features.
sec/hsts
Strict-Transport-Security is set (max-age ≥ 6 months)HSTS prevents downgrade attacks by forcing HTTPS.
sec/csp
Content-Security-Policy is set and avoids unsafe-inlineCSP is the strongest defence against cross-site scripting.
sec/nosniff
X-Content-Type-Options: nosniff is setIt stops browsers from MIME-sniffing responses into executable types.
sec/frame-protection
Clickjacking protection (frame-ancestors / X-Frame-Options)It stops other sites from embedding your pages in invisible frames.
sec/referrer-policy
Referrer-Policy is setIt controls how much URL information leaks to other sites.
sec/permissions-policy
Permissions-Policy is setIt disables powerful features (camera, geolocation…) you don't use.
sec/mixed-content
No http:// subresources on HTTPS pagesBrowsers block or warn about mixed content, breaking images and scripts.
sec/sri
Third-party scripts and styles use Subresource IntegritySRI ensures a compromised CDN can't inject malicious code into your page.
sec/target-blank
target="_blank" links use rel="noopener"Older browsers give the opened page access to window.opener.
sec/cookies
Cookies set Secure, HttpOnly and SameSiteThese flags protect session cookies from theft and CSRF.
sec/server-header
Server headers don't reveal software versionsVersion banners help attackers target known vulnerabilities.
Site files & icons7 checks
assets/favicon
Favicon is declared and reachableA missing favicon shows a blank tab icon and fills server logs with 404s.
assets/apple-touch-icon
Apple touch icon (180×180) is availableIt is used when people add your site to the iOS home screen.
assets/manifest
Web app manifest is valid (name, 192/512 icons)It is needed for installable PWAs and good Android home-screen icons.
assets/theme-color
theme-color meta tag is setIt tints the browser UI on mobile to match your brand.
assets/robots-txt
robots.txt exists and doesn't block everythingA leftover “Disallow: /” from staging removes the whole site from search.
assets/sitemap
sitemap.xml exists, is valid and lists production URLsIt helps crawlers discover pages; wrong hosts mean staging URLs get indexed.
assets/not-found-page
Unknown URLs return a real 404 statusSoft 404s (200 on missing pages) confuse search engines and monitoring.
Links & resources5 checks
links/internal
Internal links resolve without errorsBroken links hurt users and SEO.
links/external
External links are aliveDead outbound links make a site look abandoned.
links/resources
Images, scripts and stylesheets loadA 404 resource means a broken layout or missing functionality.
links/anchors
#fragment links point to existing idsBroken in-page anchors silently do nothing.
links/placeholder
No placeholder links (href="#" or javascript:)They aren't real links: inaccessible, and they break middle-click and open-in-new-tab.
HTML hygiene5 checks
html/status
Page responds with a 2xx statusError pages are not indexed and usually indicate a broken deploy.
html/doctype
Document starts with <!DOCTYPE html>Without it browsers fall into quirks mode with inconsistent rendering.
html/charset
Character encoding is declared as UTF-8Otherwise special characters (ş, ğ, ü, é, emoji…) may render as garbage.
html/deprecated
No obsolete HTML elementsTags like font, center and marquee are unsupported or discouraged.
html/meta-refresh
No <meta http-equiv="refresh"> redirectsMeta refresh is slow and bad for accessibility and SEO.

Run it in CI

Fail the build when a preview deploy has errors, and put the Markdown report on the job summary:

- name: Check the preview deploy
  run: |
    metaweave "$PREVIEW_URL" -f markdown --fail-on error | tee -a "$GITHUB_STEP_SUMMARY"

Use -f json when you want to post-process the results. Each finding has an id, a severity, a message and a fix.