dex/AGENTS.md
chris 803ed2a988 Upgrade to Vite 6, drop unused ws dep
Vite 5 pulled esbuild 0.21.5 — the only source of the GHSA-67mh-4wv8-2f99
dev-server advisory. Vite 6.4 (esbuild 0.25) runs on the current Node
baseline and clears it: `npm audit` now reports 0 vulnerabilities.

- vite 5.4 → 6.4, vite-plugin-pwa 0.21 → 1.3 (needs Vite 6+).
- Removed `ws` from devDependencies — it was only used by throwaway test
  scripts, never the app or build.
- Build, all 14 routes, and the service worker verified on Vite 6.
- SECURITY.md / AGENTS.md updated.

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

4.6 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+.
  • There is no lint or test command and no test suite. The build (npm run build) is the only automated check — it must pass. It runs esbuild over every module, so it catches syntax and import errors.
  • 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.
  • 2-space indent, semicolons, single quotes, trailing commas in multi-line literals. 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 build 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.