- 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
5.1 KiB
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) andnpm run build(esbuild transforms every module, so it catches syntax and import errors). Runnpm run formatbefore finishing. There is no test suite and no ESLint. npm run snapshot -- --forcerebuilds 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()fromsrc/lib/dom.js—el(tag, props, ...children). No template-string HTML, noinnerHTML, except the deliberatehtml:prop for trusted inline SVG. - Stores:
createStore(key, initial)→{ get, set, subscribe, replace }.set(fn)replaces state (it does not merge) — spread...syourself. In views,subscribe()and call the returned unsub inonTeardown(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éAPIpast_values. - Tracking is per game.
src/store/selection.js:entry(id)/toggle(id, field)/stats(ids)default to the selected game;favoriteandnoteare global. Don't reintroduce a single global caught set. - Respect
prefersReducedMotion()(fromsrc/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.jsexportingasync function Foo()returning a node; add one entry toroutesinsrc/router.js. Add askeletonif it does async work before first paint. - Setting — key + default in
src/store/settings.js(andapplyTheme()if it affects the document), a field insrc/views/SettingsView.js, and add it to the export payload inexportData()if it should survive a backup. - Snapshot field — add it in
scripts/build-snapshot.mjs, runnpm run snapshot -- --force, read it vialoadSnapshot(). Keep the snapshot small; it's precached on every install.
Do not
- Commit
dist/orsrc/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.