dex/AGENTS.md
chris 39bffcab32 CI: gate on Prettier; docs: disclose AI assistance
- ci.yml runs `npm run format:check` before the build.
- CONTRIBUTING / AGENTS: point at `npm run format` instead of the old
  "no formatter" note.
- README: new "Built with AI assistance" section — the project is
  developed with Claude / Claude Code, human-directed and reviewed;
  visible in the Co-Authored-By trailers. CONTRIBUTING asks contributors
  to disclose AI-assisted PRs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
2026-09-10 11:26:16 -04:00

5.1 KiB

AGENTS.md

Guidance for AI coding agents working in this repo. Humans: see CONTRIBUTING.md — this file is the short, machine-facing version of the same rules.

What this is

Pocketdex — an offline-first Pokédex / team builder / save-file tracker. Vanilla JS, no UI framework. Vite 6 + vite-plugin-pwa (Workbox, injectManifest). All data comes from PokéAPI.

Setup & commands

npm install
npm run snapshot        # build src/data/snapshot.json from PokéAPI (git-ignored; required before first build/dev)
npm run dev             # dev server, http://localhost:5173
npm run build           # runs `snapshot` (prebuild) then builds to dist/
npm run preview         # serve the production build — REQUIRED to test the service worker / offline / install
  • Node 20+.
  • Automated checks (both run in CI, both must pass): npm run format:check (Prettier) and npm run build (esbuild transforms every module, so it catches syntax and import errors). Run npm run format before finishing. There is no test suite and no ESLint.
  • npm run snapshot -- --force rebuilds the snapshot even if it's fresh.

Project structure

Path What
src/main.js boot: theme, nav, router, SW registration, install prompt
src/router.js hash router; routes array; each view is () => Promise<Node>
src/views/*.js one file per route (DexGrid, PokemonDetail, TeamView, …)
src/components/*.js reusable DOM pieces (Card, Sprite, TypeChip, CompareTable, …)
src/store/*.js createStore() state, persisted to localStorage under pdx.*
src/data/*.js snapshot loader, pokedex resolver, lazy PokéAPI client, type chart, natures
src/lib/*.js app-agnostic helpers (dom, anim, damage-calc, savedex, swipe, …)
scripts/build-snapshot.mjs the only thing that calls PokéAPI at build time
src/styles/tokens.css palette, type colours, the five themes
src/styles/layout.css everything else

Conventions

  • Build DOM with el() from src/lib/dom.jsel(tag, props, ...children). No template-string HTML, no innerHTML, except the deliberate html: prop for trusted inline SVG.
  • Stores: createStore(key, initial){ get, set, subscribe, replace }. set(fn) replaces state (it does not merge) — spread ...s yourself. In views, subscribe() and call the returned unsub in onTeardown(viewNode, off).
  • Everything is game-aware. The selected game lives in settings.get().versionGroup. If you touch typings, effectiveness, learnsets or evolution, honour that game's generation: typesForGen(), multiplier(atk, def, gen), PokéAPI past_values.
  • Tracking is per game. src/store/selection.js: entry(id) / toggle(id, field) / stats(ids) default to the selected game; favorite and note are global. Don't reintroduce a single global caught set.
  • Respect prefersReducedMotion() (from src/store/settings.js) for any animation.
  • Formatting is Prettier (npm run format). Otherwise match the surrounding file; keep comments about why.
  • No new runtime dependencies. Prefer adding to the snapshot over a new runtime fetch.

Adding things

  • Route — new src/views/Foo.js exporting async function Foo() returning a node; add one entry to routes in src/router.js. Add a skeleton if it does async work before first paint.
  • Setting — key + default in src/store/settings.js (and applyTheme() if it affects the document), a field in src/views/SettingsView.js, and add it to the export payload in exportData() if it should survive a backup.
  • Snapshot field — add it in scripts/build-snapshot.mjs, run npm run snapshot -- --force, read it via loadSnapshot(). Keep the snapshot small; it's precached on every install.

Do not

  • Commit dist/ or src/data/snapshot.json (both git-ignored).
  • Commit Pokémon sprites, artwork, audio, ROMs or save files. All imagery is fetched at runtime from PokéAPI.
  • Add analytics, telemetry, ads, tracking, or "sign in" flows.
  • Add a framework or a build step that isn't Vite.
  • Break offline-first: the grid, search, filters and game switching must work with no network.

Verifying a change

npm run format then npm run build — both must pass. Then sanity-check by hand: the dex grid (filters, sort, catching from a card), switching games (numbers + typings update), a detail page (all tabs, form switch), and npm run preview offline (DevTools → Network → Offline → reload). Check light and dark theme and a mobile-width viewport.