125 lines
4.9 KiB
Markdown
125 lines
4.9 KiB
Markdown
# 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
|
||
|
||
```bash
|
||
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 config
|
||
- `lib/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, sortOrder
|
||
- `User`, `Session`, `Account`, `Verification` - Better Auth models
|
||
|
||
### basePath & Reverse Proxy
|
||
|
||
The app is deployed behind a reverse proxy at `/studio` path:
|
||
- `next.config.js` sets `basePath: '/studio'`
|
||
- All pages and API routes are served under `/studio/...`
|
||
|
||
**Critical gotchas**:
|
||
- **Next.js strips basePath from `request.url` in route handlers** — Better Auth's `basePath` must be `/api/auth` (without `/studio`), not `/studio/api/auth`
|
||
- **`BETTER_AUTH_URL` must NOT contain a path** (just the origin like `http://localhost:3001`) — Better Auth's `withPath()` silently ignores the `basePath` config if the URL already has a path component
|
||
- **HTTPS production adds `__Secure-` cookie prefix** — middleware must check both `better-auth.session_token` and `__Secure-better-auth.session_token`
|
||
- **`router.push()` auto-prepends basePath** — never manually add `/studio` to paths used in client-side navigation or callbackUrl params
|
||
- **`request.nextUrl.pathname` in middleware excludes basePath** — e.g., `/levels` not `/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.52` at `/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.js` sets `output: '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 `hashPassword` from `better-auth/crypto` for compatibility
|
||
- Session model requires `token` field 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 写出对应的 MySQL `ALTER 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):
|
||
|
||
```sql
|
||
ALTER TABLE levels
|
||
ADD COLUMN difficulty_score TINYINT NULL,
|
||
ADD COLUMN fun_score TINYINT NULL;
|
||
```
|
||
|
||
新增非空字段需要同步给出现有行填默认值,需要在 SQL 里分两步走。
|
||
|