241 lines
7.8 KiB
Markdown
241 lines
7.8 KiB
Markdown
# MemeStudio - Quick Reference Guide
|
|
|
|
## 🏗️ ARCHITECTURE AT A GLANCE
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Next.js 14 (App Router) │
|
|
│ With basePath=/studio │
|
|
└──────────────┬──────────────────────────────────────────┘
|
|
│
|
|
┌─────────┴─────────┐
|
|
│ │
|
|
┌────▼────┐ ┌──────▼─────┐
|
|
│ Frontend │ │ API Routes │
|
|
│ Pages │ │ (Protected)│
|
|
│ & UX │ └──────┬─────┘
|
|
└────┬────┘ │
|
|
│ ┌──────┴─────────────────┐
|
|
│ │ Better Auth (7-day) │
|
|
│ └──────┬─────────────────┘
|
|
│ │
|
|
└───────────┬───────┘
|
|
│
|
|
┌────────▼────────┐
|
|
│ MySQL via │
|
|
│ Prisma ORM │
|
|
│ (7 models) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
## 📊 DATABASE MODELS (7)
|
|
|
|
| Model | Purpose | Key Fields |
|
|
|-------|---------|-----------|
|
|
| **Level** | Game levels | id, imageUrl, answer, hint1-3, sortOrder |
|
|
| **User** | Admin users | id, email, name, password (in Account) |
|
|
| **Session** | Auth sessions | id, token (unique), expiresAt, userId |
|
|
| **Account** | Auth accounts | id, password, providerId, userId |
|
|
| **Verification** | Email verification | id, identifier, expiresAt |
|
|
| **WxUser** | Mini-program users | id, openid, nickname, points |
|
|
| **WxUserLevelProgress** | User progress | id, userId, levelId, completedAt |
|
|
|
|
## 🔐 AUTH FLOW
|
|
|
|
```
|
|
1. User Login
|
|
└─> POST /api/auth/sign-in (Better Auth)
|
|
└─> Session created in DB
|
|
└─> Cookie set (7-day expiry)
|
|
|
|
2. Page Navigation
|
|
└─> Middleware checks cookie
|
|
├─> If missing → Redirect to login
|
|
└─> If present → Allow access
|
|
|
|
3. API Calls
|
|
└─> auth.api.getSession({ headers: request.headers })
|
|
├─> If null → Return 401 Unauthorized
|
|
└─> If valid → Proceed with operation
|
|
```
|
|
|
|
## 🛣️ API ENDPOINTS (14 total)
|
|
|
|
### Auth (1 catch-all)
|
|
- `POST /api/auth/[...all]` - Better Auth routes
|
|
|
|
### Levels (4 routes)
|
|
- `GET /api/levels` - List all (sorted by sortOrder)
|
|
- `POST /api/levels` - Create new (auto-increment sortOrder)
|
|
- `PUT /api/levels` - Update existing
|
|
- `DELETE /api/levels?id=...` - Delete level
|
|
- `PUT /api/levels/reorder` - Batch reorder (transaction)
|
|
|
|
### Users (4 routes)
|
|
- `GET /api/users` - List all admin users
|
|
- `POST /api/users` - Create new admin
|
|
- `PUT /api/users` - Update user/password
|
|
- `DELETE /api/users?id=...` - Delete user (prevent self-delete)
|
|
|
|
### WeChat Users (3 routes)
|
|
- `GET /api/wx-users?search=...&page=...` - List with pagination
|
|
- `GET /api/wx-users/[id]` - Get user with progress history
|
|
- `DELETE /api/wx-users/level-progress` - Batch delete progress
|
|
|
|
### COS (1 route)
|
|
- `GET /api/cos/temp-key` - Get 30-min temp credentials
|
|
|
|
## 📁 PROJECT STRUCTURE
|
|
|
|
```
|
|
MemeStudio/
|
|
├── app/
|
|
│ ├── (auth)/login/page.tsx # Public login
|
|
│ ├── (dashboard)/ # Protected pages
|
|
│ │ ├── levels/page.tsx # Levels UI + CRUD
|
|
│ │ ├── users/page.tsx # User management
|
|
│ │ └── wx-users/page.tsx # WeChat users
|
|
│ └── api/ # All API routes
|
|
├── lib/
|
|
│ ├── auth.ts # Better Auth config
|
|
│ ├── auth-client.ts # Client hooks
|
|
│ ├── prisma.ts # Singleton
|
|
│ ├── cos.ts # COS utilities
|
|
│ ├── api.ts # apiFetch (adds basePath)
|
|
│ └── utils.ts # Tailwind cn()
|
|
├── components/ # React UI components
|
|
├── prisma/schema.prisma # Database schema
|
|
├── middleware.ts # Session validation
|
|
├── types/index.ts # TypeScript interfaces
|
|
└── next.config.js # basePath=/studio config
|
|
```
|
|
|
|
## 🔑 ENVIRONMENT VARIABLES
|
|
|
|
```bash
|
|
# Required
|
|
DATABASE_URL=mysql://user:pass@host:port/db
|
|
BETTER_AUTH_SECRET=32+ chars
|
|
BETTER_AUTH_URL=https://domain.com # ⚠️ NO path!
|
|
NEXT_PUBLIC_APP_URL=https://domain.com
|
|
NEXT_PUBLIC_BASE_PATH=/studio
|
|
|
|
# Admin seed
|
|
ADMIN_EMAIL=user@example.com
|
|
ADMIN_PASSWORD=password
|
|
|
|
# Tencent COS
|
|
COS_SECRET_ID=AKID...
|
|
COS_SECRET_KEY=...
|
|
COS_BUCKET=lookai-1308511832
|
|
COS_REGION=ap-guangzhou
|
|
COS_APPID=1308511832
|
|
```
|
|
|
|
## ⚙️ KEY UTILITIES
|
|
|
|
### `apiFetch(path, options)` - API Wrapper
|
|
- Automatically prepends basePath
|
|
- Usage: `apiFetch('/api/levels')` → requests `/studio/api/levels`
|
|
- Used in all client components
|
|
|
|
### `getTempKey()` - COS Credentials
|
|
- Returns temp credentials valid 30 minutes
|
|
- Restricts uploads to `mini_game/images/*`
|
|
- Called before image upload
|
|
|
|
### `useSession()` - Auth Hook
|
|
- Returns: `{ data: session, isPending: boolean }`
|
|
- Shows current user email in header
|
|
- Used in all protected pages
|
|
|
|
## 🚀 DEPLOYMENT
|
|
|
|
**Server**: `root@119.91.211.52:/root/apps/meme-studio`
|
|
**Process**: PM2
|
|
**Staging**: `/studio` path (reverse proxy)
|
|
|
|
**Deploy Steps**:
|
|
1. `npm run build` (locally)
|
|
2. `./deploy.sh` (rsync + npm install + PM2 restart)
|
|
|
|
## ⚠️ CRITICAL GOTCHAS
|
|
|
|
### 1. basePath Issues
|
|
```
|
|
❌ request.nextUrl.pathname INCLUDES basePath in Next.js 12
|
|
✅ request.nextUrl.pathname EXCLUDES basePath in Next.js 13+/14
|
|
✅ Middleware: DO check for `/levels`, NOT `/studio/levels`
|
|
❌ Don't manually prepend /studio to routes
|
|
✅ Use apiFetch() which handles basePath automatically
|
|
```
|
|
|
|
### 2. Better Auth Configuration
|
|
```
|
|
✅ BETTER_AUTH_URL = "https://domain.com"
|
|
❌ BETTER_AUTH_URL = "https://domain.com/studio" (WRONG!)
|
|
✅ basePath = "/api/auth"
|
|
❌ basePath = "/studio/api/auth" (WRONG!)
|
|
```
|
|
|
|
### 3. Cookie Naming
|
|
```
|
|
HTTP: better-auth.session_token
|
|
HTTPS: __Secure-better-auth.session_token
|
|
Middleware checks both!
|
|
```
|
|
|
|
### 4. Image Upload
|
|
```
|
|
Frontend → GET /api/cos/temp-key
|
|
→ Upload directly to COS (no backend)
|
|
→ Backend stores URL only
|
|
→ (Frontend handles COS SDK)
|
|
```
|
|
|
|
## 🔍 NO SHARING/INVITE LOGIC
|
|
|
|
✅ What Exists:
|
|
- Basic auth (email/password)
|
|
- User management (admins only)
|
|
- Level CRUD
|
|
- WeChat user tracking
|
|
|
|
❌ What's Missing:
|
|
- Share links/tokens
|
|
- Permission system (all authenticated = full admin)
|
|
- Invite workflows
|
|
- Role-based access
|
|
|
|
## 💡 COMMON TASKS
|
|
|
|
### Add a new API endpoint
|
|
1. Create file: `app/api/resource/route.ts`
|
|
2. Follow session check pattern
|
|
3. Use `apiFetch()` from client
|
|
4. Add types in `types/index.ts`
|
|
|
|
### Modify database schema
|
|
1. Edit `prisma/schema.prisma`
|
|
2. Run `pnpm run db:push` (dev) or `db:migrate`
|
|
3. Generate types: `pnpm run db:generate`
|
|
|
|
### Deploy to production
|
|
1. Push changes to git
|
|
2. Run `pnpm run deploy` (builds locally + deploys via ssh)
|
|
|
|
## 📋 QUICK STATS
|
|
|
|
- **Framework**: Next.js 14.2.28 (App Router)
|
|
- **Auth**: Better Auth v1.2.7
|
|
- **Database**: MySQL + Prisma v6.5.0
|
|
- **UI**: shadcn/ui + Tailwind CSS
|
|
- **State**: TanStack React Query
|
|
- **Storage**: Tencent COS
|
|
- **Deployment**: PM2 on Linux server
|
|
- **Code Language**: TypeScript
|
|
- **Session Duration**: 7 days
|
|
- **COS Temp Credentials**: 30 minutes
|
|
- **Protected Routes**: All except /login and /api/* (handled separately)
|
|
|