The AI Web
Skills logo

Skills · 9

Claude Code skills for web work. Paste one file, get a repeatable job done.

Filter

Turn a customer problem into three to five How Might We statements, then into specific website ideas for each one, with where it goes and how you would test it.

Claude Code skill, one file, no tools needed

FitsReach for it when a request arrives as a complaint or as somebody's pet solution, and before any session where a group is about to generate ideas. It needs no data and no tools, so it works on day one of a project.

1---
2name: hmw-generator
3description: Turn a customer problem into How Might We statements and concrete
4 website ideas for each. Use when you have a problem and need experiment
5 directions rather than another discussion.
6argument-hint: [the customer problem]
7---
8
9# How Might We generator
10
11A How Might We statement turns a problem into an opportunity that a group can
12answer. Broad enough to invite ideas, narrow enough to constrain them, aimed at
13something you can actually change.
14
15## 1. Understand the problem
16
17Gather, or ask for, the four things that make the rest possible:
18
19- which audience it affects
20- what evidence there is, with the source
21- where in the funnel it happens
22- what it costs the business
23
24If a problem file already exists, read it rather than re-asking. Read the
25audience notes too. Ideas written without knowing who they are for are how a
26session ends with twelve variations of the same headline.
27
28## 2. Write 3 to 5 statements
29
30The formula:
31
32> How might we [verb] [audience] [outcome they want] [on the site]?
33
34A good one describes a user need, implies the site as the lever, opens up
35possibilities, and contains no solution. "How might we add a comparison table"
36is a plan someone already made.
37
38Six lenses, to get genuinely different statements rather than one statement
39five times:
40
41| Lens | The question it asks |
42| --- | --- |
43| Amplify the good | how might we do more of what already works here? |
44| Remove the bad | how might we take the friction out entirely? |
45| Explore the opposite | what if we did the reverse of what we do now? |
46| Question the assumption | what if the thing everyone believes is not true? |
47| Change the moment | what if this happened at a different point in the visit? |
48| Split the audience | what if different people need different answers? |
49
50## 3. Ideas for each statement
51
523 to 5 per statement, each with three lines:
53
54- **The idea.** One or two sentences, specific.
55- **Where.** The page, component or flow it touches.
56- **How we would test it.** The validation, named.
57
58Push across the categories rather than staying in one: copy and messaging,
59layout and hierarchy, social proof, functionality, personalisation, friction
60removal, trust signals. A list of seven copy tweaks means the lenses were not
61used.
62
63## 4. Recommend three next steps
64
65- **Quick win.** Lowest effort with real learning in it.
66- **High impact.** The one that addresses the cause rather than the symptom.
67- **De-risking test.** The cheap test that validates the assumption under the
68 expensive idea, before anyone builds the expensive idea.
69
70## Output
71
72Save it dated, one file per problem, so the ideas that did not get built are
73still findable when the problem comes back. Close with what it connects to: the
74related problems, the ideas ready to become hypotheses, and the ones that need
75copy written first.
76
77Never invent evidence. If the impact number would strengthen the case and
78nobody has it, write that it is missing and carry on.

Turn a rough page idea into a brief you can hand to a builder, or to Claude: who it is for, what sections it needs, and what each one has to say.

Claude Code skill, one file, no dependencies

1---
2name: page-brief
3description: Turn a rough page idea into a build-ready brief. Use when someone
4 asks for a new landing page, product page or pricing page and the goal,
5 audience or sections are still vague.
6---
7
8# Page brief
9
10Ask for the one thing you cannot infer: who the page is for. Infer the rest
11from the site you are in.
12
131. Read the site's existing pages for voice, section rhythm and component set.
142. Name the page's single job in one sentence. If it has two jobs, split it.
153. Draft the section list. For each: the reader's question, the answer, the
16 proof, the next action.
174. Write the headline three ways - plain, specific, and short - and pick one.
185. List every component the page needs that does not exist yet.
19
20Output the brief as markdown. No lorem, use real copy candidates.
21Never invent numbers, metrics or customer names.

Find out what structured data your site already publishes, one page type at a time, then get the JSON-LD that fixes what is wrong or missing.

Claude Code skill, runs against any live site

FitsReach for it before a launch, after a migration, or when rich results disappeared and nobody changed anything on purpose. It runs against any site you can load in a browser, including one you did not build.

1---
2name: schema-audit
3description: Audit a site's structured data one page type at a time - what is
4 there, what is wrong, what is missing - and write the JSON-LD that fixes it.
5 Use before a launch, after a migration, or when rich results disappeared.
6---
7
8# Schema markup audit
9
10Structured data is the part of a page written for machines: a block of JSON
11saying "this is an article, published on this date, by this person". Search
12engines and assistants read it to decide what a page is. This checks what a
13site currently says about itself, then writes what it should say.
14
15## 1. Pick one URL per page type, not every URL
16
17A site with 400 pages has maybe six page types: home, listing, entry, article,
18author, contact. Structured data comes out of a template, so a fault on one
19product page is a fault on all of them.
20
21List the types first, pick one live URL for each, and say in the report which
22URL stands for which type. If a type has two shapes (an article with a video,
23an article without), that is two URLs.
24
25## 2. Read what is actually there
26
27For each URL, load the page in a browser and pull:
28
29- every JSON-LD block, parsed, plus any microdata or RDFa left in the markup
30- the type of each node and the id links between them
31- whether the blocks form one connected graph or several islands that never
32 refer to each other
33
34Render the page before reading it. Structured data that only exists after
35hydration is data a crawler may never see, and that is itself a finding worth
36reporting.
37
38## 3. Check each block against the page
39
40Three questions per block, in this order:
41
421. Does the type match what the page is? An About page marked up as an Article
43 is a wrong answer, not a partial one.
442. Does every claim in the markup appear on the page? A rating nobody can see,
45 a price the page does not show, an author with no byline. This is the fault
46 that earns manual actions, and it is the most common one.
473. Are the required properties present, and the recommended ones the page
48 already has the material for?
49
50## 4. Report the faults with the reason
51
52Per page type, worst first, in this order: wrong type, invented claim, missing
53required property, missing recommended property, no markup at all.
54
55Give each fault a sentence a non-specialist can act on. "Article needs
56dateModified" is not a reason. "Without dateModified, a post you rewrote last
57week still competes on the date it was first published" is.
58
59## 5. Write the fix
60
61Output JSON-LD per page type, not per page, with the variable parts marked so
62it drops into the template.
63
64- one connected graph per page: Organization and WebSite declared once with
65 stable ids, everything below referring to them
66- author as a reference to a Person id, never a bare string
67- every URL absolute, every date ISO 8601, every id resolvable in the graph
68
69Never propose Review or AggregateRating unless real ratings exist and a visitor
70can see them on the page. Marking up ratings you do not have is the fastest way
71to lose rich results altogether.
72
73Validate the output before handing it over, and say what you validated it with.
74

Run this against a site before it goes public and it tells you what would stop it being found: a missing description, a redirect that loops, a sitemap that lists a 404.

Claude Code skill, reads the built pages and probes the live host

FitsRuns the day before a launch and again the hour after the domain is attached, because the second run is the one that catches the host. It reads the pages your build produced, so it works on any framework that outputs HTML, and it probes the live URL with plain requests, so it works on any host. Pair it with the schema audit when the structured data itself needs rewriting rather than checking.

1---
2name: launch-check
3description: Check a site before it goes public, the way a crawler will see it.
4 Reads the built pages for title, description, canonical, H1, og:image and
5 JSON-LD, probes the live host for redirects and stray noindex headers, and
6 checks robots, sitemap and llms.txt against each other. Use the day before a
7 launch and again once the domain is attached.
8---
9
10# Launch check
11
12Read what ships, never what was meant to ship. Passing typecheck, lint and
13build says nothing about the HTML a crawler receives. Every check below runs
14against built output or a live URL.
15
16## 1. Establish what is supposed to exist
17
18Before checking anything, find out:
19
20- the canonical origin, including the www or apex decision (one constant in
21 the code, a config value, or ask). Every absolute URL below is checked
22 against it
23- the list of public routes: the sitemap if there is one, otherwise the
24 route files or the content data. Note routes that are deliberately kept
25 out of the index and why (a redirector, an internal asset page, the 404)
26- whether the site is live yet, because a pre-launch site is allowed to
27 carry a noindex header and a live one is not
28
29Say which of these you had to guess. A wrong canonical host makes every
30other result wrong.
31
32## 2. Check every route from the built HTML
33
34Read the build output (`.next/server/app` for Next.js, `dist/` for Astro,
35`out/` or `build/` elsewhere), or fetch each live URL. Per page:
36
37| Check | Pass |
38|---|---|
39| `<title>` | present, unique across the site, the page's subject in the first words |
40| `meta description` | present, 140-160 characters, hand-written, not repeated on any other page, not the same text as the visible summary |
41| `link rel=canonical` | present, absolute, on the canonical origin, points at this page |
42| `<h1>` | exactly one |
43| `og:image` | present, absolute, returns 200 |
44| JSON-LD | every block parses; see step 5 |
45| Links | at least one internal link in from another page, one out |
46
47Routes kept out of the index still need a title and one H1, and are exempt
48from the rest. A description of 36 characters is a failure, not a partial
49pass. A description that falls back to the summary already on the page is a
50failure that the page's author has to fix by writing one.
51
52## 3. Check the site files against each other
53
54- `robots.txt`: allows crawling, names the sitemap with an absolute URL,
55 disallows only what is meant to be disallowed. If AI crawlers are
56 blocked, confirm that was a decision and not a default
57- `sitemap.xml`: every URL is absolute, on the canonical origin, answers
58 200 without a redirect, and carries a last-modified date that is the day
59 the content changed, not the build time. Every public route is in it.
60 Nothing that is noindex is in it
61- `llms.txt`, if the site has one: lists the same pages the sitemap does
62- a made-up path returns HTTP 404, not a 200 page that says "not found"
63
64The sitemap and llms.txt should be generated from the same list the pages
65come from. If they are maintained by hand, say so in the report: that is the
66fault that lets a new page ship without being in either.
67
68## 4. Probe the host
69
70Run these against the live site and record the status line and the headers
71that matter. Replace the host.
72
73```sh
74for url in \
75 https://www.example.com/ \
76 https://example.com/ \
77 http://www.example.com/ \
78 http://example.com/ \
79 https://example-project.vercel.app/ ; do
80 printf '%s\n' "$url"
81 curl -sI -o /dev/null -w ' %{http_code} -> %{redirect_url}\n' "$url"
82done
83
84curl -sI https://www.example.com/ | grep -i -E 'x-robots-tag|content-type|strict-transport'
85curl -sI https://www.example.com/no-such-page | head -1
86curl -sI https://www.example.com/sitemap.xml | head -1
87```
88
89Pass:
90
91- the canonical origin answers 200
92- the twin host (apex when www is canonical, or the reverse), both http
93 variants and every preview or platform host answer 301 or 308 straight to
94 the canonical URL, in one hop, keeping the path
95- no live response carries `x-robots-tag: noindex`. A launch flag or
96 middleware that added this before launch has to be off on the production
97 deployment, not just in the code
98- the unknown path is a 404 and the sitemap is a 200
99
100A redirect chain of two hops is a fail. A preview host that serves the site
101with a 200 is a fail: it is a duplicate of every page under a second origin.
102
103## 5. Check the structured data
104
105Parse every `application/ld+json` block on every route.
106
107- every block parses, and the page has at least one
108- `Organization` and `WebSite` appear once, declared with stable `@id`s,
109 and nothing restates them on a lower page
110- every page below the home has a `BreadcrumbList`
111- one node's `@id` is the page's canonical URL. Without it the page has the
112 site's graph and none of its own
113- no `@id` is defined twice
114- no `Review` or `AggregateRating` unless real ratings exist and a visitor
115 can see them on the page
116- articles: `author` is a reference to a `Person` node, not a string, and
117 `datePublished` plus `dateModified` match the visible dates
118
119For one URL per page type, run the Rich Results Test and the Schema.org
120validator and quote what they said. If the markup itself needs rewriting,
121hand over to the schema-audit skill rather than patching it here.
122
123## 6. Report, worst first
124
125Three grades, in this order:
126
1271. **Blocking** - keeps a page out of the index or sends a visitor to the
128 wrong place: a live noindex header, a preview host serving 200, a
129 sitemap URL that 404s, a canonical on the wrong origin, a redirect loop
1302. **Fix before launch** - the per-page set from step 2 and the graph
131 rules from step 5
1323. **Noted** - fine today, wrong after the first change: slugs with no
133 redirect map, sitemap dates that equal the build time, a hand-maintained
134 route list
135
136Each line: the route, the fault, and what it costs in one sentence a
137non-specialist can act on. "No canonical" is not a reason. "Without a
138canonical, the www and apex copies of this page compete with each other" is.
139
140## 7. Leave a gate behind
141
142Turn step 2 and step 5 into a script in the project's own language that
143reads the build output and exits non-zero with the list. Put it in CI after
144the build. It should fail on: no title, duplicate title, description outside
145140-160 or repeated, missing or relative canonical, H1 count other than one,
146missing og:image, JSON-LD that does not parse, no node at the page's own URL,
147any rating markup.
148
149When a page fails the gate, the fix is the page. Never widen the rule to get
150a green build.
151
QA pass logo

QA pass

03 Sept

Put a page through the same checks every time: how it holds up at seven screen widths, what the markup says, whether anyone on a keyboard can get through it, and whether the words are right.

Claude Code skill driving Playwright through its MCP server

FitsReach for it before you publish, after a redesign, and on the page a client says looks off without being able to say why. What comes back is a list of faults with a fix attached to each one, not a folder of screenshots you still have to read yourself.

1---
2name: qa-pass
3description: QA a live page across seven breakpoints. Checks content, links,
4 layout, accessibility and technical basics, then writes a prioritised report
5 with a paste-ready line per issue. Use before launch, after a redesign, or on
6 any page someone says looks off.
7argument-hint: <url> [quick|deep|focus:<category>]
8---
9
10# QA pass
11
12One URL in, one prioritised report out. Same checks every time, so two runs a
13month apart are comparable.
14
15**What you need:** the Playwright MCP server, and nothing else. No install into
16the site you are checking, no script to place, no repo access. It works against
17any URL you can load, including a site you did not build and cannot deploy to.
18
19## Step 1 - load the page in a real browser
20
21Drive Playwright, never a plain fetch. Half of what breaks only exists after
22JavaScript runs, and a fetch will not see it.
23
24Accept the cookie banner before anything else, with a text selector rather than
25a snapshot reference: snapshot refs go stale between calls and the click fails
26silently.
27
28## Step 2 - sweep seven breakpoints
29
30Smallest to largest, every run, whatever device the request named:
31
32| Width | Represents | Screenshot |
33| --- | --- | --- |
34| 330px | smallest common phone | yes |
35| 375px | mobile baseline | yes |
36| 768px | tablet portrait | yes |
37| 1024px | tablet landscape | overflow check only |
38| 1280px | desktop baseline | yes, full page |
39| 1440px | large desktop | overflow check only |
40| 1920px | full HD desktop | yes, full page |
41
42At each width run this through the MCP server's evaluate call. Run it as
43written rather than improvising the check, so a run today and a run in a month
44are answering the same question:
45
46```js
47() => ({
48 // A false here with elements listed below does NOT mean clipping: a
49 // container with overflow-x hidden suppresses the bar. Check the shot.
50 hasHorizontalScroll:
51 document.documentElement.scrollWidth > document.documentElement.clientWidth,
52 past: [...document.querySelectorAll("*")]
53 .filter((el) => el.getBoundingClientRect().right > window.innerWidth + 5)
54 .slice(0, 10)
55 .map((el) => ({
56 tag: el.tagName,
57 class: el.className?.toString().slice(0, 60),
58 right: Math.round(el.getBoundingClientRect().right),
59 })),
60})
61```
62
63These are representative widths, not every pixel. If someone reports a break at
64850px, resize to 850px and look, rather than trusting the sweep.
65
66Reset to 1280px before the content checks. Capture the accessibility tree and
67the console messages once, at that width.
68
69## Step 3 - the two rules that keep a report honest
70
71**Verify visually before reporting.** Code tells you what the DOM says, the
72screenshot tells you what a visitor sees. If you cannot see the problem in the
73screenshot, it does not go in the report.
74
75**Know the false positives.** Three that catch every new run:
76
77- No horizontal scrollbar plus overflowing elements does not mean clipping. A
78 container with overflow-x hidden suppresses the bar while the element still
79 extends past the viewport. Check the screenshot.
80- innerText returns empty for anything hidden or mid-animation, including links
81 inside a collapsed accordion. Read textContent before calling a link empty.
82- Keep a written ignore list of the patterns that are fine on this site, and
83 cite it in the report. A report that cries wolf twice gets skimmed the third
84 time.
85
86Expand every accordion individually, wait for the animation to settle, and
87screenshot the open state before reading what is inside.
88
89## Step 4 - check these, at 1280px
90
91**Content.** Spelling and grammar in visible copy, placeholder text left behind
92(lorem, TBD, {{key}}, %s), stale dates and old product names, inconsistent
93terminology, contradicting statements.
94
95**Links and CTAs.** Broken links, links pointing at staging or localhost, empty
96anchors with no text and no image, CTA text that says only "read more", a
97primary CTA that is missing or below the fold.
98
99**Layout.** Broken or stretched images, text overflow and truncation, misaligned
100or overlapping elements, inconsistent button styles, heading sizes that do not
101match the hierarchy.
102
103**Accessibility.** Images with no alt, links with no descriptive text, form
104inputs with no label, visibly low contrast, focus that disappears on tab.
105
106**Technical.** One evaluate covers everything a screenshot cannot show you.
107Read the console messages separately, and check for a consent banner where the
108law needs one:
109
110```js
111() => {
112 const meta = (sel, name) => document.querySelector(sel)?.getAttribute(name) ?? null;
113 return {
114 title: document.title,
115 description: meta('meta[name="description"]', "content"),
116 canonical: meta('link[rel="canonical"]', "href"),
117 robots: meta('meta[name="robots"]', "content"),
118 social: ["og:title", "og:description", "og:image", "twitter:card"].map((p) => ({
119 tag: p,
120 content: meta(`meta[property="${p}"], meta[name="${p}"]`, "content"),
121 })),
122 headings: [...document.querySelectorAll("h1,h2,h3,h4,h5,h6")].map((h) => ({
123 level: Number(h.tagName[1]),
124 // textContent, not innerText: innerText is empty for anything hidden or
125 // mid-animation, which turns every collapsed accordion into a false alarm.
126 text: h.textContent.trim().slice(0, 90),
127 })),
128 imagesWithoutAlt: [...document.images]
129 .filter((i) => !i.hasAttribute("alt"))
130 .map((i) => i.currentSrc),
131 vagueLinks: [...document.querySelectorAll("a")]
132 .map((a) => a.textContent.trim())
133 .filter((t) => /^(click here|read more|learn more|here|more)$/i.test(t)),
134 emptyLinks: [...document.querySelectorAll("a[href]")]
135 .filter((a) => !a.textContent.trim() && !a.querySelector("img"))
136 .map((a) => a.href),
137 offsiteLinks: [...document.querySelectorAll("a[href]")]
138 .map((a) => a.href)
139 .filter((h) => /staging\.|dev\.|localhost/.test(h)),
140 unnamedControls: [...document.querySelectorAll("button,input,select,textarea")]
141 .filter(
142 (el) =>
143 !el.labels?.length && !el.getAttribute("aria-label") && !el.textContent.trim(),
144 )
145 .map((el) => el.outerHTML.slice(0, 120)),
146 jsonLd: [...document.querySelectorAll('script[type="application/ld+json"]')].map(
147 (s) => s.textContent,
148 ),
149 };
150}
151```
152
153Title present and roughly 50-60 characters, meta description present, all four
154social tags present, canonical correct, no console errors.
155
156**Shared regions.** Check the footer and the global nav once for the whole site,
157not once per page. They come from one template, so the same three issues on
158forty pages is one issue.
159
160## Step 5 - report only what is broken
161
162Nothing optional, no best-practice suggestions, no "consider adding". If it is
163fine it does not appear. Give every issue an ID (EN1, EN2, and EN1M for a
164mobile-only one) so a reviewer can reply "EN3 is by design" in one line.
165
166| ID | Category | Priority | Location | Issue | Fix | Paste |
167| --- | --- | --- | --- | --- | --- | --- |
168
169The last column is the whole issue in under 200 characters, starting with the
170ID and ending with a sentence that starts "Fix:", so it drops straight into a
171message to whoever owns the page.
172
173Priorities: red for broken functionality, a typo in headline copy, a dead nav
174link or a severe accessibility failure. Yellow for anything a visitor will
175notice. Green and grey below that.
176
177Close with what is clean. The list of what passed is what makes the failures
178believable.
179
180## More than one language
181
182Every locale gets the same full checks, not a lighter scan. Practical order:
183establish the base language first, then the languages whose words run longest,
184where text expansion breaks layouts at 330 and 375px. Use one small evaluate
185per locale for title, H1 and a body excerpt, and pull a full snapshot only
186where that flags something.
187
188A fault in a template is one systemic issue affecting every locale, not one
189issue per locale. Say it once.
190
191Always state the limit: translation accuracy needs a native speaker. This pass
192covers structure, layout and completeness only.

Before you build a test, find out whether your team already ran it. It searches the finished tests, weighs each one by how recent and how proven it is, and tells you to proceed, change it, or think again.

Claude Code skill, reads your test record or learnings file

FitsReach for it the moment an idea is proposed, not after it is built. Test hypothesis runs it automatically as step zero, and it works standalone when somebody asks in a meeting whether a thing has been tried.

1---
2name: learnings-check
3description: Check a proposed test idea against everything the team has already
4 learned, weighted by how recent and how proven each past result is. Returns a
5 verdict. Run it before any hypothesis gets written.
6argument-hint: [brief description of the test idea]
7---
8
9# Learnings check
10
11The read side of a team's memory. Before an idea becomes a hypothesis, check it
12against what has already been tested, so nobody re-runs a loser, re-litigates a
13settled question, or ignores a pattern that already works.
14
15## Step 1 - query the record, most recent first
16
17Pull concluded tests from wherever the raw record lives: the testing tool, the
18experiment tracker, or the learnings file. Filter to the ones touching the same
19page, element or zone as the idea.
20
21If the live record is unreachable, fall back to the written digest and say so.
22A verdict from a digest is not a verdict from the data.
23
24**If there is no record yet**, say that plainly and return PROCEED. A team on
25its first test has no prior art and does not need to pretend otherwise. Then do
26the one useful thing available: start the file, so the second test has something
27to check against. Everything below applies from the second test onward.
28
29## Step 2 - apply the recency policy
30
31Bucket every match by how old it is, relative to today:
32
33| Age | Weight | How to cite it |
34| --- | --- | --- |
35| Up to 6 months | primary | full weight |
36| 6 to 18 months | secondary | usable, but state the age out loud |
37| Over 18 months | stale | mention it exists, never cite it as evidence |
38
39A stale test alone never blocks an idea. Sites change, audiences change, old
40truths expire. Say "this was tested about two years ago, re-validate it" and
41move on.
42
43## Step 3 - tier every result you are about to cite
44
45Mandatory. Never present a bare claim.
46
47- **Proven.** Two or more tests point the same way, with strong statistics, and
48 recent. Reliable.
49- **Provisional.** A single clean result. Directionally useful, one test, not
50 law. Always cite it with that caveat.
51- **Weak.** Inconclusive, small sample, stale, or contradicted by another test.
52 Offer it as a re-test idea, never as evidence.
53
54A win that was never re-validated is Provisional, not Proven. Say so.
55
56## Step 4 - sort into four buckets
57
58Cite the test, its tier and its age every time.
59
601. **Repeats a recent loser.** A close paraphrase lost inside the last 18
61 months. Quote the test and the mechanism.
622. **Anti-pattern risk.** Contradicts a documented failure mode, even if this
63 exact thing was never tested.
643. **Already settled.** A recent win already shipped, or a recent inconclusive
65 in a zone known to produce no signal.
664. **Extends a validated winner.** Name it, tier it, and note that winners do
67 not always transfer between pages, audiences or markets.
68
69If nothing matches inside the recency window, say that plainly. A genuinely new
70idea is a valid outcome.
71
72## Step 5 - the verdict
73
74```
75Learnings check: <the idea in one line> (as of <today>, 6mo primary / 18mo cap)
76
77Recent loser - [test, tier, N months ago, what happened]
78Anti-pattern - [test, tier, mechanism]
79Already settled - [test, tier, N months ago]
80Builds on winner - [test, tier, effect, N months ago]
81Stale precedent - [test, over 18 months, re-validate, not cited as evidence]
82
83Verdict: PROCEED / PROCEED WITH CHANGES / RECONSIDER
84Why: <two or three sentences, every citation carrying its tier and age>
85Sharpen it by: <one concrete adjustment that respects the past results>
86```
87
88Omit any line that has nothing in it.
89
90- **RECONSIDER** only for a near-exact repeat of a recent, Provisional-or-better
91 loser, or a clear anti-pattern. Always pair it with a better alternative.
92- **PROCEED WITH CHANGES** when the idea is supported but risks a known failure
93 mode.
94- **PROCEED** when it is new, or when the only precedent is stale or weak.
95
96Be a guard, not a gate. Inform, never block. The person asking can always
97override you, and sometimes should.

Write an A/B test up properly before it gets built: who you are helping, what they are trying to do, what you are changing, why you think it will work, and what you will learn either way.

Claude Code skill, chains the learnings check first

FitsReach for it whenever somebody proposes a test, including the ones that sound obvious. Writing the hypothesis is what turns an opinion into something a result can disagree with.

1---
2name: test-hypothesis
3description: Write a structured hypothesis for an A/B test, after checking the
4 idea against what the team already learned. Use whenever someone proposes a
5 test or needs an experiment written up before it gets built.
6argument-hint: [brief description of the test]
7---
8
9# Test hypothesis
10
11## Step 0 - learnings check, first, always
12
13Run the learnings check skill on the idea before writing a word. It reads the
14concluded tests and returns a verdict: whether the idea repeats a known loser,
15trips a documented anti-pattern, is already settled, or extends a validated
16winner.
17
18- On **RECONSIDER**, show the block to the person who asked and confirm they
19 still want it before writing anything.
20- Otherwise carry the cited tests into the hypothesis. The previous-evidence
21 bullet below should name the specific past tests the check surfaced.
22
23Skipping this is how a team spends four weeks of traffic learning something it
24wrote down last spring.
25
26If you do not have that skill, do the search by hand before writing: grep the
27notes, the tracker, the old decks. Two minutes of searching beats four weeks of
28traffic. If there is genuinely nothing to search yet, say so in the hypothesis
29rather than leaving the evidence field looking answered.
30
31## The format
32
33### One-sentence summary
34
35We will try to help **who** to do **what** [when **specific conditions**] by
36changing **something**.
37
38### The detail
39
40We will try to help **who**
41
42- To do **what**
43- When **specific conditions** (only when there genuinely is a condition)
44- By changing **something**
45
46We will do this because:
47
48- **The reasoning.** Why this change should alter behaviour, stated as a
49 mechanism rather than a wish.
50- **The previous evidence.** Data, research or prior test results that support
51 it, named and dated. If there is none, the field stays empty and the
52 hypothesis says so.
53
54We are aiming to learn:
55
56- **A thing.** A specific question the result will answer.
57- **Another thing.** As many as genuinely apply.
58
59## Rules
60
61- **Who** is a real segment: new trial users, returning visitors on mobile,
62 people arriving from paid search. Not "users".
63- **What** is the job they are trying to do, in their terms.
64- **By changing** is specific enough to build from without another meeting.
65- Evidence is real or the field is empty. "We think people are confused" is not
66 evidence. A recording, a ticket count, an exit rate or a survey answer is.
67- Learnings are about behaviour, not just metric movement. "Does the metric go
68 up" is not a learning, it is the test.
69- Write the decision rule now: the effect worth having, the sample it needs,
70 how long that takes at current traffic, and what you do if the result is
71 flat. Deciding this after the numbers arrive is how flat results become wins.
72
73## Output
74
75The verdict from step 0, the hypothesis, and one line naming the smallest
76version of the test that would still answer the question.
77
78Save it next to the others, dated, one file per test, so the learnings check
79can find it in a year.

A test finished. Get ten specific things to try next, each with what changes, why it might work, and what success would look like, grounded in what the last one showed.

Claude Code skill, reads your whole knowledge base first

FitsReach for it at the decision point of every test, including the losers. A loss tells you the mechanism is real and pointed the wrong way, which is a better starting point than a blank page.

1---
2name: test-iteration
3description: Generate around ten specific iteration ideas for a concluded A/B
4 test, grounded in the hypothesis, the result and everything already known.
5 Use when a test has finished, whether it won, lost or went nowhere.
6argument-hint: [test name or result]
7---
8
9# Test iteration
10
11A finished test is an input, not a conclusion. This turns one result into the
12next ten things worth trying, with a reason attached to each.
13
14## Before generating anything
15
16Gather four things: the result (won, lost, inconclusive), the original
17hypothesis, what was learned and what was not, and which metrics moved.
18
19Then read the whole knowledge base, not a sample of it: every past learning,
20every note on the audience, every documented failure mode. Ideas that ignore
21what is already known are how a team runs the same test twice with a different
22button colour.
23
24## What separates a strong idea from a weak one
25
26| Weak | Strong |
27| --- | --- |
28| "Try different copy" | "Test an outcome-led CTA, because the original tested a feature rather than a benefit" |
29| "Make it bigger" | "Increase the CTA by 40% and add whitespace, since the original may have been lost in visual noise" |
30| "Test on mobile" | "Mobile-only test with the CTA in the thumb zone, since desktop won and mobile was flat" |
31
32Every idea answers three questions: what specifically changes, why it might
33work, and what success would look like.
34
35## Eight angles to generate across
36
371. **Intensity.** Dial the change up or down. Was it too subtle, or too much?
382. **Segment.** A different audience: device, new against returning, source.
393. **Timing.** The same change at a different moment in the visit.
404. **A different route.** Same problem, another solution entirely.
415. **Supporting elements.** Add or remove what sits around the change.
426. **Message.** A different value proposition or tone.
437. **Visual weight.** Hierarchy, prominence, contrast.
448. **The gaps.** Test what the last one failed to tell you.
45
46## Reasoning depth
47
48Each "why" carries three parts: the connection to what the last test showed,
49the supporting evidence (a past test, a documented behaviour, research), and
50the mechanism, which is the sentence explaining why this specific change should
51produce a different result.
52
53Without the mechanism it is a guess with a citation attached.
54
55## Output
56
57```
58[Test] - iteration ideas
59
60Original: [what ran]
61Result: [won / lost / inconclusive] - [headline metric]
62Learning: [one or two sentences]
63
64(1) [Title in sentence case]
65 Change: [what specifically changes]
66 Why: [connection, evidence, mechanism]
67 Success: [metric and direction]
68
69(2) ... through (10)
70
71Test first: (1), (2) - [why these]
72Worth exploring: (3), (4) - [why]
73If there is room: (5) to (10) - [why]
74```
75
76Number ideas as (1), (2), (3) rather than 1. 2. 3. - it survives being pasted
77into a tracker that mangles ordered lists.
78
79## Before you finish
80
81Check each idea: specific enough to build without another conversation, real
82reasoning rather than "let's try it", connected to what the last test showed,
83measurable, and not a repeat of something already run. That last one means
84running the learnings check over your own output.

Write a finished test up in four fixed sections, then decide what earns a place in the file everyone searches before proposing the next one.

Claude Code skill, two-part write-up and promotion

FitsReach for it as the last step of every test, wins and losses alike. Pair it with the learnings check: this one writes the file, that one reads it, and neither is much use without the other.

1---
2name: learnings-log
3description: Write up a concluded test in four fixed sections, then promote what
4 is worth keeping into the curated learnings digest with a confidence tier. Use
5 as the last step of every test, wins and losses alike.
6argument-hint: [test name or the result you just concluded]
7---
8
9# Learnings log
10
11Two jobs, in order. First write the outcome. Then decide what, if anything,
12earns a place in the digest the next hypothesis will search.
13
14## Part 1 - the outcome, in four sections
15
16Always these four, always in this order.
17
18**We learned:**
19
20- The findings that answer the original hypothesis, positive and negative.
21- At least one thing nobody expected, when there is one. Those are usually the
22 entries still being read in two years.
23
24**We did not learn:**
25
26- Something BECAUSE the reason. A bug, a planning miss, a sample that never
27 arrived, an external event, a window too short to see the metric that matters.
28- This section is the one people skip and the one that stops the result being
29 over-read later. An empty "we did not learn" almost always means it was not
30 thought about.
31
32**We now have these questions:**
33
34- Written as specific, testable questions. These become the next hypotheses.
35
36**So we are going to:**
37
38- Ship it, iterate on it, drop it, or run the complementary test. Name the
39 action and connect it to the learning above it.
40
41Keep two versions: the long one with the full context and numbers, and a short
42plain-text one that survives being pasted into a tracker with no formatting.
43
44## Part 2 - promote it, or do not
45
46The raw record already lives wherever tests are tracked. The digest is a
47curated file of proven and recent patterns, and it is only useful while it
48stays high signal. Most tests do not belong in it.
49
50Assign a tier first:
51
52- **Proven.** This corroborates a pattern already in the digest, or a follow-up
53 chain that held. Upgrade the existing entry, add this test's key to it, raise
54 its tier. Do not add a second entry saying the same thing.
55- **Provisional.** A single clean result, strong numbers, recent, never
56 re-validated. Add a new entry and label it provisional out loud.
57- **Weak.** Inconclusive, thin sample, or contradicted. No pattern entry. One
58 line in the "already run" list so nobody repeats it.
59
60Never inflate the patterns section with single tests dressed as law. A pattern
61earns the word proven by being validated twice, not by being written
62confidently once.
63
64Every entry carries a tier and a date, so a future reader knows how much to
65trust it without asking anyone.
66
67## Handling a result that contradicts an older one
68
69Do not edit the old entry to match the new one. Add a line under it naming the
70newer test and what changed. A log people can rewrite is a log nobody trusts,
71and the disagreement is often the most useful thing in the file.
72
73If three entries now say the same thing, promote them into one principle at the
74top of the file and link all three.
75
76## Before writing
77
78Show the proposed changes as a diff, section by section, tier visible, and wait
79for a yes. Then apply them as targeted edits rather than rewriting the file, so
80the ordering and curation survive.
81
82## The line that matters
83
84The learning sentence is the only part anyone reads in a year. It must be true
85beyond this page: "visitors who cannot find the price leave before they read
86the value proposition" transfers, "moving the price up lifted signups" does
87not. It must be falsifiable. And a flat or losing test gets one too, because
88those are the entries that stop repeats.

Free to use in your own work, paid work included, no attribution required. Not for repackaging into a product you sell. Full terms.