Skills: a set of steps loaded only when the matching task appears

Skill: loaded only when needed

1You ask2AI matchesSkill descriptions3Loads onlythat Skill4Follows its steps

A Skill is .claude/skills/name/SKILL.md. The description says "what it does + what the user would say"; Claude uses it to decide whether to read the body, so it costs no context normally. Guests can see the full content of the 5 Skills below.

.claude/skills/acceptance-criteria/SKILL.md Download
---
name: acceptance-criteria
description: "Use when writing the acceptance criteria of a requirement/feature (what counts as done and correct): turn requirements into testable yes/no clauses with Given-When-Then, about 5 per group, covering normal path + error + boundary + permissions, and state how each is verified. Triggers on 'acceptance criteria', 'how do we know it is done', 'write test cases', 'make the requirement clear'."
---

# How to write acceptance criteria

## Principles
- Good criteria are clear, specific and testable; two people reading them reach the same pass/fail.
- Given-When-Then: Given = the state before the action, When = what the user does, Then = the change that must be seen.
- Every clause must answer "how do we test it?"; if it cannot be tested, rewrite it. Turn "must be fast" into "opens within 3 seconds on a normal connection".
- About 5 clauses per group at most; more means several features, so split.
- Cover: normal path, error state, boundary cases, permission rules. Each clause independent with a clear yes/no.
- Write the result from the user's or business's view, not the implementation.

## Extras (pitfalls we hit)
1. After each clause write "Verification": automated test / browser automation (phone and PC widths) / needs a human eye / needs a real device; if it cannot be done, honestly write "not verified".
2. For "A cannot see B / A does not affect B" (multi-user, language isolation) there must be a reverse case: really try with B's identity.
3. Use numbers where possible: no horizontal overflow = `scrollWidth <= clientWidth`; after release confirm 200 with `curl`.
4. Whatever can be automated goes into a test script and is run after every change.

## Template
```
Feature: <name>
Acceptance criteria (<=5):
1. Given <state> When <action> Then <result>   Verification: <method>
2. (error) Given ... When ... Then ...
3. (boundary) ...
4. (permission/isolation) Given users A and B When B logs in Then B cannot see A's data   Verification: automated test (two sessions)
```

## Example: multi-user
1. Given user A has favourites When B logs in Then B's favourites are empty   Verification: automated test
2. Given B changes their own settings When A refreshes Then A's settings are unchanged   Verification: automated test
3. Given not logged in When visiting another user's data endpoint Then 401 is returned   Verification: automated test
.claude/skills/deploy-verify/SKILL.md Download
---
name: deploy-verify
description: "Fixed procedure to deploy website/service changes to your own server and verify them: back up -> syntax check -> upload -> restart -> curl online -> click through in a browser -> write a record. Use when the user says 'deploy', 'go live', 'push to the server', 'roll back', 'restart the service'. If unsure, do not deploy; ask the user first."
---

# Deploy + verify (do every step, do not skip)

First write into the project `CLAUDE.md`: server address, deploy directory, service name, domain. If missing, ask the user; do not guess.

1. **Back up**: `ssh <server> "mkdir -p <dir>/.bak_<date> && cp <files to change> <dir>/.bak_<date>/"`. Rollback = copy back + restart.
2. **Syntax check**: Node `node --check <file>`, Python `python -m py_compile <file>`. If front-end JS changed, add 1 to the `?v=` version where the page references it (avoid cache), and bump the parent file that references it too.
3. **Upload**: `scp` to the directory. Before changing nginx back it up, run `nginx -t`, then `systemctl reload nginx`; only add your own server/location, never touch others'.
4. **Restart** (only if the backend changed): `systemctl restart <service> && systemctl is-active <service>`.
5. **Verify online**: `curl -s -o /dev/null -w "%{http_code}" <url>` for key URLs (home, API, new images and static files; if one is 404, check the other files in the same directory); then really click through with browser automation.
6. **Report**: state what was NOT tested (real phone, concurrency, ...); never write untested things as "verified".
7. **Record**: add 3-5 lines to the project `CLAUDE.md` (what changed, backup directory, what was not tested).

## Red lines
- On live data delete only test records **you created yourself**; never DELETE a whole table or wipe it.
- Do not touch another project's nginx config.
- Never put passwords/tokens in a skill, a reply or git; keep secrets in `secrets/*.env` (in `.gitignore`); at run time the environment variables on the server are the authority.
- Heavy jobs (video transcoding, big downloads) one at a time, check memory with `free -m` first.
- When unsure or suspecting a problem: do not deploy, confirm with the user.
.claude/skills/skill-writer/SKILL.md Download
---
name: skill-writer
description: "Process for writing a new skill or improving an existing one: decide whether it is worth writing, how to split it (entry SKILL.md + sub-files read on demand), how to write trigger words in the description, how to keep it small. Use when the user says 'write a skill', 'turn this into a skill', 'the skill did not trigger', 'the skill is too big'."
---

# Writing a skill

## 0. First decide if it is worth it
Worth it: the same kind of job done >=2 times with fixed steps; pitfalls that can become a checklist; reusable scripts.
Not worth it: done once; already covered by a rule or command; just a pile of links (links cannot be searched or triggered, so the key points must be in the body).

## 1. Structure
- One skill = one folder, entry `SKILL.md`, starting with `name` (same as the folder) + `description`.
- Simple ones need only one SKILL.md. Complex ones: the entry holds only "routing + key rules", details go to `references/*.md`, fixed actions to `scripts/*.py`, and the body says "when to read which file".
- Treat scripts as black boxes: the body says "run --help first, do not read the source".

## 2. The description decides whether it triggers
- One paragraph: "what it does + what the user would say"; list the words users really use.
- Also say when it should NOT trigger.
- At most about 600 characters.

## 3. Size
Entry SKILL.md target <=5KB, hard limit 12KB; above that, split into references.

## 4. Must do after writing
1. Find a real task that triggers it once and check it behaves as intended.
2. Add one line to the project `CLAUDE.md` with the skill name.
3. Never store keys/passwords in a skill (paths may be written, values not).

## 5. Where to put it
- Personal, for all projects: `~/.claude/skills/<name>/SKILL.md`
- Only for one project: `.claude/skills/<name>/SKILL.md` inside the project
.claude/skills/web-standards/SKILL.md Download
---
name: web-standards
description: "Read before building or changing any website/page: follow common industry practice (accessibility WCAG, responsive layout, forms, performance, settings-page conventions); deviations must be written into the design doc. Use when the user says 'make a web page', 'change the site', 'the UI looks bad', 'the phone display is wrong', 'where do settings go'."
---

# Common web standards (short version)

Use common industry practice by default; when deviating, write "why it is designed this way" in the project `DESIGN.md`.

## Layout and responsive
- `<meta name="viewport" content="width=device-width, initial-scale=1">` is mandatory.
- No fixed pixel widths for containers; give flex children `min-width:0` so they cannot blow out; long text `overflow-wrap:anywhere`.
- Put tables and code blocks in a horizontally scrollable container; the whole page must not get a horizontal scrollbar.
- After changing, measure `scrollWidth <= innerWidth` at two widths (about 390 and 1400).

## Accessibility (common WCAG 2.2 points)
- Body text contrast >= 4.5:1; do not express state by colour alone.
- Every clickable element reachable by keyboard with a visible focus; targets >= 24px (44px recommended on phones).
- Images have alt; form inputs have a label; error messages explain the cause and how to fix it.
- Dialogs: closable with Esc, focus moves in when opened and back to the trigger when closed.

## Forms and interaction
- One main action per page; dangerous actions (delete) need a second confirmation that states the consequence.
- Do not clear what the user already typed; disable the button on submit to prevent double submission.

## Settings page conventions
- Order: common -> appearance/language -> account/data -> about (version and updates).
- Put the version number and the update entry in "About".

## Performance and caching
- Compress images, lazy-load; static resource URLs carry a `?v=` version, bump it when changed.
- After deploying confirm key resources return 200 with `curl`.
.claude/skills/webapp-testing/SKILL.md Download
---
name: webapp-testing
description: "After changing the web front end/back end, verify that it really works online: two viewports (phone about 390 / PC about 1400) for horizontal overflow, JS errors in the console, click through the key flow, save screenshots in the project folder. Use when the user says 'test it', 'verify', 'the phone display is wrong', 'check it online after the change', 'Playwright', 'screenshot'."
---

# Web verification (online first)

## Method
Use Playwright (`pip install playwright && playwright install chromium`, or the Node version) against the **real URL**:

1. Open it once in each of two viewports: `390x844` (phone) and `1400x900` (PC).
2. Wait for the page to settle (`wait_for_load_state('networkidle')`).
3. Measure horizontal overflow: `document.documentElement.scrollWidth > innerWidth` means overflow.
4. Collect console errors: list the count and the first 5.
5. Click through the key flow (login, submit, switch language, ...); prefer id or text selectors.
6. Take screenshots and save them in **the project's own folder** with a full absolute path.

Minimal example (Python):
```python
from playwright.sync_api import sync_playwright
URL = "https://your-url/"
with sync_playwright() as p:
    b = p.chromium.launch(headless=True)
    for name, w, h in [("phone", 390, 844), ("pc", 1400, 900)]:
        pg = b.new_page(viewport={"width": w, "height": h})
        errs = []
        pg.on("console", lambda m: errs.append(m.text) if m.type == "error" else None)
        pg.goto(URL); pg.wait_for_load_state("networkidle")
        sw = pg.evaluate("document.documentElement.scrollWidth")
        print(name, "scrollWidth", sw, "viewport", w, "overflow" if sw > w else "ok", "errors", len(errs))
        pg.screenshot(path=f"/full/absolute/path/{name}.png")
    b.close()
```

## Must follow
1. Screenshots use a full absolute path in the project folder; never leave them in the root directory.
2. Do not change the user's real data: create test data yourself and delete it yourself; never DELETE a whole table.
3. Local pass != online works: after deploying run it again on the real URL; for new images or other binaries confirm each with `curl` for 200.
4. The feel on a real phone, the microphone, orientation lock cannot be tested by the script; write "not tested: ..." in the report, never "verified".

Extra Skills after sign-in