# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. @AGENTS.md ## Build & Development Commands ```bash npm run dev # Start dev server (hot reload) npm run build # Production build npm start # Start production server npm run lint # ESLint (flat config, v9+) npx prisma generate # Regenerate Prisma client after schema changes npx prisma migrate dev --name # Create and apply a migration npx prisma db push # Push schema changes without migration (dev only) ``` ## Architecture **Stack**: Next.js 16.2.1 (App Router) · React 19 · TypeScript · Tailwind CSS v4 · Prisma · PostgreSQL 16 · Cloudflare R2 **Path alias**: `@/*` maps to project root (configured in tsconfig.json). ### App Router Structure ``` app/ ├── page.tsx # Homepage (manga grid) ├── layout.tsx # Root layout (Geist fonts, metadata) ├── manga/[slug]/page.tsx # Manga detail + chapter list ├── manga/[slug]/[chapter]/page.tsx # Chapter reader ├── api/search/route.ts # Search endpoint (?q=) ├── api/manga/route.ts # Manga CRUD (admin) ├── api/upload/route.ts # R2 presigned URL generation └── sitemap.ts # Auto-generated sitemap ``` ### Data Flow - **Database**: Prisma ORM → PostgreSQL. Models: `Manga`, `Chapter`, `Page` (see `prisma/schema.prisma`). - **Images**: Stored in Cloudflare R2 (S3-compatible). Upload flow: backend generates presigned URL → browser uploads directly to R2 → database records the image path. - **R2 bucket layout**: `/manga/{manga_id}/{chapter_id}/{page_number}.webp` and `/thumbnails/{manga_id}/cover.webp`. - **Search**: PostgreSQL `contains` with `insensitive` mode (phase 1). No external search engine needed until >10k titles. ### Key Libraries - `@aws-sdk/client-s3` + `@aws-sdk/s3-request-presigner` — R2 uploads (S3-compatible API) - `prisma` / `@prisma/client` — ORM and database client ## Deployment - **Docker**: `docker build` from root Dockerfile → container exposes port 3000, mapped to host port 3001. - **Compose**: `docker-compose.yml` runs both the app and PostgreSQL 16. - **Flow**: Push to Gitea → `git pull` on Proxmox Docker host → rebuild → restart via Portainer. - **Reverse proxy**: aaPanel Nginx routes `manga.04080616.xyz` → `http://127.0.0.1:3001`. - **Port 3001** (app) and **5433** (Postgres) on the host — many other ports are taken. ## Environment Variables Required in `.env` (see docker-compose.yml for container equivalents): - `DATABASE_URL` — PostgreSQL connection string - `R2_ACCOUNT_ID`, `R2_ACCESS_KEY`, `R2_SECRET_KEY`, `R2_BUCKET`, `R2_PUBLIC_URL` — Cloudflare R2 ## Content Policy All manga content must be **public domain or free** (Comic Book Plus, Digital Comic Museum, Internet Archive). No copyrighted material.