4.9 KiB
4.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Meme Studio is a homophone pun game operation platform built with Next.js 14 (App Router). It provides level configuration management for a wordplay game.
Commands
pnpm run dev # Start development server (port 3001)
pnpm run build # Production build
pnpm run deploy # Build and deploy to production server (./deploy.sh)
pnpm run lint # Run ESLint
# Database (Prisma + MySQL)
pnpm run db:generate # Generate Prisma client
pnpm run db:push # Push schema changes (dev)
pnpm run db:migrate # Create migration
pnpm run db:studio # Open Prisma Studio
pnpm run db:seed # Create/update admin user
Architecture
Tech Stack
- Framework: Next.js 14 App Router
- Auth: Better Auth with Prisma adapter (email/password)
- Database: MySQL via Prisma ORM
- UI: shadcn/ui + Tailwind CSS
- State: TanStack Query for server state
- Drag & Drop: @dnd-kit/sortable
Key Patterns
Route Groups:
app/(auth)/- Login page (no sidebar)app/(dashboard)/- Protected pages with sidebar layout
Auth Flow:
lib/auth.ts- Server-side Better Auth configlib/auth-client.ts- Client-side auth hooks (useSession,signIn,signOut)middleware.ts- Cookie-based session check (cannot use Prisma in Edge Runtime)
API Routes:
/api/auth/[...all]- Better Auth endpoints/api/levels- CRUD for game levels/api/levels/reorder- Batch update sort order/api/cos/temp-key- Tencent COS temporary credentials
Database Models:
Level- Game levels with image, answer, hints, sortOrderUser,Session,Account,Verification- Better Auth models
basePath & Reverse Proxy
The app is deployed behind a reverse proxy at /studio path:
next.config.jssetsbasePath: '/studio'- All pages and API routes are served under
/studio/...
Critical gotchas:
- Next.js strips basePath from
request.urlin route handlers — Better Auth'sbasePathmust be/api/auth(without/studio), not/studio/api/auth BETTER_AUTH_URLmust NOT contain a path (just the origin likehttp://localhost:3001) — Better Auth'swithPath()silently ignores thebasePathconfig if the URL already has a path component- HTTPS production adds
__Secure-cookie prefix — middleware must check bothbetter-auth.session_tokenand__Secure-better-auth.session_token router.push()auto-prepends basePath — never manually add/studioto paths used in client-side navigation or callbackUrl paramsrequest.nextUrl.pathnamein middleware excludes basePath — e.g.,/levelsnot/studio/levels- Prisma requires
binaryTargets = ["native", "rhel-openssl-3.0.x"]for cross-platform deployment (macOS dev → Linux server)
Deployment
- Server:
root@119.91.211.52at/root/apps/meme-studio - Process Manager: PM2 (
ecosystem.config.js) - Script:
./deploy.sh— builds locally, rsyncs files (excluding node_modules), installs deps on server, restarts PM2 - Standalone output:
next.config.jssetsoutput: 'standalone' - Server uses
npm install --production+npx prisma generate(prisma is a devDependency)
Environment Variables
Required in .env:
DATABASE_URL=mysql://...
BETTER_AUTH_SECRET= # 32+ chars, generate with: openssl rand -base64 32
BETTER_AUTH_URL= # Origin only, NO path (e.g., http://localhost:3001)
NEXT_PUBLIC_APP_URL= # Same as BETTER_AUTH_URL
NEXT_PUBLIC_BASE_PATH= # /studio
ADMIN_EMAIL=
ADMIN_PASSWORD=
COS_SECRET_ID= # Tencent Cloud COS
COS_SECRET_KEY=
COS_BUCKET=
COS_REGION=
COS_APPID=
Important Notes
- Middleware uses cookie check only (Prisma doesn't work in Edge Runtime)
- Password hashing must use
hashPasswordfrombetter-auth/cryptofor compatibility - Session model requires
tokenfield with unique constraint - Git commit messages must be written in Chinese
Database Schema Changes
涉及 Prisma schema 修改时,不要自动跑 pnpm run db:push 或 prisma db push。
- 改完
prisma/schema.prisma后,根据 schema 写出对应的 MySQLALTER TABLE语句 给用户,让用户手动在 dev / prod 数据库上执行 - 跑
pnpm run db:generate让本地 Prisma client 同步类型(这一步是 OK 的) - 部署脚本
./deploy.sh也只跑npx prisma generate(只重生 client),不会自动 apply schema,所以线上库也需要用户手动执行 SQL - 理由:schema 变更需要人工 review(数据迁移、默认值、索引取舍),不应该由 Agent 在没有确认的情况下直接改库
新增可空字段示例(本次 difficulty_score / fun_score):
ALTER TABLE levels
ADD COLUMN difficulty_score TINYINT NULL,
ADD COLUMN fun_score TINYINT NULL;
新增非空字段需要同步给出现有行填默认值,需要在 SQL 里分两步走。