From 572854fcda683dd3470e67d632e3b9c27d213f13 Mon Sep 17 00:00:00 2001 From: Juan Bejarano Date: Tue, 19 May 2026 11:43:23 -0500 Subject: [PATCH] feat: full-stack indie games catalog with AI chat - Games CRUD: SQLite persistence via better-sqlite3, repository pattern (GamesRepository interface + SqliteGamesRepository), Zod validation, seed script with 10 sample games. - REST API: five route handlers (GET/POST /api/games, GET/PUT/DELETE /api/games/:id) with structured error responses and request body validation. - AI Chat: streaming chat via Vercel AI SDK + Anthropic claude-haiku-4-5, tool calling (list_games, find_game_by_title, catalog_summary, respond), structured output as a discriminated union (game | games | comparison | count | stats | text) rendered as rich cards in the UI. - UI: Next.js 16 App Router, mobile-first Tailwind v4, native modals (bottom-sheet on mobile / centered on desktop), right-anchored chat drawer with backdrop, answer cards per output kind. - Docs: technical feature docs in docs/features/, specs in docs/specs/, CLAUDE.md with engineering rules and conventions. --- .env.example | 1 + .gitignore | 59 +- AGENTS.md | 5 + CLAUDE.md | 127 + README.md | 172 +- app/api/chat/route.ts | 60 + app/api/games/[id]/route.ts | 57 + app/api/games/route.ts | 36 + app/globals.css | 8 + app/layout.tsx | 31 + app/page.tsx | 7 + components/chat/answer-card.tsx | 160 + components/chat/chat-dock.tsx | 37 + components/chat/chat-drawer.tsx | 57 + components/chat/chat-scaffold.tsx | 215 + components/games/delete-dialog.tsx | 74 + components/games/game-card.tsx | 62 + components/games/game-form-dialog.tsx | 276 + components/games/games-view.tsx | 96 + components/site-header.tsx | 11 + data/.gitkeep | 0 docs/features/01-games-crud.md | 97 + docs/features/02-rest-api.md | 79 + docs/features/03-ai-chat.md | 122 + docs/features/04-ui.md | 111 + docs/specs/01-games-crud.md | 34 + docs/specs/02-rest-api.md | 35 + docs/specs/03-ai-chat.md | 36 + docs/specs/04-ui.md | 32 + docs/template/spec-template.md | 74 + eslint.config.mjs | 18 + lib/db/client.ts | 25 + lib/db/schema.sql | 14 + lib/games/ai-tools.ts | 183 + lib/games/answer-types.ts | 24 + lib/games/format.ts | 21 + lib/games/repository.ts | 101 + lib/games/schemas.ts | 12 + lib/games/types.ts | 15 + next.config.ts | 7 + package-lock.json | 7862 +++++++++++++++++++++++++ package.json | 35 + postcss.config.mjs | 7 + scripts/seed.ts | 29 + tsconfig.json | 34 + 45 files changed, 10501 insertions(+), 57 deletions(-) create mode 100644 .env.example create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 app/api/chat/route.ts create mode 100644 app/api/games/[id]/route.ts create mode 100644 app/api/games/route.ts create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 components/chat/answer-card.tsx create mode 100644 components/chat/chat-dock.tsx create mode 100644 components/chat/chat-drawer.tsx create mode 100644 components/chat/chat-scaffold.tsx create mode 100644 components/games/delete-dialog.tsx create mode 100644 components/games/game-card.tsx create mode 100644 components/games/game-form-dialog.tsx create mode 100644 components/games/games-view.tsx create mode 100644 components/site-header.tsx create mode 100644 data/.gitkeep create mode 100644 docs/features/01-games-crud.md create mode 100644 docs/features/02-rest-api.md create mode 100644 docs/features/03-ai-chat.md create mode 100644 docs/features/04-ui.md create mode 100644 docs/specs/01-games-crud.md create mode 100644 docs/specs/02-rest-api.md create mode 100644 docs/specs/03-ai-chat.md create mode 100644 docs/specs/04-ui.md create mode 100644 docs/template/spec-template.md create mode 100644 eslint.config.mjs create mode 100644 lib/db/client.ts create mode 100644 lib/db/schema.sql create mode 100644 lib/games/ai-tools.ts create mode 100644 lib/games/answer-types.ts create mode 100644 lib/games/format.ts create mode 100644 lib/games/repository.ts create mode 100644 lib/games/schemas.ts create mode 100644 lib/games/types.ts create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.mjs create mode 100644 scripts/seed.ts create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8b3e125 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +ANTHROPIC_API_KEY= diff --git a/.gitignore b/.gitignore index 57817f9..8bffce5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,55 @@ -node_modules/ -.next/ -out/ -build/ -dist/ -.env -.env.local -.env.*.local +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug npm-debug.log* yarn-debug.log* -pnpm-debug.log* -.DS_Store +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* +!.env.example + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# editors .vscode/ .idea/ +.claude/ + +# local sqlite database *.sqlite *.sqlite3 *.db -coverage/ +*.db-shm +*.db-wal + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8bd0e39 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,5 @@ + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..84841b4 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,127 @@ +# CLAUDE.md + +Guidance for Claude Code sessions working in this repository. + +## Project Overview + +An internal dashboard to manage a catalog of indie games (CRUD) plus an AI chat that answers natural-language questions about the catalog. The chat uses tool calling against the same data layer that backs the REST API — it never receives the database as raw context — and streams responses to the UI in real time. + +## Tech Stack + +- **Framework:** Next.js 14+ (App Router) + TypeScript (strict mode) +- **Styling:** Tailwind CSS +- **Persistence:** SQLite (local file under `data/`, git-ignored) +- **LLM layer:** Vercel AI SDK + Anthropic `claude-sonnet-4-6` +- **Transport:** Next.js Route Handlers for both REST and streaming chat + +## Spec Quick Reference + +Authoritative requirements live in [docs/specs/](docs/specs/). Always read the relevant spec before changing the corresponding area: + +- [docs/specs/01-games-crud.md](docs/specs/01-games-crud.md) — Games data model (`title`, `developer`, `genre`, `monthly_revenue_usd`, `monthly_downloads`, `average_rating`) + SQLite persistence. +- [docs/specs/02-rest-api.md](docs/specs/02-rest-api.md) — REST endpoints: `GET /games`, `POST /games`, `GET /games/:id`, `PUT /games/:id`, `DELETE /games/:id`. +- [docs/specs/03-ai-chat.md](docs/specs/03-ai-chat.md) — Streaming chat with tool calling; no DB dumps into the prompt. +- [docs/specs/04-ui.md](docs/specs/04-ui.md) — Dashboard view (table or cards) + chat view, Next.js App Router + Tailwind. + +## Feature Documentation + +Technical docs explaining how each feature is actually implemented — data flow, components, design decisions. Read these when working on or extending an existing feature: + +- [docs/features/01-games-crud.md](docs/features/01-games-crud.md) — Data model, SQLite schema, repository pattern (`GamesRepository` interface + `SqliteGamesRepository`), Zod validation, seed script. +- [docs/features/02-rest-api.md](docs/features/02-rest-api.md) — Route handler structure, request/response shapes, error format, design decisions (full replacement PUT, server-generated IDs, no query params). +- [docs/features/03-ai-chat.md](docs/features/03-ai-chat.md) — `streamText` setup, system prompt contract, tool definitions (`list_games`, `find_game_by_title`, `catalog_summary`, `respond`), `CatalogAnswer` discriminated union, hydration pattern, client-side part rendering logic. +- [docs/features/04-ui.md](docs/features/04-ui.md) — App Router data flow, component tree, native `` pattern, chat drawer, `AnswerCard` variants, Tailwind conventions. + +## Engineering Rules (Non-Negotiable) + +### Clean Code +- Meaningful, intention-revealing names. No abbreviations that aren't industry-standard. +- Small functions doing one thing. Early returns over nested conditionals. +- No dead code, no unused exports, no premature abstraction. Duplication is preferable to the wrong abstraction. + +### SOLID +- **S** — One responsibility per module, component, route handler, and tool definition. +- **O / L** — Extend behavior by adding new tools, repositories, or components rather than mutating existing ones. +- **I** — Keep interfaces narrow; consumers should not depend on shapes they don't use. +- **D** — Depend on abstractions at the data and AI boundaries (e.g. a `GamesRepository` interface implemented by a SQLite adapter; LLM tools defined against the repository, not against the DB driver). + +### No Comments — Of Any Kind +Code must be self-explanatory through naming and structure. Do not write: +- Inline comments (`//` or `#`). +- Block comments (`/* ... */`). +- JSDoc / TSDoc. +- Banner comments, section dividers, `TODO` / `FIXME` / `NOTE` markers. + +The only acceptable prose lives in Markdown files (`CLAUDE.md`, `README.md`, `docs/`). If you feel the urge to explain code with a comment, rename a symbol or extract a function instead. + +### Mobile First +All UI work starts from the smallest viewport and scales up — never the other way around: +- Design and implement the mobile layout first, then progressively enhance with Tailwind's `sm:`, `md:`, `lg:`, `xl:` breakpoints. +- Base (unprefixed) Tailwind classes describe the mobile experience; larger-breakpoint prefixes add or override only what changes. +- Tap targets are at least 44×44px; spacing, typography, and forms must remain usable with one thumb. +- Tables (dashboard view) must have a mobile-friendly fallback — horizontal scroll within a bounded container, or a card layout on narrow screens — never a layout that overflows the viewport. +- The chat surface must work on mobile: composer pinned, input never hidden by the on-screen keyboard, streaming output scrolls into view. +- Test every change at ~360px wide before considering it done. + +### Accessibility (UI) +Every interactive UI surface must meet WCAG basics: +- Semantic HTML (`