PrimeDex — a Next.js 16 (App Router) + React 19 Pokédex dashboard with TanStack Query, Zustand (IndexedDB), and 9 locales.
npm install
npm run dev # next dev --webpack (NOT turbopack) — http://localhost:3000
npm run build
npm run lint # eslint v9 flat config with eslint-config-next
npm run test # vitest via ./node_modules/vitest/vitest.mjs (jsdom)
npm run typecheck| Task | Command |
|---|---|
| Typecheck one path | npx tsc --noEmit |
| Lint one path | npx eslint path/to/file.tsx |
| Run one test | npx vitest path/to/file.test.ts |
| Test UI | npx vitest --ui |
Per-directory AGENT.md files override the root for their subtree. Always read the closest one before editing:
src/AGENT.md,src/app/AGENT.md,src/components/AGENT.mdsrc/components/ui/AGENT.md,src/components/pokemon/AGENT.md,src/components/layout/AGENT.mdsrc/lib/AGENT.md,src/lib/api/AGENT.mdsrc/store/AGENT.md,src/types/AGENT.md,src/hooks/AGENT.mdpublic/AGENT.md
- RSC by default. Only add
"use client"to leaves that need interactivity; persrc/app/AGENT.md,Headeris rendered per-page, not in the root layout. - Tailwind v4 only. Uses
@import "tailwindcss"insrc/app/globals.css. Notailwind.config.js— do not create one. - Images: always
next/image; raw<img>is prohibited. - Imports: use the
@/alias (tsconfig.jsonpaths →src/). - API: all requests go through
@/lib/api/barrel; never callfetch/axiosdirectly in components. REST + GraphQL hithttps://pokeapi.co; TCG hitshttps://api.tcgdex.net. Query keys are built from@/lib/api/keys. - Types:
src/types/pokemon.tsis the source of truth. NoanyorRecord<string, unknown>. - i18n: client code uses
@/lib/i18n(lazy-loaded language bundles, English is the initial bundle); server code uses@/lib/server-i18n(all bundles baked in). User-facing strings go throught(). - State: Zustand store in
src/store/primedex.tsholds IDs/primitives only, persisted viaidb-keyval(IndexedDB, not localStorage). Check_hasHydratedbefore trusting persisted state in effects. Use selectors to avoid re-renders. - Heavy components (
EvolutionChain,AdvancedInfo, etc.) are loaded vianext/dynamic. - shadcn/ui style is
base-nova; some primitives come from@base-ui/react(seecomponents.json). - Accessibility: WCAG 2.2 AA; every icon-only control needs
aria-label, every image analt.
- Locale prefix is required.
src/middleware.tsrewrites/<lang>/...→/...and 308-redirects unprefixed paths based on theprimedex-langcookie orAccept-Language. Supported:en, fr, es, de, it, ja, ko, zh, pt. UseuseLocaleHrefto build internal links with the current prefix. - Routes (under
src/app/):/(listing),/pokemon/[name],/team,/compare,/favorites,/quiz,/types,/tcg,/moves,/dashboard,/about,/faq,/cookies,/legal,/privacy,/terms.revalidate = 3600andgenerateStaticParams(first 151) are set on the dynamic[name]page. - Providers (
src/app/providers.tsx): TanStack Query (staleTime 10 min, gcTime 60 min, retry 1, no refetchOnWindowFocus), theme via store +next-themes, i18n. - Data flow: components consume TanStack Query hooks from
@/lib/api/; persistent UI state (favorites, team, caught, filters, history, settings) from@/store/primedex.
- Dev uses webpack, not turbopack. The
devscript forces--webpack.next.config.tsstill declaresturbopack.root; leave it alone. - Agentation dev tool runs on
http://localhost:4747(CSP andallowedDevOriginsare pre-wired for it). Toggled viaNEXT_PUBLIC_ENABLE_AGENTATION=truein.env.local. Don't add 4747 to CSP yourself. - Tests live next to the code they cover (e.g.,
src/lib/auto-complete.test.ts). The Vitest setup filesrc/test/setup.tsexists and imports@testing-library/jest-dom/vitest— without it,npm run testfails to start. - No CI yet — no
.github/directory.vercel.jsononly has{"name": "poke-app"}; deploy config lives in the Vercel dashboard. - No project-level opencode config —
.opencode/is gitignored (has its ownnode_modules). GEMINI.mdis a separate mandate document at the repo root and in some subtrees; treat its rules as authoritative when they overlap.- Local editor / agent artifacts are gitignored:
.vscode/,.opencode/,*.local,header-*.png,tcg-*.png,tcgp-logo.webp. Don't commit them.
AI-authored commits MUST include the trailer:
Co-authored-by: Gemini CLI <agent@gemini.google.com>