Pure formatting — no behaviour change. Verified: build passes, all 14 routes render, service worker active, no console errors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
98 lines
5.0 KiB
Markdown
98 lines
5.0 KiB
Markdown
# AGENTS.md
|
|
|
|
Guidance for AI coding agents working in this repo. Humans: see
|
|
[CONTRIBUTING.md](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](https://pokeapi.co/).
|
|
|
|
## Setup & commands
|
|
|
|
```bash
|
|
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.js` — `el(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.
|