# Magikarp Collection A Next.js web app to browse every English Magikarp Pokémon card with images, set symbols, search, set filter, and a personal checklist stored in your browser. ## Features - **Checklist (variants-aware)**: Track base, holofoil, and reverse holofoil per card. Local persistence with migration from v1 to v2. - **Card images**: Card scans from `assets.tcgdex.net` (a placeholder is shown for cards TCGdex has no scan for). - **Set badges**: Displays series and set name. - **Search & filter**: Search by name/number/rarity/set and filter by set. - **Totals include variants**: The header and tab badges use variant totals (base + available variants) for collected/uncollected counts. - **Sort by release date**: Cards are ordered by set release date (oldest first). - **Caching with TTL**: Server route caches card data to `data/cards.json` with a 24h TTL and a manual refresh button. - **Cached/Live indicator**: Header shows whether data came from cache or a live fetch, with last updated timestamp. - **Non-blocking error toast**: Refresh errors show a short-lived toast without disrupting the current view. - **Responsive UI**: Tailwind CSS, mobile-friendly grid. ## Tech Stack - **Next.js 15** (App Router) - **React 19** - **TypeScript** - **Tailwind CSS v4** - **Axios** for HTTP ## Quick Start ### 1) Prerequisites - Node.js 18+ and npm ### 2) Install dependencies ```bash npm install ``` ### 3) Environment variables No API key is needed. Card data comes from the free [TCGdex](https://tcgdex.dev/) API. To enable the optional single-user Basic Auth, create `.env.local` (or `.env`) in the project root: ```bash # .env.local BASIC_AUTH_USER=your_user BASIC_AUTH_PASS=your_password ``` An example is provided in `.env.local.example`. ### 4) Run the dev server ```bash npm run dev ``` By default: http://localhost:3000 If you see a server already running on port 3000, you can use another port: ```bash PORT=3001 npm run dev ``` ## Scripts - `npm run dev` – start Next.js in development - `npm run build` – production build - `npm run start` – start production server - `npm run lint` – lint project ## Project Structure ``` magikarp-collection/ ├─ src/ │ ├─ app/ │ │ ├─ api/ │ │ │ ├─ magikarp/route.ts # API route with 24h TTL cache (data/cards.json) │ │ │ └─ checklist/route.ts # Server-backed checklist persistence (optional) │ │ ├─ layout.tsx # Root layout and global wrapper │ │ ├─ page.tsx # Main page: search, set filter, grid, checklist │ │ └─ globals.css # Tailwind entry + global styles │ ├─ components/ │ │ ├─ CardGrid.tsx # Grid for card list │ │ ├─ CardItem.tsx # Card tile with image, rarity, set badge, checklist toggle │ │ ├─ Header.tsx # Title, search, stats │ │ ├─ SetBadge.tsx # Shows set symbol and name │ │ └─ SetFilter.tsx # Dropdown to filter by set │ ├─ lib/ │ │ ├─ api.ts # Axios client for Pokémon TCG API │ │ ├─ checklist.ts # Checklist utils (local + server-backed) │ │ └─ currency.ts # Price formatting + exchange rate hook │ └─ types/ │ └─ pokemon.ts # TypeScript types for cards/sets ├─ data/ # Local cache for cards/checklist JSON (gitignored) ├─ next.config.ts # Remote image domains, turbopack settings ├─ tsconfig.json # TS config with path alias '@/*' ├─ postcss.config.cjs # Tailwind v4 PostCSS plugin config ├─ Dockerfile # Multi-stage Docker build (standalone output) ├─ docker-compose.yml # Compose with APP_PORT and data volume ├─ .dockerignore # Reduce build context ├─ package.json └─ .env.local.example # Example env file ``` ## Data Source - TCGdex REST API v2: https://api.tcgdex.net/v2/en (no key required) - `GET /cards?name=magikarp` lists matching cards; each card (`/cards/{id}`) and each set (`/sets/{id}`) is then fetched for details. - Pokémon TCG Pocket cards are skipped. - Cards whose TCGdex ID differs from the old pokemontcg.io ID keep the old ID (see `LEGACY_CARDS` in `src/lib/api.ts`) so saved checklists stay valid. - The previous source, the Pokémon TCG API (pokemontcg.io), is deprecated. ## How It Works - The client loads data from `GET /api/magikarp` (`src/app/api/magikarp/route.ts`). - The route fetches from TCGdex using `fetchMagikarpCards()` (`src/lib/api.ts`), caches the full response in `data/cards.json`, and serves cached data when fresh (<24h) unless `?refresh=1` is provided. If a refresh fails, the last cached data is served and marked `stale`. - Cards render in `CardGrid`/`CardItem`, ordered by set release date. - Checklist persists locally (v2 supports variant-level tracking). A server-backed route exists at `api/checklist` if you enable it. ## Docker Build and run using Docker/Compose. The container listens on port 3000 internally; pick a host port via `APP_PORT`. ### Build and run ```bash # Default host port 3000 docker compose up --build # Custom host port APP_PORT=8080 docker compose up --build ``` Open: http://localhost:3000 (or your chosen `APP_PORT`). ### Volumes and data - The `./data` directory is mounted to `/app/data` in the container so cached JSON persists between restarts. - `data/cards.json` and `data/checklist.json` are gitignored by default. ## Deployment - **Vercel**: Zero-config for Next.js. No API key is required. - **Netlify/Other**: Build command `npm run build`, publish `.next` with a Next adapter or use Next on Node; make sure environment vars are set. ## Troubleshooting - "Cannot find module '@tailwindcss/postcss'": install the Tailwind v4 PostCSS plugin and ensure CommonJS config. ```bash npm i -D @tailwindcss/postcss # Ensure postcss.config.cjs exists with: # module.exports = { plugins: { '@tailwindcss/postcss': {} } } ``` - Images not loading: confirm `next.config.ts` allows `assets.tcgdex.net` and restart the dev server. - No cards shown: check the server log for `Error fetching cards`; if TCGdex is unreachable the app serves the last cached data. ## License This project is provided as-is for personal collection tracking.