Quality & tools
Checks & scripts
Every check and script in the project, in one table: what it guards, when it runs, and where its details are.
On every pull request (CI)
GitHub runs these on each PR (.github/workflows/checks.yml), each one even when another failed. They are not run by hand after an edit: only when the PR's Checks run is red, to confirm the fix (CLAUDE.md §12). check:seo, check:headings and check:variants need the site running; check:hebrew is the one that spends tokens.
| Command | What it does | Docs |
|---|---|---|
npm run lint -- --quiet | ESLint errors: an internal <a> instead of <Link>, a fixed value in style={{}} in a demo, the lead-paragraph token, and the rest of the CLAUDE.md rules that a linter can see. Warnings are not a gate. | ESLint |
npm run check:seo | Every page in the sitemap: a title and a description, unique, 70 to 160 characters, no build notes and no em-dash; the canonical is the page's own URL; og:image answers; JSON-LD parses; /demos stays noindex. | |
npm run check:headings | One h1 per page and no skipped level going down (h2 then h4). CI adds --with-demos (every demo home and the pages it links to); --width 390 checks a phone. | |
npm run check:variants | A demo with several homepages: every internal link on a variant's pages stays under that variant's root, and none is broken. | Shared Inner Pages |
npm run check:hebrew | Claude reads the Hebrew lines the PR added or changed (app, components, data, lib; not docs or comments) and reports only real errors: agreement, a wrong preposition, a typo, an English calque, a singular "you", an em-dash. A finding fails the check with file:line, the fix and why. Needs the ANTHROPIC_API_KEY repo secret, without it it passes with a note. By hand: this branch against main, --dry-run shows what would be sent. |
By hand, when you need it
With the dev server running. Each prints only what it found.
| Command | What it does | Docs |
|---|---|---|
npm run rhythm -- /about | Vertical rhythm at phone and desktop: same-background sections that double their padding, a heading too far from its paragraph, a heading out of the scale. --demo <id> walks a whole demo. | vertical-rhythm skill |
npm run dead-spots -- /demos/vision_31_10 | Where the scroll does nothing: frames that barely change while scrolling, with the length in screens and the share of the scrollbar. For a long-scroll page. --w 390 for a phone. From PowerShell: Git Bash mangles the path. | Storytelling |
?lines on any URL | Not a script: draws a 24px rule over the page, in the browser, and stays on page to page. ?lines=0 takes it off. A helper to look with: nothing has to sit on it, though it can show a wrong gap. A home built on it to compare: /beta/on-the-lines. | Tailwind website style |
npm run look -- /about | Screenshots of a page as a reviewer sees it, at 1440 and 390: the first fold, one element scrolled in (a selector), the whole page (--full), the mobile menu (--menu). | |
npm run heads -- / /about | The SEO tags each page actually renders: title, description, canonical, robots, og: and twitter:. | |
npm run css:unused | Classes a CSS file styles that no code uses: what a rebuilt section left behind. A list to check, not proof (a class built in a template string shows as "dynamic?"). | |
node scripts/css-snapshot.cjs <label> | For a CSS refactor that must not change the look: record the computed style of every element, change, record again, then node scripts/css-diff.cjs <before> <after>. | |
node scripts/copy-audit.cjs --all | Every heading and principle / FAQ title across the demos, to review copy in one pass. |
Images
From a prompt to a light file in its slot.
| Command | What it does | Docs |
|---|---|---|
node scripts/gen-images.mjs | Generate demo pictures with Gemini from a manifest of { file, prompt, ratio }. | Image Generator |
node scripts/trim-margins.cjs · fit-ratio.cjs · cutout.cjs | After a generation: crop the canvas margin, crop to a slot's exact ratio, turn a white canvas into a transparent cut-out. | Image Generator |
npm run shrink -- <dir> | Down to the width the slots use, JPEG q82: a 43 MB folder to about 1.3 MB. | |
npm run avif -- <file|dir> | An .avif next to each JPG / PNG, same size, about half the bytes; the original stays for share cards. | |
npm run shot -- <demo-id> | The demo's first fold as its showcase card picture (public/demos/previews/<id>.webp). | |
node scripts/shoot-showpiece-previews.cjs · shoot-concept-previews.cjs | The card pictures of the GSAP showpieces and of Outside the Box. | Showpieces |
Google data
Read-only, from the terminal, as the service account (sign in once with npm run google:auth).
| Command | What it does | Docs |
|---|---|---|
npm run ga -- overview | GA4 reports: overview, pages, landing pages, sources, campaigns, the Ads campaigns through GA. | Analytics |
npm run gsc -- queries | Search Console: what people searched when the site showed up, per page, and the sitemaps Google knows. | Analytics |
npm run ads -- campaigns | Google Ads: campaigns, ads, conversions, search terms, Keyword Planner. It also adds keywords, negatives and ads, only after you approved the exact text; never a budget, a bid or a campaign switched on. | PPC |
npm run rank | Where the site ranks on Google (Israel, Hebrew) for the words in rank/keywords.txt, through Serper. | |
npm run kw -- --file rank/volume-keywords.txt | DataForSEO, paid per use: how many search each word a month in Israel; --ideas for the phrasings around a seed; --balance. | DataForSEO |
npm run serp | Where the site stands on Google itself for each word, one check per word (--live at once, --site for a client, --depth up to 200). | DataForSEO |
npm run seo-map | Joins the volume and the positions into the month, rank/map-<yyyy-mm>.json, shown on /beta/seo-map. | מיפוי מילים |
Housekeeping
| Command | What it does | Docs |
|---|---|---|
npm run dev | Before it starts (predev), the dev cache .next/dev is deleted when it passes NEXT_DEV_CACHE_MAX_GB (5): it only grows, and twice filled the drive. | |
npm run dev:fresh | Delete .next and start: for a route that 404s after big edits, or styles that will not update. |
