Files
MemeStudio/QUICK_REFERENCE.md
2026-05-01 08:44:56 +08:00

7.8 KiB

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

# 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!)
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)