skills/link-checker/SKILL.md
# Link Checker Skill Find and validate links on web pages. Reports broken links, redirects, and other issues. ## When to Use - Before releases to catch broken links - After content updates - During user testing (with `--check-links` flag) - Regular site maintenance ## Link Extraction ### Using Browser Snapshot Use `browser_snapshot` to get page accessibility tree, then extract links: ```javascript // Links to extract const linkSelectors = [ 'a[href]', // Standard links 'area
npx skillsauth add ncklrs/claude-chrome-user-testing skills/link-checkerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Find and validate links on web pages. Reports broken links, redirects, and other issues.
--check-links flag)Use browser_snapshot to get page accessibility tree, then extract links:
// Links to extract
const linkSelectors = [
'a[href]', // Standard links
'area[href]', // Image map links
'link[href]', // Stylesheet/resource links (optional)
];
| Type | Pattern | Action |
|------|---------|--------|
| Internal | Same domain | Check via HEAD |
| External | Different domain | Check via HEAD (unless excluded) |
| Anchor | #section | Verify element exists |
| mailto: | mailto:* | Validate format |
| tel: | tel:* | Validate format |
| javascript: | javascript:* | Flag as warning |
| data: | data:* | Skip |
async (page) => {
const links = await page.evaluate(() => {
const anchors = document.querySelectorAll('a[href]');
return Array.from(anchors).map(a => ({
href: a.href,
text: a.textContent.trim().slice(0, 50),
location: a.closest('[id]')?.id || 'page'
}));
});
return links;
}
For each link, make a HEAD request to check status:
async (page) => {
const response = await page.request.head(url, {
timeout: 10000,
ignoreHTTPSErrors: false
});
return {
status: response.status(),
headers: response.headers()
};
}
| Status Code | Category | Action | |-------------|----------|--------| | 200 | Success | Mark as working | | 201-299 | Success | Mark as working | | 301 | Permanent Redirect | Warn - update link | | 302 | Temporary Redirect | Note redirect | | 303, 307, 308 | Redirects | Note redirect | | 400 | Bad Request | Error | | 401, 403 | Auth Required | Warning | | 404 | Not Found | Error - broken link | | 405 | Method Not Allowed | Retry with GET | | 429 | Rate Limited | Wait and retry | | 500-599 | Server Error | Error | | Timeout | No Response | Error |
Track redirect chains:
const checkLink = async (url) => {
const redirects = [];
let currentUrl = url;
let maxRedirects = 5;
while (maxRedirects > 0) {
const response = await fetch(currentUrl, {
method: 'HEAD',
redirect: 'manual'
});
if (response.status >= 300 && response.status < 400) {
const location = response.headers.get('location');
redirects.push({ from: currentUrl, to: location, status: response.status });
currentUrl = new URL(location, currentUrl).href;
maxRedirects--;
} else {
return { finalStatus: response.status, redirects };
}
}
return { error: 'Too many redirects', redirects };
};
function crawl(startUrl, maxDepth):
visited = Set()
toVisit = [(startUrl, 0)] // (url, depth)
results = []
while toVisit not empty:
(url, depth) = toVisit.pop()
if url in visited or depth > maxDepth:
continue
visited.add(url)
pageLinks = extractLinks(url)
results.extend(validateLinks(pageLinks))
if depth < maxDepth:
for link in pageLinks:
if isInternal(link) and link not in visited:
toVisit.append((link, depth + 1))
return results
| Depth | Typical Links | Time | |-------|---------------|------| | 1 | 20-100 | 10-30s | | 2 | 100-500 | 1-5 min | | 3 | 500-2000+ | 5-20 min |
Tips:
--internal-only to reduce scopeconst linkReport = {
url: 'https://example.com',
checkedAt: '2025-01-06T14:30:00Z',
summary: {
total: 47,
working: 44,
broken: 2,
redirects: 3,
skipped: 1
},
broken: [
{ url: '/old-page', foundOn: '/', status: 404 },
],
redirects: [
{ url: '/blog', redirectsTo: '/news', status: 301 },
],
warnings: [
{ type: 'javascript-link', url: 'javascript:void(0)', foundOn: '/nav' },
],
byPage: {
'/': { checked: 15, broken: 1 },
'/about': { checked: 8, broken: 1 },
}
};
When --check-links is added to /user-test:
## Link Health
### Summary
- **Links Encountered**: 32
- **Working**: 30 (94%)
- **Broken**: 2 (6%)
### Broken Links Found During Testing
| Link | Encountered During | Status |
|------|-------------------|--------|
| /products/sale | Browsing products | 404 |
| /help/faq | Looking for help | 404 |
### Impact on User Experience
The persona encountered 2 broken links during their journey,
which could cause confusion and frustration.
development
# WCAG Auditor Skill This skill provides WCAG 2.1 accessibility audit capabilities, including criteria definitions, check implementations, and scoring logic. ## Purpose Systematically evaluate web pages against WCAG 2.1 Level A and AA success criteria to identify accessibility barriers and provide remediation guidance. ## WCAG 2.1 Overview WCAG is organized around four principles (POUR): - **Perceivable**: Information must be presentable to users - **Operable**: Interface must be usable - *
development
Comprehensive persona-based user testing skill for web applications. Simulates how real users from different demographics interact with interfaces, including realistic timing, behavioral patterns, and frustration triggers. Use when: - Testing user interfaces before release - Validating UX flows from diverse perspectives - Conducting accessibility reviews - Optimizing onboarding or checkout experiences - Getting feedback on form design
development
# Stripe Checkout Testing Skill This skill provides guidance for testing Stripe checkout flows with any persona. It handles test card data, form detection, and payment-specific narration. ## Purpose Enable realistic user testing of Stripe payment flows using official test cards, with persona-appropriate reactions to checkout experiences. ## Test Card Reference Load card data from `test-cards.json`. Key scenarios: | Scenario | Card | When to Use | |----------|------|-------------| | `succes
testing
# Smoke Testing Skill Run pre-configured smoke tests for common user flows. Quick validation that critical functionality works. ## What is Smoke Testing? Smoke testing is a quick sanity check to ensure basic functionality works before deeper testing. The name comes from electronics - if you turn on a circuit and smoke comes out, you know something is wrong without further testing. ## When to Use - Before releases to catch obvious breaks - After deployments to verify functionality - In CI/CD