Quick reference for AI coding agents working in this repo. See README.md for full project overview.
npm run dev # start Vite dev server (localhost:5173)
npm run build # tsc type-check + vite build → dist/
npm run lint # ESLint (ts/tsx only)
npm run preview # preview production build locally
npm run deploy # build + gh-pages publish to GitHub Pages- Data — 11 JSON files in
src/data/categories/→ merged flat array insrc/data/index.ts→ consumed byApp.tsxas a module-scopeconst. No runtime fetches. - State — All state (
theme,searchQuery,activeCategory,expandedCards) lives inApp.tsx. No context, no stores. - Search — Fuse.js index built once via
useMemowith weighted keys; multi-variant query (normalized, slash-stripped, slash-prefixed) deduplicated and priority-sorted. - Theming —
data-color-modeattribute on<html>switches CSS var sets; persisted tolocalStoragekeyghcp-theme.
- Create
src/data/categories/<slug>.json— flat array ofCommandobjects. - Import and spread it in
src/data/index.ts. - Add a
Categoryentry toCATEGORIESinsrc/types/index.ts(this file owns both types and the categories data array — do not move it).
Edit the matching src/data/categories/<slug>.json. Follow these conventions:
| Field | Convention |
|---|---|
id |
"{2-3-letter-prefix}-{n}" — prefix abbreviates the category slug (e.g. gs-5, chat-2) |
title |
The slash-command or command name alone (e.g. "/bug") |
syntax |
Full usage signature with args; may equal title for simple commands |
examples |
Plain strings; use " #" (two-space hash) to add an inline comment rendered as a styled annotation |
note |
Omit entirely when not needed (only truly optional field alongside terminalDemo) |
terminalDemo |
Optional { prompt: string; output: string[] } for an animated terminal block |
- Named exports only — no default exports from components.
- Local
interface Props— declare immediately before the function, not exported, not named after the component. import typefor type-only imports — required byverbatimModuleSyntax: true.- No
const enum—erasableSyntaxOnly: trueforbids it; use plainenumor union types. - Sub-components stay file-local — extract into the same file above the exported component; do not export them.
- Accessibility — interactive non-button elements need
role="button",tabIndex={0}, andonKeyDownhandling forEnter/Space.
- All colors via CSS custom properties (
--color-*) following GitHub Primer naming. - When adding a new color token, add it to both the dark block (
:root, html[data-color-mode='dark']) and the light block (html[data-color-mode='light']) insrc/index.css. - No inline styles, no CSS-in-JS, no Tailwind, no CSS Modules — plain global CSS only.
- No top-level
strict: true; individual strict options are selectively enabled (seetsconfig.app.json). noUnusedLocalsandnoUnusedParametersare on — remove dead code rather than suppressing.moduleResolution: "bundler"— Vite handles transpilation; TypeScript is type-check only (noEmit: true).
- Vite
baseis/ghcp-cli-cheatsheet/(GitHub Pages path) — do not change without also updating the gh-pages config. npm run deployrunspredeploy(build) then publishesdist/viagh-pages.
Follow these steps for every bot-generated PR before merging into main. Never merge directly without completing this checklist.
- Check out the feature branch locally and pull the latest changes.
- Run
npm run buildto confirm no TypeScript or build errors. - Run
npm run devand visually verify the new/changed commands render correctly in the UI.
Only generate GIFs for newly added commands — do not regenerate GIFs for existing commands in the same category.
-
For each new command in the PR, generate only its GIF using the
--idflag:npm run create:gif -- --id <command-id>
The
<command-id>matches the"id"field inscripts/demos.json(e.g.autopilot,worktree). -
If the tape file for the new command doesn't exist yet, run
npm run create:tapefirst — this generates tape files fromscripts/demos.json.To generate only the tape for a specific command, use the
--idflag:npm run create:tape -- --id <command-id>
This avoids creating tape files for unrelated commands.
-
Common tape issues to check and fix before committing:
- Commands that require experimental mode need
/experimental ontyped before the command, with at leastSleep 5safterEnterto let the terminal settle. - Interactive dialogs (e.g. permission prompts) need an
Enterkeypress after aSleep 3sto select the default option. - If characters are dropped during typing, increase the
Sleepduration before thatTypeline.
- Commands that require experimental mode need
-
Verify the generated GIF at
public/images/<category>/<id>.gifplays correctly. -
Ensure the command's entry in
src/data/categories/<category>.jsonhas"terminalDemo": "images/<category>/<id>.gif"— without this field the "SEE IT IN ACTION" section won't appear in the UI even if the GIF exists. -
Commit the GIF file and any tape fixes to the feature branch (not
main).
- Only after steps above are complete: mark the PR as ready for review (convert from draft), then merge using a regular merge (not squash) to preserve the "Merge pull request #X" entry in the git log.