Install
openclaw skills install web-quality-audit-eccComprehensive web quality audit covering performance, accessibility, SEO, best practices, and browser automation testing. Supports automated testing with Pin...
openclaw skills install web-quality-audit-eccComprehensive 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.