/seo-checker
Audit web pages for SEO issues in a real browser. Checks rendered meta tags, heading hierarchy, image alt text, structured data, canonical URLs, mobile rendering, and performance signals. Produces a scored report with specific findings and fixes. Read-only — inspects, doesn't
$ npx -y skills add hanzili/hanzi-browse --skill seo-checker --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/seo-checker
Context preview
The summary Claude sees to decide when to auto-load this skill.
Audit web pages for SEO issues in a real browser. Checks rendered meta tags, heading hierarchy, image alt text, structured data, canonical URLs, mobile rendering, and performance signals. Produces a scored report with specific findings and fixes. Read-only — inspects, doesn't
SKILL.md
seo-checker.SKILL.mdname: seo-checker
description: Audit web pages for SEO issues in a real browser. Checks rendered meta tags, heading hierarchy, image alt text, structured data, canonical URLs, mobile rendering, and performance signals. Produces a scored report with specific findings and fixes. Read-only — inspects, doesn't modify. Requires the hanzi browser automation MCP server and Chrome extension.
category: productivity
SEO Checker
You audit web pages for SEO issues using a real browser — rendered meta tags, actual heading structure, real schema markup, mobile viewport behavior. This skill is read-only: observe and report, don't modify.
Tool Selection Rule
- Prefer existing tools first (code search, local files, `curl`). Review HTML source, meta tags, and sitemap before opening the browser.
- Use Hanzi for Phase 2–5 — always open the browser for these phases even if Phase 1 found all static data. Do not substitute curl or WebFetch for browser phases.
Before Starting
Call `browser_status` to verify the extension is reachable. If unavailable, tell the user to install from: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
What You Need
1. **URL** — page or site to audit 2. **Scope** — single page, specific section, or full site (default: single page) 3. **Focus** — any specific SEO concerns (e.g., "we're not showing up in rich results", "mobile traffic dropped")
Audit Phases
Phase 1 — Source Review (before browser)
Check what you can without a browser:
- **Robots.txt**: Fetch `<domain>/robots.txt` — check for accidental `Disallow: /` or blocked important paths. Note: some sites serve different robots.txt to different user agents (UA sniffing). If the curl result looks suspicious or overly restrictive, verify with `browser_start` to see what a real browser receives.
- **Sitemap**: Fetch `<domain>/sitemap.xml` — verify it exists and includes the target URL
- **HTML source**: If accessible, review raw `<head>` for meta tags, canonical, hreflang
- **Codebase** (if source available): Scan for hardcoded noindex, missing meta tag templates, SEO component patterns
Summarize findings before opening the browser.
Phase 2 — Meta & Head Tags (browser)
Use `browser_start` to open the page and inspect the rendered DOM. JavaScript-rendered SPAs may have different meta tags than the raw HTML source.
- **Title tag**: Exists, 50-60 characters, unique, descriptive (not "Home" or "Untitled")
- **Meta description**: Exists, 150-160 characters, includes target keywords, compelling for CTR
- **Canonical URL**: Present, points to the correct URL (not a duplicate or wrong domain)
- **Robots meta**: Check for unintentional `noindex`, `nofollow`, or `none` directives
- **Open Graph tags**: `og:title`, `og:description`, `og:image`, `og:url` — all present and correct
- **Twitter Card tags**: `twitter:card`, `twitter:title`, `twitter:description`, `twitter:image`
- **Viewport meta**: `<meta name="viewport" content="width=device-width, initial-scale=1">` present
- **Charset & lang**: `<meta charset="utf-8">` and `<html lang="...">` set correctly
Screenshot the page after loading.
Phase 3 — Content Structure (browser)
- **H1 tag**: Exactly one per page, descriptive, contains primary keyword
- **Heading hierarchy**: H1 → H2 → H3 — no skipped levels (e.g., H1 → H3 with no H2)
- **Image alt text**: All meaningful images have descriptive alt text; decorative images use `alt=""`
- **Internal links**: Key pages are linked, anchor text is descriptive (not "click here")
- **Broken links**: Check for obvious 404s or dead links on the page
Phase 4 — Structured Data (browser)
- **JSON-LD / Microdata**: Check `<script type="application/ld+json">` blocks in the rendered DOM
- **Schema types**: Verify appropriate types are used (Article, Product, LocalBusiness, BreadcrumbList, FAQ, etc.)
- **Required properties**: Each schema type has required fields — check they're populated (e.g., Article needs `headline`, `datePublished`, `author`)
- **Validation**: Flag malformed JSON-LD or schemas with empty/placeholder values
Phase 5 — Mobile & Performance (browser)
Render the page at a mobile viewport (375×812, iPhone-sized):
- **Mobile layout**: No horizontal scrolling, text readable without zooming, tap targets at least 48×48px
- **Content parity**: Mobile version has the same key content as desktop (Google uses mobile-first indexing)
- **Image optimization**: Check for oversized images (e.g., 2000px wide image in a 375px container), missing `loading="lazy"` on below-fold images
- **CLS indicators**: Elements that visibly shift during load (ads, images without dimensions, dynamically injected content)
- **Core Web Vitals**: Use `javascript_tool` to extract real navigation timing from the Performance API:
const nav = performance.getEntriesByType('navigation')[0];
const paint = performance.getEntriesByType('paint');
({
ttfb: nav.responseStart - nav.requestStart,
domContentLoaded: nav.domContentLoadedEventEnd - nav.startTime,
load: nav.loadEventEnd - nav.startTime,
fcp: paint.find(e => e.name === 'first-contentful-paint')?.startTime,
});Screenshot at mobile viewport.
Scoring
Rate each category on a 0-10 scale:
| Category | What's checked | |----------|---------------| | **Meta Tags** | Title, description, canonical, robots, OG, Twitter cards | | **Content Structure** | H1, heading hierarchy, image alt text, internal links | | **Structured Data** | JSON-LD presence, correct types, required properties | | **Mobile** | Responsive layout, content parity, tap targets | | **Performance Signals** | Image sizes, lazy loading, CLS indicators | | **Internationalisation** | hreflang alternates, lang attribute, multilingual implementation |
**Overall score** = average of the 6 category scores (out of 10).
- **9-10**: Excellent — production-ready SEO
- **7-8**: Good — minor improvements needed
- **5-6**: Needs work — several issues aff
Read more
name: seo-checker description: Audit web pages for SEO issues in a real browser. Checks rendered meta tags, heading hierarchy, image alt text, structured data, canonical URLs, mobile rendering, and performance signals. Produces a scored report with specific findings and fixes. Read-only — inspects, doesn't modify. Requires the hanzi browser automation MCP server and Chrome extension. category: productivity
SEO Checker
You audit web pages for SEO issues using a real browser — rendered meta tags, actual heading structure, real schema markup, mobile viewport behavior. This skill is read-only: observe and report, don't modify.
Tool Selection Rule
- Prefer existing tools first (code search, local files, `curl`). Review HTML source, meta tags, and sitemap before opening the browser.
- Use Hanzi for Phase 2–5 — always open the browser for these phases even if Phase 1 found all static data. Do not substitute curl or WebFetch for browser phases.
Before Starting
Call `browser_status` to verify the extension is reachable. If unavailable, tell the user to install from: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
What You Need
1. **URL** — page or site to audit 2. **Scope** — single page, specific section, or full site (default: single page) 3. **Focus** — any specific SEO concerns (e.g., "we're not showing up in rich results", "mobile traffic dropped")
Audit Phases
Phase 1 — Source Review (before browser)
Check what you can without a browser:
- **Robots.txt**: Fetch `<domain>/robots.txt` — check for accidental `Disallow: /` or blocked important paths. Note: some sites serve different robots.txt to different user agents (UA sniffing). If the curl result looks suspicious or overly restrictive, verify with `browser_start` to see what a real browser receives.
- **Sitemap**: Fetch `<domain>/sitemap.xml` — verify it exists and includes the target URL
- **HTML source**: If accessible, review raw `<head>` for meta tags, canonical, hreflang
- **Codebase** (if source available): Scan for hardcoded noindex, missing meta tag templates, SEO component patterns
Summarize findings before opening the browser.
Phase 2 — Meta & Head Tags (browser)
Use `browser_start` to open the page and inspect the rendered DOM. JavaScript-rendered SPAs may have different meta tags than the raw HTML source.
- **Title tag**: Exists, 50-60 characters, unique, descriptive (not "Home" or "Untitled")
- **Meta description**: Exists, 150-160 characters, includes target keywords, compelling for CTR
- **Canonical URL**: Present, points to the correct URL (not a duplicate or wrong domain)
- **Robots meta**: Check for unintentional `noindex`, `nofollow`, or `none` directives
- **Open Graph tags**: `og:title`, `og:description`, `og:image`, `og:url` — all present and correct
- **Twitter Card tags**: `twitter:card`, `twitter:title`, `twitter:description`, `twitter:image`
- **Viewport meta**: `<meta name="viewport" content="width=device-width, initial-scale=1">` present
- **Charset & lang**: `<meta charset="utf-8">` and `<html lang="...">` set correctly
Screenshot the page after loading.
Phase 3 — Content Structure (browser)
- **H1 tag**: Exactly one per page, descriptive, contains primary keyword
- **Heading hierarchy**: H1 → H2 → H3 — no skipped levels (e.g., H1 → H3 with no H2)
- **Image alt text**: All meaningful images have descriptive alt text; decorative images use `alt=""`
- **Internal links**: Key pages are linked, anchor text is descriptive (not "click here")
- **Broken links**: Check for obvious 404s or dead links on the page
Phase 4 — Structured Data (browser)
- **JSON-LD / Microdata**: Check `<script type="application/ld+json">` blocks in the rendered DOM
- **Schema types**: Verify appropriate types are used (Article, Product, LocalBusiness, BreadcrumbList, FAQ, etc.)
- **Required properties**: Each schema type has required fields — check they're populated (e.g., Article needs `headline`, `datePublished`, `author`)
- **Validation**: Flag malformed JSON-LD or schemas with empty/placeholder values
Phase 5 — Mobile & Performance (browser)
Render the page at a mobile viewport (375×812, iPhone-sized):
- **Mobile layout**: No horizontal scrolling, text readable without zooming, tap targets at least 48×48px
- **Content parity**: Mobile version has the same key content as desktop (Google uses mobile-first indexing)
- **Image optimization**: Check for oversized images (e.g., 2000px wide image in a 375px container), missing `loading="lazy"` on below-fold images
- **CLS indicators**: Elements that visibly shift during load (ads, images without dimensions, dynamically injected content)
- **Core Web Vitals**: Use `javascript_tool` to extract real navigation timing from the Performance API:
const nav = performance.getEntriesByType('navigation')[0];
const paint = performance.getEntriesByType('paint');
({
ttfb: nav.responseStart - nav.requestStart,
domContentLoaded: nav.domContentLoadedEventEnd - nav.startTime,
load: nav.loadEventEnd - nav.startTime,
fcp: paint.find(e => e.name === 'first-contentful-paint')?.startTime,
});Screenshot at mobile viewport.
Scoring
Rate each category on a 0-10 scale:
| Category | What's checked | |----------|---------------| | **Meta Tags** | Title, description, canonical, robots, OG, Twitter cards | | **Content Structure** | H1, heading hierarchy, image alt text, internal links | | **Structured Data** | JSON-LD presence, correct types, required properties | | **Mobile** | Responsive layout, content parity, tap targets | | **Performance Signals** | Image sizes, lazy loading, CLS indicators | | **Internationalisation** | hreflang alternates, lang attribute, multilingual implementation |
**Overall score** = average of the 6 category scores (out of 10).
- **9-10**: Excellent — production-ready SEO
- **7-8**: Good — minor improvements needed
- **5-6**: Needs work — several issues aff
The context layer for browsing agents. Your browsing agent keeps failing on real sites — X uses Draft.js, LinkedIn hides the connect button, Gmail needs keyboard shortcuts.
Repo: hanzili/hanzi-browse
Other skills on hanzi-browse.
- /a11y-auditor
Audit web pages for accessibility issues in a real browser. Checks contrast, font sizes, focus indicators, keyboard navigation, ARIA labels, and semantic HTML against WCAG 2.1 AA. Reports findings with screenshots and specific remediation steps. Requires the hanzi browser
Open skill - /apartment-finder
Search for apartments across multiple real estate platforms, compare listings side by side, and help submit inquiries or applications. Use when the user wants to find a place to rent — searching Zillow, Apartments.com, Craigslist, and similar sites with their real signed-in
Open skill - /competitor-monitor
Monitor competitor websites for changes. Visit a list of URLs, extract pricing, features, positioning, and key content, compare against previous snapshots stored locally, and generate a change report summarizing what's different. Use when the user says "check competitors", "what
Open skill - /competitor-researcher
Research SaaS and AI-tool competitors in a real browser. Visit competitor sites, pricing pages, feature pages, and review platforms to extract pricing, features, positioning, and customer sentiment, then return a structured comparison report. Use when the user wants competitor
Open skill - /data-extractor
Extract structured data from websites into CSV or JSON. Use when the user wants to scrape a list, table, directory, or repeated elements from one or more pages — especially pages that require login, handle CAPTCHAs, or load content dynamically. Examples: "pull all company names
Open skill - /e2e-tester
Test a web app like a QA person — open it in a real browser, click through flows, and report what's broken with screenshots and code references. Works on localhost. Use when the user wants to test their app, verify a flow works, check for visual bugs, or validate changes before
Open skill

