Frontend quality checks: TypeScript type check, linting, and the JS test suite (Vitest/Jest). Activate after editing JS/TS files. Triggers: eslint, typescript, tsc, type check, lint, vitest, jest, test:js, frontend tests, frontend checks.
php artisan boost:add-skill sandermuller/boost-skills
Save this content to: .claude/skills/frontend-quality/SKILL.md
# Frontend Code Quality
Run all frontend quality checks after making changes to JavaScript or TypeScript files. The static checks (type-check, lint) and the test suite must all pass before work is complete. A change that renders UI is also eye-verified in a real browser when a harness can run — and when one genuinely can't this session, that's an explicit deferral, not a silent skip.
## When to Use This Skill
Activate this skill when:
- JS or TS files have been created or modified
- Finalizing a feature, bug fix, or refactor that touched frontend code
- The user asks to run frontend checks, ESLint, or TypeScript checks
- Before creating a PR with JS/TS changes
- Applying review feedback or rework with JS/TS changes
- A change renders UI that should be *seen running*, not just type-checked
## Checks (Run in Order)
### 1. Type Checking
If the project uses TypeScript, run its type-check script with the project's package manager — it is defined in `package.json` (commonly a `type-check` script; the underlying command is usually `tsc --noEmit`):
```bash
npm run type-check # or: yarn / pnpm / bun — match the project's lockfile
```
Must show 0 errors. Fix any type issues found. Skip this check for a plain-JavaScript project with no type-checker.
### 2. Linting
Run the project's lint script — it runs whatever linter the project uses (ESLint, Biome, oxlint, …):
```bash
npm run lint # or: yarn / pnpm / bun
```
If the project uses **ESLint**, you can scope it to the changed files for speed instead of linting everything. Run the project-local ESLint via its package manager (`npm exec` / `pnpm exec` / `yarn` / `bunx`):
```bash
eslint --cache --cache-location ".cache/eslint/" <file1> <file2> ...
```
Must show 0 errors. Fix any linting issues found. Skip this check when `package.json` defines no lint script, or the project has no `package.json` — a server-rendered project may have templates and styles but no JS linter.
### 3. Tests
Run the project's JS/TS test suite — its script is in `package.json` (commonly `test`, or a dedicated script such as `test:js`; the underlying runner is Vitest, Jest, etc.):
```bash
npm test # or: yarn / pnpm / bun — match the project's lockfile
```
Must show 0 failures. Fix any failing tests. When the change added or altered testable logic, **add or update a test for it** before the work is done — the `test-writing` skill covers what to write and where. During development you can scope to the changed area (e.g. `vitest run <path>` for Vitest, `jest <path>` for Jest) and run the full suite at completion. Skip only when the project has no JS test setup.
### 4. Eye-verify — see UI changes run in a browser
If the change renders UI (not pure logic), type-check and lint aren't enough — runtime/visual
bugs (stale state, dead toggles, broken scroll / sticky behaviour, z-index show-through, async
races, untranslated keys) only show in a browser. Do it whenever a harness can run against the
change; if one genuinely can't this session (no running app, an external service that can't be
seeded), name the deferral in a NOT-VERIFIED list rather than reporting an unqualified green.
- **Follow the coverage contract, don't just "click around".** Derive the checklist first
(ticket steps, edge cases, design annotations), assert one testable per check, drive full
flows and mutations (create → round-trip → delete), and list what you couldn't verify. The
contract, the traps that fake a green run, fault injection, and the reproducible-harness-vs-
ad-hoc-browser decision are all in [`references/eye-verify.md`](references/eye-verify.md).
- **This skill ships a framework-agnostic harness** — `scripts/screenshot.mjs` (capture +
crop-to-selector with ≥15px padding), `scripts/console.mjs` (console/page errors + a leak
scan over text *and* screen-reader attributes + an optional `--axe` accessibility pass),
`scripts/auth-capture.mjs` (save a login session the others reuse via `--storage-state`), and
`scripts/lib.mjs` (helpers to write a drive-script: `createChecker` for the contract,
`capturePageIssues`, `withFailedRoute` for fault injection). See
[`scripts/README.md`](scripts/README.md); it needs Playwright in the project
(`npm i -D playwright && npx playwright install chromium`) and points at the *already
running* app. Use it, the project's own harness if it has one, or a Playwright MCP server.
- **Put the app into the state that reveals the change before capturing.** A feature that ships
*off* by default — behind a flag, a new column, or per-record opt-in — renders nothing until
enabled, so make the fixture sufficient first: run its migration, set the flag/field on a
seeded record, rebuild the frontend bundle if JS/CSS changed. Verify behaviour, not just
geometry; revert seeded test data after.
- When the change has an approved design, verify it **per element** and assert computed values
rather than eyeballing the whole image — see
[`references/design-verification.md`](references/design-verification.md).
- Here the browser pass is one step of the gate; when a change deserves a full, mandatory
browser pass — resolving the testables from the PR/issue/spec, driving every one, and
publishing the proof screenshots to the PR or issue — run that as its own flow rather than
ad hoc: the `eye-verification` skill (`/eye-verification`), where the project ships it.
See the `javascript` guideline ("Eye-verify frontend changes" and "Verify against the design, per element") for the why.
## Quick Reference
| Check | Command | Pass criteria |
|-------|---------|---------------|
| Type checking | `npm run type-check` (TypeScript projects) | 0 errors |
| Linting | `npm run lint` (the project's lint script) | 0 errors |
| Tests | `npm test` (the project's JS test script) | 0 failures |
| Eye-verify (UI changes) | Drive it in a real browser per the coverage contract (`references/eye-verify.md`) | every testable checked or listed NOT-VERIFIED; no console/page errors or untranslated keys |
## Important
- Type-checking is project-wide — a change in one file can surface type errors in another, so a clean run matters beyond the files you edited.
- Know what your project's type-checker covers. Some setups leave certain component file formats (e.g. framework single-file components) out of the static check — those surface errors only at build or runtime.
- Type-check and lint prove the code is well-formed, not that it behaves — run the test suite too, and cover changed logic with a test (see the `test-writing` skill).
- Run every applicable check before the work is considered done — all must pass.
Run all frontend quality checks after making changes to JavaScript or TypeScript files. The static checks (type-check, lint) and the test suite must all pass before work is complete. A change that renders UI is also eye-verified in a real browser when a harness can run — and when one genuinely can't this session, that's an explicit deferral, not a silent skip.
Activate this skill when:
If the project uses TypeScript, run its type-check script with the project's package manager — it is defined in package.json (commonly a type-check script; the underlying command is usually tsc --noEmit):
npm run type-check # or: yarn / pnpm / bun — match the project's lockfile
Must show 0 errors. Fix any type issues found. Skip this check for a plain-JavaScript project with no type-checker.
Run the project's lint script — it runs whatever linter the project uses (ESLint, Biome, oxlint, …):
npm run lint # or: yarn / pnpm / bun
If the project uses ESLint, you can scope it to the changed files for speed instead of linting everything. Run the project-local ESLint via its package manager (npm exec / pnpm exec / yarn / bunx):
eslint --cache --cache-location ".cache/eslint/" <file1> <file2> ...
Must show 0 errors. Fix any linting issues found. Skip this check when package.json defines no lint script, or the project has no package.json — a server-rendered project may have templates and styles but no JS linter.
Run the project's JS/TS test suite — its script is in package.json (commonly test, or a dedicated script such as test:js; the underlying runner is Vitest, Jest, etc.):
npm test # or: yarn / pnpm / bun — match the project's lockfile
Must show 0 failures. Fix any failing tests. When the change added or altered testable logic, add or update a test for it before the work is done — the test-writing skill covers what to write and where. During development you can scope to the changed area (e.g. vitest run <path> for Vitest, jest <path> for Jest) and run the full suite at completion. Skip only when the project has no JS test setup.
If the change renders UI (not pure logic), type-check and lint aren't enough — runtime/visual bugs (stale state, dead toggles, broken scroll / sticky behaviour, z-index show-through, async races, untranslated keys) only show in a browser. Do it whenever a harness can run against the change; if one genuinely can't this session (no running app, an external service that can't be seeded), name the deferral in a NOT-VERIFIED list rather than reporting an unqualified green.
references/eye-verify.md.scripts/screenshot.mjs (capture +
crop-to-selector with ≥15px padding), scripts/console.mjs (console/page errors + a leak
scan over text and screen-reader attributes + an optional --axe accessibility pass),
scripts/auth-capture.mjs (save a login session the others reuse via --storage-state), and
scripts/lib.mjs (helpers to write a drive-script: createChecker for the contract,
capturePageIssues, withFailedRoute for fault injection). See
scripts/README.md; it needs Playwright in the project
(npm i -D playwright && npx playwright install chromium) and points at the already
running app. Use it, the project's own harness if it has one, or a Playwright MCP server.references/design-verification.md.eye-verification skill (/eye-verification), where the project ships it.See the javascript guideline ("Eye-verify frontend changes" and "Verify against the design, per element") for the why.
| Check | Command | Pass criteria |
|---|---|---|
| Type checking | npm run type-check (TypeScript projects) |
0 errors |
| Linting | npm run lint (the project's lint script) |
0 errors |
| Tests | npm test (the project's JS test script) |
0 failures |
| Eye-verify (UI changes) | Drive it in a real browser per the coverage contract (references/eye-verify.md) |
every testable checked or listed NOT-VERIFIED; no console/page errors or untranslated keys |
test-writing skill).How can I help you explore Laravel packages today?