New: Earn 20% as an AgentAlley affiliate. Share your link and earn on every sale you refer. Join now New: Earn 20% as an affiliate. Join now

Run QA testing on a page, feature

by rampstackco · MIT license · ★ 901 on GitHub · updated Sep 15

QA testing cover

Run QA testing on a page, feature, or full site at one of three depth tiers (smoke, standard, full). Use this skill whenever the user asks to QA a page or site, run a smoke test after a deploy, verify a page before launch, or run a…

---
name: qa-testing
description: "Run QA testing on a page, feature, or full site at one of three depth tiers (smoke, standard, full). Use this skill whenever the user asks to QA a page or site, run a smoke test after a deploy, verify a page before launch, or run a regression sweep. Triggers on QA, QA sweep, smoke test, regression test, post-deploy check, pre-launch check, verify the deploy, test this page, does the page render, broken link, 404, image not loading. Also triggers proactively after a deploy or a new page launch where verification matters. Covers accessibility, performance, and SEO at the surface-signal level only: deep audits belong to `accessibility-audit`, `performance-optimization`, and `seo-technical`, and code-level debugging to `code-review-web`."
category: qa
catalog_summary: "Pre-launch QA, regression testing, cross-browser checks"
display_order: 1
---

# QA Testing

Verify that a page, feature, or site is working before declaring it shipped. Stack-agnostic. Console-snippet driven for speed.

This skill is faster than `accessibility-audit` (which goes deeper on WCAG) and `performance-optimization` (which goes deeper on Core Web Vitals). Use this skill for general QA. Use the specialists for deep audits.

---

## When to use

Overview

Verify that a page, feature, or site is working before declaring it shipped. Stack-agnostic. Console-snippet driven for speed.

Manual install (npx, ZIP)
Claude Codenpx skills add rampstackco/claude-skills --skill qa-testing -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/rampstackco/claude-skills/tar.gz/3d4510a94a76 \ | tar -xz -C ~/.claude/skills --strip-components=2 claude-skills-3d4510a94a76/skills/qa-testing
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/a96ecc28689d15d51ee4/qa-testing.zip" -OutFile "$env:TEMP\qa-testing.zip"; Expand-Archive "$env:TEMP\qa-testing.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md12.6 KB
  • references/1 file · 4.3 KB
Read the files here
rampstackco/3d4510a2 files
SKILL.md
Show the full text303 lines

QA Testing

Verify that a page, feature, or site is working before declaring it shipped. Stack-agnostic. Console-snippet driven for speed.

This skill is faster than accessibility-audit (which goes deeper on WCAG) and performance-optimization (which goes deeper on Core Web Vitals). Use this skill for general QA. Use the specialists for deep audits.


When to use

  • After every deploy (smoke test)
  • After launching a new page or feature (standard audit)
  • Before a major release (full release matrix)
  • Investigating a "something looks off" report
  • Pre-launch verification of a site or section

When NOT to use

  • Deep accessibility compliance work (use accessibility-audit)
  • Deep performance investigation (use performance-optimization)
  • Code review or debugging (use code-review-web)
  • Initial site setup or technical SEO baseline (use seo-technical)

Required inputs

  • The page URL or site under test
  • The tier of QA needed (smoke, standard, or full)
  • Browser dev tools access
  • Any specific concerns to check beyond the standard tier

The framework: 3 tiers

QA scales with the stakes. Pick the tier that matches the context.

Tier When to run Time Coverage
Smoke After every deploy 2 minutes Critical signals only
Standard New page or feature 10 minutes On-page basics, accessibility, structure
Full Major release, pre-launch 30+ minutes Comprehensive across all dimensions
Tier 1: Smoke test

The 2-minute "did the deploy break anything obvious?" check. Run after every deploy.

Console snippet (paste in browser dev tools):

const smoke = {
  title: document.title,
  titleLen: document.title.length,
  canonical: document.querySelector('link[rel="canonical"]')?.href,
  h1Count: document.querySelectorAll('h1').length,
  missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
  schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
    .map(s => { try { return JSON.parse(s.innerText)['@type'] } catch(e) { return 'invalid' } }),
  brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
};
console.log(JSON.stringify(smoke, null, 2));

Pass criteria:

  • Title exists and is 30 to 60 characters
  • Canonical points at the production domain (never staging or preview URLs)
  • Exactly one H1
  • Zero images missing the alt attribute. An empty alt="" on a decorative image is correct markup and passes; only an absent attribute fails.
  • Zero broken images
  • Every schema block parses (no invalid entries in the snippet output). Whether the types are the right ones for the page is a Full-tier check, against the Rich Results Test.

If any of these fail, do not proceed with deeper testing until the smoke issue is fixed.

Tier 2: Standard page audit

The 10-minute new-page-or-feature audit. Covers the on-page basics plus accessibility and structure.

Console snippet:

const audit = {
  title: document.title,
  titleLen: document.title.length,
  canonical: document.querySelector('link[rel="canonical"]')?.href,
  metaDesc: document.querySelector('meta[name="description"]')?.content,
  metaDescLen: document.querySelector('meta[name="description"]')?.content?.length,
  ogImage: document.querySelector('meta[property="og:image"]')?.content,
  ogTitle: document.querySelector('meta[property="og:title"]')?.content,
  twitterCard: document.querySelector('meta[name="twitter:card"]')?.content,
  h1Count: document.querySelectorAll('h1').length,
  h1Text: document.querySelector('h1')?.innerText,
  h2Count: document.querySelectorAll('h2').length,
  h2s: [...document.querySelectorAll('h2')].map(h => h.innerText.trim().slice(0, 60)),
  totalImages: document.querySelectorAll('img').length,
  missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
  brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
  externalLinksWithoutNoopener: [...document.querySelectorAll('a[target="_blank"]')]
    .filter(a => !a.rel?.includes('noopener')).length,
  schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
    .map(s => {
      try {
        const d = JSON.parse(s.innerText);
        return d['@graph'] ? d['@graph'].map(x => x['@type']) : d['@type'];
      } catch(e) { return 'invalid' }
    }),
  hasSkipLink: [...document.querySelectorAll('a[href^="#"]')].slice(0, 3)
    .some(a => /skip/i.test(a.textContent) && !!document.getElementById(a.getAttribute('href').slice(1))),
  pageLanguage: document.documentElement.lang || 'NOT SET',
  hasFavicon: !!document.querySelector('link[rel*="icon"]'),
};
console.log(JSON.stringify(audit, null, 2));

Pass criteria (in addition to smoke):

  • Meta description: 120 to 160 characters
  • og:image, og:title, twitter:card present
  • H2s present and descriptive
  • All external links with target="_blank" have rel="noopener"
  • Page language declared (lang attribute on <html>)
  • Favicon present
Tier 3: Full release matrix

The 30-minute pre-launch check. Cover all dimensions.

Dimension Pass criteria
Smoke and standard All pass
Accessibility (basic) Run browser audit tool (e.g., Lighthouse), score above 90
Performance (basic) Every threshold in the report template's Performance checklist, INP included
Mobile responsiveness Every viewport in the report template's responsiveness checklist
Cross-browser Tested in Chrome, Safari, Firefox (and Edge if relevant audience)
Forms All forms submit successfully and validate correctly
Internal links No broken internal links (sample 20 random)
External links All return 200 (sample 10)
Sitemap Returns 200, lists canonical URLs only
robots.txt Allows production crawlers, blocks staging if applicable
Security headers HSTS, X-Frame-Options, X-Content-Type-Options present
HTTPS All resources load over HTTPS, no mixed content
404 handling 404 pages return HTTP 404 (not soft 200)
Schema validation All schema validates in Rich Results Test
Analytics Events fire as expected on key user actions
Cache behavior Cache headers appropriate for page type

For headers, run:

fetch(window.location.origin, { method: 'HEAD' })
  .then(r => {
    const headers = {};
    for (const [k, v] of r.headers.entries()) headers[k] = v;
    console.log(JSON.stringify(headers, null, 2));
  });

Look for: strict-transport-security, x-frame-options, x-content-type-options.


Specific QA snippets

Image audit
const imgs = [...document.querySelectorAll('img')].map(i => ({
  src: i.src.split('/').pop().split('?')[0].slice(0, 60),
  alt: i.hasAttribute('alt') ? (i.alt === '' ? 'DECORATIVE (empty alt)' : i.alt) : 'MISSING',
  width: i.naturalWidth,
  height: i.naturalHeight,
  loaded: i.complete && i.naturalWidth > 0,
}));
console.table(imgs);
console.log({
  total: imgs.length,
  broken: imgs.filter(i => !i.loaded).length,
  noAlt: imgs.filter(i => i.alt === 'MISSING').length,
  decorative: imgs.filter(i => i.alt.startsWith('DECORATIVE')).length,
});
Heading hierarchy check
const headings = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(h => ({
  level: parseInt(h.tagName[1]),
  text: h.innerText.trim().slice(0, 80),
}));
console.table(headings);

// Check for skipped levels
const levels = headings.map(h => h.level);
let skipped = false;
for (let i = 1; i < levels.length; i++) {
  if (levels[i] > levels[i-1] + 1) {
    console.warn(`Skipped from H${levels[i-1]} to H${levels[i]}: "${headings[i].text}"`);
    skipped = true;
  }
}
if (!skipped) console.log('No skipped heading levels');
Contrast spot-check
function contrast(bg, fg) {
  function lum(hex) {
    return [hex.slice(1,3), hex.slice(3,5), hex.slice(5,7)]
      .map(h => parseInt(h, 16) / 255)
      .map(v => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4))
      .reduce((a, v, i) => a + v * [0.2126, 0.7152, 0.0722][i], 0);
  }
  const [l1, l2] = [lum(bg), lum(fg)];
  const r = ((Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05)).toFixed(2);
  return r + ':1 ' + (parseFloat(r) >= 4.5 ? 'PASS body' : parseFloat(r) >= 3 ? 'PASS large only' : 'FAIL');
}

// Examples
contrast('#FFFFFF', '#4B5563'); // body color check
contrast('#FFFFFF', '#9CA3AF'); // verify gray choices
Form audit (per form)
[...document.querySelectorAll('form')].forEach((form, i) => {
  const fields = [...form.querySelectorAll('input, select, textarea')].map(field => ({
    type: field.type || field.tagName.toLowerCase(),
    name: field.name,
    hasLabel: !!form.querySelector(`label[for="${field.id}"]`) || !!field.closest('label'),
    required: field.required,
  }));
  console.log(`Form ${i + 1}:`);
  console.table(fields);
});
const externalLinks = [...document.querySelectorAll('a[href^="http"]')]
  .filter(a => !a.href.includes(window.location.host));
const issues = externalLinks.filter(a =>
  a.target === '_blank' && (!a.rel?.includes('noopener') || !a.rel?.includes('noreferrer'))
);
if (issues.length) {
  console.warn(`${issues.length} external links missing noopener/noreferrer:`);
  issues.forEach(a => console.warn(a.href));
} else {
  console.log(`All ${externalLinks.length} external links properly attributed`);
}

Workflow

  1. Pick the tier. Smoke for routine deploys. Standard for new work. Full for releases.
  2. Run the snippet. Paste the appropriate console snippet, review output.
  3. Note failures. Each failure either gets fixed before ship or filed as a known issue.
  4. For Standard tier, add: visual review at 375px, 768px, and 1440px. Standard deliberately skips 1024px; the Full tier picks it up with the rest of the template's responsiveness checklist. Test the primary user flow.
  5. For Full tier, add: cross-browser testing, Lighthouse audit, schema validation, security headers, 404 handling.
  6. Document. Use the template in references/qa-report-template.md for full audits.

Failure patterns

  • Skipping smoke tests on "small" deploys. Half of broken-production incidents start with a deploy that "looked safe."
  • Running snippets but not reading the output. The console snippet is a tool. The judgment is reading what it returns.
  • Visual-only QA. Eyeballing a page misses missing alt text, broken schema, missing canonical. Always run the snippet.
  • Single-browser testing. Mobile Safari and Chrome differ enough to surprise you. Test at least Chrome and Safari.
  • No mobile QA. The 375px viewport is where most users live. Test there or get burned later.
  • Pass-fail with no remediation. A failed QA must produce a fix or a known-issue ticket. Failed QA that ships unfixed is process theater.

Output format

For smoke tests: console output is the report.

For standard and full audits: a markdown report at qa-report-[date].md. Use the template in references/qa-report-template.md.


If required data is unavailable

This skill's output depends on data, measurements, or tool results it cannot generate on its own. When a required input, tool, or data source is unavailable or unverifiable, the sanctioned output is the deliverable with the gap stated: what was needed, what was actually obtained or verified, and which parts of the output are affected. Fabricating, estimating, or interpolating a required number to complete the deliverable is never sanctioned. A stated gap is a complete answer.


Reference files

1---
2name: qa-testing
3description: "Run QA testing on a page, feature, or full site at one of three depth tiers (smoke, standard, full). Use this skill whenever the user asks to QA a page or site, run a smoke test after a deploy, verify a page before launch, or run a regression sweep. Triggers on QA, QA sweep, smoke test, regression test, post-deploy check, pre-launch check, verify the deploy, test this page, does the page render, broken link, 404, image not loading. Also triggers proactively after a deploy or a new page launch where verification matters. Covers accessibility, performance, and SEO at the surface-signal level only: deep audits belong to `accessibility-audit`, `performance-optimization`, and `seo-technical`, and code-level debugging to `code-review-web`."
4category: qa
5catalog_summary: "Pre-launch QA, regression testing, cross-browser checks"
6display_order: 1
7---
8 
9# QA Testing
10 
11Verify that a page, feature, or site is working before declaring it shipped. Stack-agnostic. Console-snippet driven for speed.
12 
13This skill is faster than `accessibility-audit` (which goes deeper on WCAG) and `performance-optimization` (which goes deeper on Core Web Vitals). Use this skill for general QA. Use the specialists for deep audits.
14 
15---
16 
17## When to use
18 
19- After every deploy (smoke test)
20- After launching a new page or feature (standard audit)
21- Before a major release (full release matrix)
22- Investigating a "something looks off" report
23- Pre-launch verification of a site or section
24 
25## When NOT to use
26 
27- Deep accessibility compliance work (use `accessibility-audit`)
28- Deep performance investigation (use `performance-optimization`)
29- Code review or debugging (use `code-review-web`)
30- Initial site setup or technical SEO baseline (use `seo-technical`)
31 
32---
33 
34## Required inputs
35 
36- The page URL or site under test
37- The tier of QA needed (smoke, standard, or full)
38- Browser dev tools access
39- Any specific concerns to check beyond the standard tier
40 
41---
42 
43## The framework: 3 tiers
44 
45QA scales with the stakes. Pick the tier that matches the context.
46 
47| Tier | When to run | Time | Coverage |
48|---|---|---|---|
49| Smoke | After every deploy | 2 minutes | Critical signals only |
50| Standard | New page or feature | 10 minutes | On-page basics, accessibility, structure |
51| Full | Major release, pre-launch | 30+ minutes | Comprehensive across all dimensions |
52 
53### Tier 1: Smoke test
54 
55The 2-minute "did the deploy break anything obvious?" check. Run after every deploy.
56 
57Console snippet (paste in browser dev tools):
58 
59```javascript
60const smoke = {
61 title: document.title,
62 titleLen: document.title.length,
63 canonical: document.querySelector('link[rel="canonical"]')?.href,
64 h1Count: document.querySelectorAll('h1').length,
65 missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
66 schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
67 .map(s => { try { return JSON.parse(s.innerText)['@type'] } catch(e) { return 'invalid' } }),
68 brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
69};
70console.log(JSON.stringify(smoke, null, 2));
71```
72 
73**Pass criteria:**
74- Title exists and is 30 to 60 characters
75- Canonical points at the production domain (never staging or preview URLs)
76- Exactly one H1
77- Zero images missing the `alt` attribute. An empty `alt=""` on a decorative image is correct markup and passes; only an absent attribute fails.
78- Zero broken images
79- Every schema block parses (no `invalid` entries in the snippet output). Whether the types are the right ones for the page is a Full-tier check, against the Rich Results Test.
80 
81If any of these fail, do not proceed with deeper testing until the smoke issue is fixed.
82 
83### Tier 2: Standard page audit
84 
85The 10-minute new-page-or-feature audit. Covers the on-page basics plus accessibility and structure.
86 
87Console snippet:
88 
89```javascript
90const audit = {
91 title: document.title,
92 titleLen: document.title.length,
93 canonical: document.querySelector('link[rel="canonical"]')?.href,
94 metaDesc: document.querySelector('meta[name="description"]')?.content,
95 metaDescLen: document.querySelector('meta[name="description"]')?.content?.length,
96 ogImage: document.querySelector('meta[property="og:image"]')?.content,
97 ogTitle: document.querySelector('meta[property="og:title"]')?.content,
98 twitterCard: document.querySelector('meta[name="twitter:card"]')?.content,
99 h1Count: document.querySelectorAll('h1').length,
100 h1Text: document.querySelector('h1')?.innerText,
101 h2Count: document.querySelectorAll('h2').length,
102 h2s: [...document.querySelectorAll('h2')].map(h => h.innerText.trim().slice(0, 60)),
103 totalImages: document.querySelectorAll('img').length,
104 missingAlts: [...document.querySelectorAll('img')].filter(i => !i.hasAttribute('alt')).length,
105 brokenImages: [...document.querySelectorAll('img')].filter(i => !i.complete || i.naturalWidth === 0).length,
106 externalLinksWithoutNoopener: [...document.querySelectorAll('a[target="_blank"]')]
107 .filter(a => !a.rel?.includes('noopener')).length,
108 schema: [...document.querySelectorAll('script[type="application/ld+json"]')]
109 .map(s => {
110 try {
111 const d = JSON.parse(s.innerText);
112 return d['@graph'] ? d['@graph'].map(x => x['@type']) : d['@type'];
113 } catch(e) { return 'invalid' }
114 }),
115 hasSkipLink: [...document.querySelectorAll('a[href^="#"]')].slice(0, 3)
116 .some(a => /skip/i.test(a.textContent) && !!document.getElementById(a.getAttribute('href').slice(1))),
117 pageLanguage: document.documentElement.lang || 'NOT SET',
118 hasFavicon: !!document.querySelector('link[rel*="icon"]'),
119};
120console.log(JSON.stringify(audit, null, 2));
121```
122 
123**Pass criteria** (in addition to smoke):
124- Meta description: 120 to 160 characters
125- og:image, og:title, twitter:card present
126- H2s present and descriptive
127- All external links with `target="_blank"` have `rel="noopener"`
128- Page language declared (`lang` attribute on `<html>`)
129- Favicon present
130 
131### Tier 3: Full release matrix
132 
133The 30-minute pre-launch check. Cover all dimensions.
134 
135| Dimension | Pass criteria |
136|---|---|
137| Smoke and standard | All pass |
138| Accessibility (basic) | Run browser audit tool (e.g., Lighthouse), score above 90 |
139| Performance (basic) | Every threshold in the report template's Performance checklist, INP included |
140| Mobile responsiveness | Every viewport in the report template's responsiveness checklist |
141| Cross-browser | Tested in Chrome, Safari, Firefox (and Edge if relevant audience) |
142| Forms | All forms submit successfully and validate correctly |
143| Internal links | No broken internal links (sample 20 random) |
144| External links | All return 200 (sample 10) |
145| Sitemap | Returns 200, lists canonical URLs only |
146| robots.txt | Allows production crawlers, blocks staging if applicable |
147| Security headers | HSTS, X-Frame-Options, X-Content-Type-Options present |
148| HTTPS | All resources load over HTTPS, no mixed content |
149| 404 handling | 404 pages return HTTP 404 (not soft 200) |
150| Schema validation | All schema validates in Rich Results Test |
151| Analytics | Events fire as expected on key user actions |
152| Cache behavior | Cache headers appropriate for page type |
153 
154For headers, run:
155 
156```javascript
157fetch(window.location.origin, { method: 'HEAD' })
158 .then(r => {
159 const headers = {};
160 for (const [k, v] of r.headers.entries()) headers[k] = v;
161 console.log(JSON.stringify(headers, null, 2));
162 });
163```
164 
165Look for: `strict-transport-security`, `x-frame-options`, `x-content-type-options`.
166 
167---
168 
169## Specific QA snippets
170 
171### Image audit
172 
173```javascript
174const imgs = [...document.querySelectorAll('img')].map(i => ({
175 src: i.src.split('/').pop().split('?')[0].slice(0, 60),
176 alt: i.hasAttribute('alt') ? (i.alt === '' ? 'DECORATIVE (empty alt)' : i.alt) : 'MISSING',
177 width: i.naturalWidth,
178 height: i.naturalHeight,
179 loaded: i.complete && i.naturalWidth > 0,
180}));
181console.table(imgs);
182console.log({
183 total: imgs.length,
184 broken: imgs.filter(i => !i.loaded).length,
185 noAlt: imgs.filter(i => i.alt === 'MISSING').length,
186 decorative: imgs.filter(i => i.alt.startsWith('DECORATIVE')).length,
187});
188```
189 
190### Heading hierarchy check
191 
192```javascript
193const headings = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(h => ({
194 level: parseInt(h.tagName[1]),
195 text: h.innerText.trim().slice(0, 80),
196}));
197console.table(headings);
198 
199// Check for skipped levels
200const levels = headings.map(h => h.level);
201let skipped = false;
202for (let i = 1; i < levels.length; i++) {
203 if (levels[i] > levels[i-1] + 1) {
204 console.warn(`Skipped from H${levels[i-1]} to H${levels[i]}: "${headings[i].text}"`);
205 skipped = true;
206 }
207}
208if (!skipped) console.log('No skipped heading levels');
209```
210 
211### Contrast spot-check
212 
213```javascript
214function contrast(bg, fg) {
215 function lum(hex) {
216 return [hex.slice(1,3), hex.slice(3,5), hex.slice(5,7)]
217 .map(h => parseInt(h, 16) / 255)
218 .map(v => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4))
219 .reduce((a, v, i) => a + v * [0.2126, 0.7152, 0.0722][i], 0);
220 }
221 const [l1, l2] = [lum(bg), lum(fg)];
222 const r = ((Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05)).toFixed(2);
223 return r + ':1 ' + (parseFloat(r) >= 4.5 ? 'PASS body' : parseFloat(r) >= 3 ? 'PASS large only' : 'FAIL');
224}
225 
226// Examples
227contrast('#FFFFFF', '#4B5563'); // body color check
228contrast('#FFFFFF', '#9CA3AF'); // verify gray choices
229```
230 
231### Form audit (per form)
232 
233```javascript
234[...document.querySelectorAll('form')].forEach((form, i) => {
235 const fields = [...form.querySelectorAll('input, select, textarea')].map(field => ({
236 type: field.type || field.tagName.toLowerCase(),
237 name: field.name,
238 hasLabel: !!form.querySelector(`label[for="${field.id}"]`) || !!field.closest('label'),
239 required: field.required,
240 }));
241 console.log(`Form ${i + 1}:`);
242 console.table(fields);
243});
244```
245 
246### External link audit
247 
248```javascript
249const externalLinks = [...document.querySelectorAll('a[href^="http"]')]
250 .filter(a => !a.href.includes(window.location.host));
251const issues = externalLinks.filter(a =>
252 a.target === '_blank' && (!a.rel?.includes('noopener') || !a.rel?.includes('noreferrer'))
253);
254if (issues.length) {
255 console.warn(`${issues.length} external links missing noopener/noreferrer:`);
256 issues.forEach(a => console.warn(a.href));
257} else {
258 console.log(`All ${externalLinks.length} external links properly attributed`);
259}
260```
261 
262---
263 
264## Workflow
265 
2661. **Pick the tier.** Smoke for routine deploys. Standard for new work. Full for releases.
2672. **Run the snippet.** Paste the appropriate console snippet, review output.
2683. **Note failures.** Each failure either gets fixed before ship or filed as a known issue.
2694. **For Standard tier**, add: visual review at 375px, 768px, and 1440px. Standard deliberately skips 1024px; the Full tier picks it up with the rest of the template's responsiveness checklist. Test the primary user flow.
2705. **For Full tier**, add: cross-browser testing, Lighthouse audit, schema validation, security headers, 404 handling.
2716. **Document.** Use the template in [`references/qa-report-template.md`](references/qa-report-template.md) for full audits.
272 
273---
274 
275## Failure patterns
276 
277- **Skipping smoke tests on "small" deploys.** Half of broken-production incidents start with a deploy that "looked safe."
278- **Running snippets but not reading the output.** The console snippet is a tool. The judgment is reading what it returns.
279- **Visual-only QA.** Eyeballing a page misses missing alt text, broken schema, missing canonical. Always run the snippet.
280- **Single-browser testing.** Mobile Safari and Chrome differ enough to surprise you. Test at least Chrome and Safari.
281- **No mobile QA.** The 375px viewport is where most users live. Test there or get burned later.
282- **Pass-fail with no remediation.** A failed QA must produce a fix or a known-issue ticket. Failed QA that ships unfixed is process theater.
283 
284---
285 
286## Output format
287 
288For smoke tests: console output is the report.
289 
290For standard and full audits: a markdown report at `qa-report-[date].md`. Use the template in [`references/qa-report-template.md`](references/qa-report-template.md).
291 
292---
293 
294## If required data is unavailable
295 
296This skill's output depends on data, measurements, or tool results it cannot generate on its own. When a required input, tool, or data source is unavailable or unverifiable, the sanctioned output is the deliverable with the gap stated: what was needed, what was actually obtained or verified, and which parts of the output are affected. Fabricating, estimating, or interpolating a required number to complete the deliverable is never sanctioned. A stated gap is a complete answer.
297 
298---
299 
300## Reference files
301 
302- [`references/qa-report-template.md`](references/qa-report-template.md) - Markdown report template for standard and full audits.
303 
View all files on GitHub →

Details

Updated
Sep 15, 2026
License
MIT
Stars on the repo
★ 901
Checked
Source
rampstackco/claude-skills ↗
Creator
rampstackco · 60 listings
View creator

Made with qa-testing

QA testing — Showcase grid filtered by Tone equals Provocative and Sensory equals Resonant, showing eight matching brand cards with… (from the rampstackco/claude-skills README)
QA testing — Showcase grid filtered by Tone equals Provocative and Sensory equals Resonant, showing eight matching brand cards with… (from the rampstackco/claude-skills README)

by rampstackco

QA testing — Showcase grid with all four axis filters set to Provocative, Editorial Restrained, Coach, and Resonant, showing zero… (from the rampstackco/claude-skills README)
QA testing — Showcase grid with all four axis filters set to Provocative, Editorial Restrained, Coach, and Resonant, showing zero… (from the rampstackco/claude-skills README)

by rampstackco

QA testing — RampStack architecture diagram. A central navy hub card shows the RampStack mark with the subtitle 'Stack-agnostic… (from the rampstackco/claude-skills README)
QA testing — RampStack architecture diagram. A central navy hub card shows the RampStack mark with the subtitle 'Stack-agnostic… (from the rampstackco/claude-skills README)

by rampstackco

Similar skills

See all →
SkillThe Lighthouse Agentic Browsing fractionAgentic Browsing ReadinessAgriciDaniel/claude-seo · by AgriciDanielAudit and fix agent readiness: the Lighthouse Agentic Browsing fraction, accessibility tree for agents, robots.txt and Content-Signal for AI agents, WAF treatment of agent traffic, llms.txt, Markdown delivery, ai-catalog.json, /.well-known discovery files, and WebMCP tools. Exclude AI citability and brand signals (seo-geo) and commerce protocol depth (seo-ecommerce).★ 17.4k GitHub starsSkillReferring domains, anchor text distributionBacklink Profile AnalysisAgriciDaniel/claude-seo · by AgriciDanielBacklink profile analysis: referring domains, anchor text distribution, toxic link detection, competitor gap analysis. Works with free APIs (Moz, Bing Webmaster, Common Crawl) and DataForSEO extension. Use when user says backlinks, link profile, referring domains, anchor text, toxic links, link gap, link building, disavow, or backlink audit.★ 17.4k GitHub starsSkillConnect a CMS to notfair SEO tools/setup-cmsnowork-studio/notfair-plugin · by nowork-studioConnect a CMS to notfair SEO tools. Guides users through configuring WordPress, Strapi, Contentful, or Ghost — tests the connection, and writes credentials to .env.local. Once set up, seo-analysis automatically cross- references CMS content against Google Search Console data. Use whenever the user says "connect my CMS", "set up WordPress", "configure Strapi", "add Contentful", "connect Ghost", or "CMS setup". Also trigger if the user asks why no CMS data appears in a seo-analysis report.★ 3.9k GitHub starsSkillBacklink profile for any domainBacklink checkRyze-AI-Adgent/open-seo-mcp-skills · by Ryze-AI-AdgentBacklink profile for any domain — referring domains, authority, anchors, new/lost links, and a side-by-side vs a competitor. Use when asked "check my backlinks", "backlink profile of X", "who links to them", or "link gap vs competitor".★ 3.1k GitHub starsSkillOptimize Core Web Vitals for better page experienceCore Web Vitals optimizationaddyosmani/web-quality-skills · by addyosmaniOptimize Core Web Vitals (LCP, INP, CLS) for better page experience using field and lab evidence. Use when asked to "improve Core Web Vitals", "fix LCP", "reduce CLS", "optimize INP", "page experience optimization", or "fix layout shifts".★ 2.8k GitHub starsSkillRun an SEO page observation-action-review loopRun the SEO page looptsingyuai/growth-lab · by tsingyuaiRun an SEO page observation-action-review loop with persistent Memory by coordinating demand research, page creation, adversarial review, image generation, IndexNow submission, and performance review. Use when taking an SEO page from opportunity discovery through publication, measurement, iteration, or continuing a previous SEO loop from Memory.★ 2k GitHub stars

More from rampstackco

SkillRun a comprehensive WCAG accessibility audit coveringrampstackco/claude-skills · by rampstackcoRun a comprehensive WCAG accessibility audit covering perceivable, operable, understandable, and robust principles. Use this skill whenever the user wants to audit accessibility, review WCAG compliance, fix accessibility issues, prepare for accessibility certification, address an accessibility lawsuit risk, or systematically improve a site's accessibility. Triggers on accessibility audit, WCAG audit, a11y audit, accessibility compliance, ADA compliance, screen reader test, keyboard navigation, accessibility report, fix accessibility, axe scan. Also triggers when accessibility issues have been reported and need systematic remediation.★ 901 GitHub starsSkillOptimize content and site structure for AI-driven searchAEO and GEOrampstackco/claude-skills · by rampstackcoOptimize content and site structure for AI-driven search experiences including AI overviews, large language model citations, generative answer engines, and AI assistants. Use this skill whenever the user wants to optimize for AI search, get cited by language models, appear in AI overviews, build llms.txt, structure content for AI extraction, or future-proof their SEO for the shift from blue links to AI answers. Triggers on AEO, GEO, AI search, AI SEO, AI overview, generative search, LLM optimization, llms.txt, AI citation, ChatGPT search, Perplexity, Gemini, Claude search, AI assistant optimization, answer engine. Also triggers when the user expresses concern about AI eating their organic traffic or wants to understand how to remain visible as search shifts.★ 901 GitHub starsSkillRun a structured after-action review on a launch, incidentAfter action reportrampstackco/claude-skills · by rampstackcoRun a structured after-action review (postmortem, retrospective) on a launch, incident, or completed project to capture timeline, root cause analysis, contributing factors, and actionable lessons. Use this skill whenever the user wants to run a postmortem, retrospective, AAR, or after-action review on any past event. Triggers on after-action report, AAR, postmortem, retrospective, retro, post-incident review, what went well what didn't, lessons learned, blameless postmortem, root cause analysis, RCA, five whys. Also triggers when the user has just shipped something or just resolved an incident and wants to capture learnings.★ 901 GitHub starsSkillDesign measurement frameworks including event taxonomyAnalytics strategyrampstackco/claude-skills · by rampstackcoDesign measurement frameworks including event taxonomy, KPI hierarchy, dashboard architecture, attribution models, and analytics implementation strategy. Use this skill whenever the user wants to plan analytics, design dashboards, build event taxonomies, define KPIs, set up tracking, or audit existing measurement. Triggers on analytics strategy, measurement plan, event taxonomy, tracking plan, KPI framework, dashboard design, north star metric, attribution model, conversion tracking, GA4 setup, Mixpanel setup, analytics audit. Also triggers when the user has data but no clear way to use it, or wants to make decisions but doesn't know what to track.★ 901 GitHub starsSkillDirect visual and creative work for campaigns, photographyArt directionrampstackco/claude-skills · by rampstackcoDirect visual and creative work for campaigns, photography, illustration, video, and branded experiences. Use this skill whenever the user wants to brief a photographer, direct illustrators, plan a creative campaign, develop visual concepts, or evaluate creative work for fit. Triggers on art direction, photo brief, photography brief, illustration brief, campaign concept, creative concept, visual direction, mood board, look and feel, visual treatment, video direction. Also triggers when the user has approved brand identity but needs to extend it into specific creative deliverables. Use `creative-direction` instead when the ask is the project-wide aesthetic brief that this skill consumes as input.★ 901 GitHub starsSkillPlan and run backups, set recovery objectivesBackup and disaster recoveryrampstackco/claude-skills · by rampstackcoPlan and run backups, set recovery objectives, and run disaster recovery drills. Use this skill when defining RPO/RTO targets, designing backup architecture, deciding what to back up and how often, planning for full-region or platform outages, or running a restoration drill. Triggers on backup, restore, RPO, RTO, disaster recovery, DR, business continuity, what if the database is gone, what if our hosting goes down, recovery drill, ransomware planning. Also triggers when an incident reveals a gap in restoration capability.★ 901 GitHub stars