Comprehensive web quality audit covering performance, accessibility, SEO, best practices, and browser automation testing. Supports automated testing with Pin...
Comprehensive quality review based on Google Lighthouse audits. Covers Performance, Accessibility, SEO, and Best Practices across 150+ checks. Includes browser automation testing with PinchTab for real-world validation.
Core Web Vitals — Must pass for good page experience:
Resource Optimization:
srcset.@import.font-display: swap. Preload critical fonts. Subset to needed characters.Loading Strategy:
<link rel="preconnect"> for third-party domains.Perceivable:
<img> has meaningful alt text. Decorative images use alt="".Operable:
Understandable:
lang attribute on <html>.Robust:
Crawlability:
On-Page SEO:
<h1>. Logical heading structure.Technical SEO:
Security:
Modern Standards:
document.write, synchronous XHR, etc.<!DOCTYPE html>.<meta charset="UTF-8"> as first element in <head>.UX Patterns:
| Level | Description | Action |
|---|---|---|
| Critical | Security vulnerabilities, complete failures | Fix immediately |
| High | Core Web Vitals failures, major a11y barriers | Fix before launch |
| Medium | Performance opportunities, SEO improvements | Fix within sprint |
| Low | Minor optimizations, code quality | Fix when convenient |
When performing an audit, structure findings as:
## Audit results
### Critical issues (X found)
- **[Category]** Issue description. File: `path/to/file.js:123`
- **Impact:** Why this matters
- **Fix:** Specific code change or recommendation
### High priority (X found)
...
### Summary
- Performance: X issues (Y critical)
- Accessibility: X issues (Y critical)
- SEO: X issues
- Best Practices: X issues
### Recommended priority
1. First fix this because...
2. Then address...
3. Finally optimize...
PinchTab is a high-performance browser automation bridge for AI agents. Use it to validate your site in real browsers.
# macOS / Linux
curl -fsSL https://pinchtab.com/install.sh | bash
# npm
npm install -g pinchtab
# Docker
docker run -d -p 9867:9867 pinchtab/pinchtab
# Terminal 1: Start PinchTab server
pinchtab
# Server runs on http://localhost:9867
# Navigate to URL
pinchtab nav https://example.com
# Wait 3 seconds for accessibility tree to populate
sleep 3
# Get interactive elements snapshot
pinchtab snap -i -c
# Extract text (~800 tokens vs 10,000+ for screenshots)
pinchtab nav https://example.com/article
sleep 3
pinchtab text
# Get snapshot with element refs
pinchtab snap -i
# Output shows: e5: "Submit button", e12: "Email input"
# Click element by ref
pinchtab click e5
# Fill input
pinchtab fill e12 "user@example.com"
# Press key
pinchtab press e12 Enter
# Create instance
TAB=$(curl -s -X POST http://localhost:9867/instances \
-d '{"profile":"work"}' | jq -r '.id')
# Navigate
curl -X POST "http://localhost:9867/instances/$TAB/tabs/open" \
-d '{"url":"https://example.com"}'
# Get snapshot (wait 3s first)
sleep 3
curl "http://localhost:9867/instances/$TAB/snapshot?filter=interactive"
# Click element
curl -X POST "http://localhost:9867/instances/$TAB/action" \
-d '{"kind":"click","ref":"e5"}'
# Extract text
curl "http://localhost:9867/instances/$TAB/text"
#!/bin/bash
# validate-cwv.sh
URL=${1:-"https://example.com"}
INST=$(curl -s -X POST http://localhost:9867/instances \
-d '{"mode":"headless"}' | jq -r '.id')
# Navigate and measure load time
START=$(date +%s%N)
curl -s -X POST "http://localhost:9867/instances/$INST/tabs/open" \
-d "{\"url\":\"$URL\"}" > /dev/null
sleep 3
END=$(date +%s%N)
# Calculate LCP estimate (simplified)
LOAD_TIME=$(( (END - START) / 1000000 )) # ms
echo "Estimated LCP: ${LOAD_TIME}ms"
# Check if < 2.5s
if [ $LOAD_TIME -lt 2500 ]; then
echo "✅ LCP passing"
else
echo "❌ LCP failing (> 2.5s)"
fi
# Cleanup
curl -s -X POST "http://localhost:9867/instances/$INST/stop" > /dev/null
# Get accessibility tree and check for common issues
pinchtab nav https://example.com
sleep 3
# Check for images without alt text
pinchtab snap | jq '.nodes[] | select(.role == "image" and .name == null) | {ref, role}'
# Check for buttons without labels
pinchtab snap | jq '.nodes[] | select(.role == "button" and .name == null) | {ref, role}'
# Check heading hierarchy
pinchtab snap | jq '.nodes[] | select(.role | startswith("heading")) | {role, name}'
# Create headed instance for visual inspection
pinchtab instances create --profile=mobile-test --mode=headed
# Navigate to site
pinchtab nav https://example.com
# Take screenshot for manual review
pinchtab screenshot --output=mobile-test.png
# Check viewport meta tag
pinchtab evaluate "document.querySelector('meta[name=viewport]')?.content"
# Extract page metadata
pinchtab nav https://example.com
sleep 2
# Get title
curl -s http://localhost:9867/instances/$INST/text | jq -r '.title'
# Get meta description (via evaluate)
pinchtab evaluate '
document.querySelector("meta[name=description]")?.content
'
# Check for structured data
pinchtab evaluate '
JSON.parse(document.querySelector("script[type=application/ld+json]")?.innerText || "{}")
'
Based on PinchTab documentation:
# ❌ Too fast - accessibility tree not ready
pinchtab nav https://example.com
pinchtab snap
# Returns: {"count": 1, "nodes": [{"ref": "e0", "role": "RootWebArea"}]}
# ✅ Wait 3 seconds for full tree
pinchtab nav https://example.com
sleep 3
pinchtab snap
# Returns: {"count": 2645, "nodes": [...]}
# Navigate + wait + filter (14x more token-efficient)
curl -X POST http://localhost:9867/navigate \
-d '{"url": "https://example.com"}' && \
sleep 3 && \
curl http://localhost:9867/snapshot | \
jq '.nodes[] | select(.name | length > 15) | .name' | \
head -30
Why this works:
length > 15 filters out buttons, labelshead -30 limits output (saves tokens)#!/bin/bash
# parallel-test.sh
URLS=("https://site1.com" "https://site2.com" "https://site3.com")
INSTANCES=()
# Create 3 headless instances
for i in {0..2}; do
INST=$(curl -s -X POST http://localhost:9867/instances \
-d '{"mode":"headless"}' | jq -r '.id')
INSTANCES[$i]=$INST
done
# Run tests in parallel
for i in {0..2}; do
(
curl -s -X POST "http://localhost:9867/instances/${INSTANCES[$i]}/tabs/open" \
-d "{\"url\":\"${URLS[$i]}\"}"
sleep 3
TITLE=$(curl -s "http://localhost:9867/instances/${INSTANCES[$i]}/text" | jq -r '.title')
echo "Site $i: $TITLE"
curl -s -X POST "http://localhost:9867/instances/${INSTANCES[$i]}/stop"
) &
done
wait
echo "All tests complete"
PinchTab provides an SMCP plugin for Claude Code integration:
# Set plugin directory
export MCP_PLUGINS_DIR=/path/to/pinchtab/plugins
# Available tools:
# - pinchtab__navigate
# - pinchtab__snapshot
# - pinchtab__action
# - pinchtab__text
# - pinchtab__screenshot
# - pinchtab__evaluate
# etc.
| Mode | Use Case | Memory | Speed |
|---|---|---|---|
| Headless | CI/CD, scraping, batch | ~50-80 MB | Fast |
| Headed | Debugging, visual QA | ~100-150 MB | Slower |
# Headless for production
pinchtab instances create --mode=headless
# Headed for debugging
pinchtab instances create --mode=headed
For detailed guidelines on specific areas:
Combine static analysis with real browser automation for comprehensive quality assurance.
ZIP package — ready to use