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

27 KiB

MemeStudio Server Project - Comprehensive Analysis

1. PROJECT OVERVIEW

Project Name: Meme Studio (谐音梗小游戏运营平台) Description: A homophone pun game operation platform built with Next.js 14 for level configuration management Current Version: 0.1.0 Key Purpose: Management platform for game levels, users, and mini-program users


2. FRAMEWORK & TECH STACK

Core Framework

  • Next.js: v14.2.28 (App Router)
  • Runtime: Node.js (Standalone output mode)
  • Language: TypeScript 5.8.2
  • Build Output: output: 'standalone' (for server deployment)

Authentication & Database

  • Auth System: Better Auth v1.2.7
    • Method: Email/Password with Prisma adapter
    • Session Duration: 7 days
    • Session Update Age: 1 day
    • Database Provider: MySQL via Prisma
  • ORM: Prisma v6.5.0
  • Database: MySQL
  • Adapter: Better Auth Prisma adapter

UI & Styling

  • UI Components: shadcn/ui (Radix UI based)
  • CSS Framework: Tailwind CSS v3.4.17
  • Form Handling: react-hook-form v7.54.2 + Zod validation
  • State Management: TanStack React Query v5.69.0
  • Drag & Drop: @dnd-kit (core v6.3.1 + sortable v10.0.0)
  • Icons: lucide-react v0.483.0

File Storage & CDN

  • Cloud Storage: Tencent Cloud COS (Object Storage Service)
  • SDK:
    • qcloud-cos-sts v3.1.1 (For temporary credentials)
    • cos-nodejs-sdk-v5 v2.14.0 (Server-side)
    • cos-js-sdk-v5 v1.10.1 (Client-side)

Utilities

  • UUID Generation: uuid v11.1.0
  • Password Hashing: bcryptjs v3.0.2 + better-auth/crypto
  • Form Validation: Zod v3.24.2

3. PROJECT STRUCTURE

MemeStudio/
├── app/                           # Next.js App Router
│   ├── (auth)/                    # Route group: No sidebar (login page)
│   │   └── login/
│   │       └── page.tsx
│   ├── (dashboard)/               # Route group: With sidebar (protected)
│   │   ├── layout.tsx
│   │   ├── levels/
│   │   │   └── page.tsx
│   │   ├── users/
│   │   │   └── page.tsx
│   │   └── wx-users/
│   │       └── page.tsx
│   ├── api/                       # API Routes
│   │   ├── auth/[...all]/
│   │   │   └── route.ts           # Better Auth endpoints
│   │   ├── levels/
│   │   │   ├── route.ts           # CRUD endpoints
│   │   │   └── reorder/
│   │   │       └── route.ts       # Batch update sort order
│   │   ├── cos/
│   │   │   └── temp-key/
│   │   │       └── route.ts       # Tencent COS credentials
│   │   ├── users/
│   │   │   └── route.ts           # User management CRUD
│   │   └── wx-users/
│   │       ├── route.ts           # Mini-program user list
│   │       ├── [id]/
│   │       │   └── route.ts       # Single user details
│   │       └── level-progress/
│   │           └── route.ts       # Batch delete progress
│   ├── layout.tsx                 # Root layout
│   ├── page.tsx                   # Home page (redirects to /levels)
│   └── providers.tsx              # Client providers
│
├── components/                    # React Components
│   ├── layout/
│   │   ├── header.tsx            # Header with session info
│   │   └── sidebar.tsx           # Navigation sidebar
│   ├── levels/
│   │   ├── level-list.tsx        # Drag-and-drop list
│   │   ├── level-card.tsx        # Individual level card
│   │   ├── level-dialog.tsx      # Create/edit dialog
│   │   └── image-uploader.tsx    # COS image upload
│   ├── users/
│   │   └── user-dialog.tsx       # User create/edit dialog
│   ├── wx-users/
│   │   └── wx-user-detail-dialog.tsx  # Mini-program user details
│   └── ui/                       # shadcn/ui components
│       ├── button.tsx
│       ├── input.tsx
│       ├── label.tsx
│       ├── dialog.tsx
│       ├── card.tsx
│       ├── textarea.tsx
│       └── spinner.tsx
│
├── lib/                          # Utilities & Helpers
│   ├── auth.ts                   # Better Auth configuration
│   ├── auth-client.ts            # Client-side auth hooks
│   ├── prisma.ts                 # Prisma singleton
│   ├── cos.ts                    # Tencent COS utilities
│   ├── api.ts                    # apiFetch helper with basePath
│   └── utils.ts                  # General utilities (cn for Tailwind)
│
├── types/                        # TypeScript interfaces
│   └── index.ts                  # All data models
│
├── prisma/
│   ├── schema.prisma             # Database schema
│   └── seed.ts                   # Seed script for admin user
│
├── public/                       # Static assets
├── middleware.ts                 # Session validation middleware
├── next.config.js               # Next.js configuration
├── tsconfig.json                # TypeScript config
├── tailwind.config.ts           # Tailwind CSS config
├── package.json                 # Dependencies
├── deploy.sh                    # Deployment script
└── ecosystem.config.js          # PM2 configuration

4. DATABASE SCHEMA (Prisma)

Models Overview

1. Level (Game Levels)

model Level {
  id         String   @id @default(uuid())
  imageUrl   String   @map("image_url")
  answer     String
  hint1      String?
  hint2      String?
  hint3      String?
  sortOrder  Int      @default(0) @map("sort_order")
  createdAt  DateTime @default(now()) @map("created_at")
  updatedAt  DateTime @updatedAt @map("updated_at")
  
  userProgress WxUserLevelProgress[]  # Relationship to progress
}
  • Stores game level information
  • Each level has one image, one answer, and up to 3 hints
  • sortOrder is used for drag-and-drop reordering
  • Related to WxUserLevelProgress (one-to-many)

2. User (Admin/Portal Users)

model User {
  id            String    @id @default(uuid())
  email         String    @unique
  emailVerified Boolean   @default(false)
  name          String?
  image         String?
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  
  sessions      Session[]
  accounts      Account[]
}
  • Better Auth user model
  • Email-password authentication
  • Can have multiple sessions and accounts

3. Session (Auth Sessions)

model Session {
  id           String   @id
  expiresAt    DateTime
  token        String   @unique
  ipAddress    String?
  userAgent    String?
  userId       String
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}
  • Better Auth session model
  • Stores session tokens with IP and user agent info
  • 7-day expiration

4. Account (Auth Accounts)

model Account {
  id                   String    @id @default(uuid())
  accountId            String
  providerId           String
  userId               String
  accessToken          String?
  refreshToken         String?
  idToken              String?
  accessTokenExpires   DateTime?
  refreshTokenExpires  DateTime?
  scope                String?
  password             String?   # Hash for email/password provider
  createdAt            DateTime  @default(now())
  updatedAt            DateTime  @updatedAt
  
  user                 User      @relation(fields: [userId], references: [id], onDelete: Cascade)
}
  • Better Auth account model
  • Supports multiple auth providers
  • Stores hashed passwords for credential provider

5. Verification (Email Verification)

model Verification {
  id         String   @id @default(uuid())
  identifier String
  value      String
  expiresAt  DateTime
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
}
  • Better Auth verification model for email verification tokens

6. WxUser (Mini-Program Users)

model WxUser {
  id         String   @id @default(uuid())
  openid     String   @unique
  sessionKey String?
  nickname   String?
  avatarUrl  String?
  points     Int      @default(10)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  
  levelProgress WxUserLevelProgress[]
}
  • Users from WeChat mini-program
  • OpenID uniquely identifies users (WeChat standard)
  • Stores user points/score
  • Related to level progress

7. WxUserLevelProgress (User Progress Tracking)

model WxUserLevelProgress {
  id          String   @id @default(uuid())
  userId      String
  levelId     String
  completedAt DateTime @default(now())
  
  user        WxUser   @relation(fields: [userId], references: [id], onDelete: Cascade)
  level       Level    @relation(fields: [levelId], references: [id])
}
  • Tracks which levels each WeChat user has completed
  • Stores completion timestamp
  • Composite relationship between WxUser and Level

Database Configuration

  • Provider: MySQL
  • Connection String: Defined via DATABASE_URL env var
  • Targets: ["native", "rhel-openssl-3.0.x"] for cross-platform compatibility (macOS dev → Linux server)

5. API ROUTES - COMPREHENSIVE DOCUMENTATION

Authentication Routes

POST /api/auth/[...all]

  • Handler: Better Auth routes
  • Auth: Yes (Better Auth handles internally)
  • Purpose: All authentication endpoints
  • Endpoints Provided:
    • POST /api/auth/sign-up - User registration
    • POST /api/auth/sign-in - User login
    • POST /api/auth/sign-out - User logout
    • GET /api/auth/session - Get current session
    • etc. (all Better Auth endpoints)

Levels Management

GET /api/levels

  • Auth: Required (401 if unauthorized)
  • Purpose: Fetch all game levels
  • Query Params: None
  • Returns: Array of Level objects, ordered by sortOrder ASC
  • Response:
    [
      {
        "id": "uuid",
        "imageUrl": "https://...",
        "answer": "答案",
        "hint1": "提示1",
        "hint2": null,
        "hint3": null,
        "sortOrder": 0,
        "createdAt": "2026-04-05T...",
        "updatedAt": "2026-04-05T..."
      }
    ]
    

POST /api/levels

  • Auth: Required
  • Purpose: Create a new game level
  • Request Body:
    {
      "imageUrl": "string (required)",
      "answer": "string (required)",
      "hint1": "string (optional)",
      "hint2": "string (optional)",
      "hint3": "string (optional)"
    }
    
  • Logic:
    • Gets max sortOrder and sets new level to max+1
    • Uses UUID for ID
    • Validates required fields (imageUrl, answer)
  • Returns: Created Level object (201)

PUT /api/levels

  • Auth: Required
  • Purpose: Update an existing level
  • Request Body:
    {
      "id": "string (required)",
      "imageUrl": "string",
      "answer": "string",
      "hint1": "string",
      "hint2": "string",
      "hint3": "string"
    }
    
  • Logic: Direct update via Prisma
  • Returns: Updated Level object

DELETE /api/levels

  • Auth: Required
  • Purpose: Delete a level
  • Query Params: id (string, required)
  • Returns: { "success": true }

PUT /api/levels/reorder

  • Auth: Required
  • Purpose: Batch update sort order for drag-and-drop
  • Request Body:
    {
      "orders": [
        { "id": "level-id", "sortOrder": 0 },
        { "id": "level-id", "sortOrder": 1 }
      ]
    }
    
  • Logic: Uses Prisma transaction to update all in parallel
  • Returns: { "success": true }

Users Management (Admin/Portal Users)

GET /api/users

  • Auth: Required
  • Purpose: Fetch all portal users
  • Query Params: None
  • Returns: Array of User objects (ordered by createdAt DESC)
  • Excludes: Password hash is not returned

POST /api/users

  • Auth: Required
  • Purpose: Create a new portal user
  • Request Body:
    {
      "email": "string (required)",
      "password": "string (required)",
      "name": "string (optional)"
    }
    
  • Logic:
    • Checks if email already exists (error: "该邮箱已被注册")
    • Hashes password using better-auth/crypto
    • Creates User + Account in transaction
    • Account has providerId="credential"
  • Returns: Created User object (201)

PUT /api/users

  • Auth: Required
  • Purpose: Update a portal user
  • Request Body:
    {
      "id": "string (required)",
      "email": "string (optional)",
      "password": "string (optional)",
      "name": "string (optional)"
    }
    
  • Logic:
    • Validates email not taken by another user
    • Updates password if provided (hashing in transaction)
    • Uses transaction for consistency
  • Returns: Updated User object

DELETE /api/users

  • Auth: Required
  • Purpose: Delete a portal user
  • Query Params: id (string, required)
  • Logic:
    • Prevents deleting yourself (checks session.user.id)
    • Error: "不能删除自己的账户"
  • Returns: { "success": true }

Mini-Program Users

GET /api/wx-users

  • Auth: Required
  • Purpose: Get WeChat mini-program users with pagination and search
  • Query Params:
    • search - Search in nickname or openid (optional)
    • page - Page number (default: 1)
    • limit - Results per page (default: 20)
  • Logic:
    • Search: OR condition on nickname.contains and openid.contains
    • Returns paginated results with metadata
  • Returns:
    {
      "users": [
        {
          "id": "uuid",
          "openid": "string",
          "nickname": "string",
          "avatarUrl": "string",
          "points": 10,
          "createdAt": "2026-04-05T...",
          "updatedAt": "2026-04-05T..."
        }
      ],
      "meta": {
        "total": 100,
        "page": 1,
        "limit": 20,
        "totalPages": 5
      }
    }
    
  • Performance: Uses select to exclude sessionKey

GET /api/wx-users/[id]

  • Auth: Required
  • Purpose: Get single WeChat user with level progress history
  • Params: id - User UUID
  • Returns:
    {
      "id": "uuid",
      "openid": "string",
      "nickname": "string",
      "avatarUrl": "string",
      "points": 10,
      "createdAt": "2026-04-05T...",
      "updatedAt": "2026-04-05T...",
      "levelProgress": [
        {
          "id": "uuid",
          "userId": "uuid",
          "levelId": "uuid",
          "completedAt": "2026-04-05T...",
          "level": {
            "id": "uuid",
            "answer": "答案"
          }
        }
      ]
    }
    
  • Logic: Includes levelProgress ordered by completedAt DESC

DELETE /api/wx-users/level-progress

  • Auth: Required
  • Purpose: Batch delete level progress records
  • Request Body:
    {
      "ids": ["progress-id-1", "progress-id-2"]
    }
    
  • Logic:
    • Validates ids is non-empty array of strings
    • Uses deleteMany with IN clause
  • Returns: { "deleted": 5 }

COS (Tencent Cloud Object Storage)

GET /api/cos/temp-key

  • Auth: Required
  • Purpose: Get temporary credentials for frontend image upload
  • Query Params: None
  • Logic:
    • Uses Tencent COS STS service
    • Generates temp credentials valid for 30 minutes (1800 seconds)
    • Restricts upload to mini_game/images/* prefix
  • Returns:
    {
      "credentials": {
        "tmpSecretId": "string",
        "tmpSecretKey": "string",
        "sessionToken": "string"
      },
      "startTime": 1712345678,
      "expiredTime": 1712347478,
      "bucket": "lookai-1308511832",
      "region": "ap-guangzhou"
    }
    

Authentication Patterns

  • Session Check Pattern:
    const session = await auth.api.getSession({ headers: request.headers })
    if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
    
  • All routes use the same pattern (except Better Auth routes)
  • No role/permission system yet - all authenticated users have full access

6. MIDDLEWARE & AUTHENTICATION

File: middleware.ts

Location: Root level Purpose: Session validation for protected pages

Features:

  • Checks for session cookies on protected pages
  • Handles both HTTP and HTTPS cookie naming:
    • better-auth.session_token (HTTP)
    • __Secure-better-auth.session_token (HTTPS with Secure prefix)
  • Redirects to login if no session
  • Allows public access to:
    • /login page
    • /api/* routes (API auth handled separately)
    • Static assets (/_next, /favicon, files with extensions)
  • Important: Middleware runs at Edge Runtime, so cannot use Prisma - only cookie check
  • Preserves callbackUrl for redirect after login

basePath Gotcha:

  • request.nextUrl.pathname does NOT include basePath
  • Path comparison is done without /studio prefix
  • Redirect URLs must manually prepend basePath

Better Auth Configuration

File: lib/auth.ts

export const auth = betterAuth({
  database: prismaAdapter(prisma, { provider: 'mysql' }),
  emailAndPassword: { enabled: true },
  basePath: '/api/auth',
  trustedOrigins: [process.env.BETTER_AUTH_URL],
  secret: process.env.BETTER_AUTH_SECRET,
  session: {
    expiresIn: 60 * 60 * 24 * 7,      // 7 days
    updateAge: 60 * 60 * 24,           // Update token every 1 day of activity
  },
})

Key Points:

  • Uses Prisma adapter for MySQL
  • basePath: /api/auth (NOT /studio/api/auth)
  • BETTER_AUTH_URL must be origin only (NO path component)
  • Secret must be 32+ characters
  • Sessions auto-refresh if 1+ day of activity

Client Auth Hooks

File: lib/auth-client.ts

export const { signIn, signOut, useSession } = authClient

Provides:

  • useSession() hook - Get current session data
  • signIn() - Login function
  • signOut() - Logout function
  • Automatically uses basePath + appUrl to construct auth endpoint URL

7. LIBRARY UTILITIES

lib/api.ts - API Fetch Helper

export function apiFetch(input: string, init?: RequestInit): Promise<Response>
  • Prepends basePath to API routes
  • Example: apiFetch('/api/levels')/studio/api/levels
  • Used throughout all client components

lib/prisma.ts - Prisma Singleton

const prisma = globalForPrisma.prisma ?? new PrismaClient()
  • Prevents multiple Prisma instances in development (hot reload)
  • Exports single prisma instance for all API routes

lib/cos.ts - Tencent COS Utilities

Functions:

  • getTempKey() - Get temporary STS credentials
    • Duration: 30 minutes
    • Policy: Upload only to mini_game/images/*
  • getBucketName() - Format bucket name (appends APPID if needed)
  • getBucketConfig() - Get bucket and region for SDK

lib/utils.ts - General Utilities

export function cn(...inputs: ClassValue[])
  • Tailwind CSS utility merger (clsx + tailwind-merge)
  • Used throughout components for className management

8. UI COMPONENTS & PATTERNS

Component Structure

All components use React patterns:

  • Client Components: 'use client' directive
  • Controlled Forms: State-driven form handling
  • TanStack Query: For server state management
  • Dialog-based Operations: Create/Edit in modals

Key Components

Pages

  1. Levels Page (app/(dashboard)/levels/page.tsx)

    • List all levels with drag-and-drop reordering
    • Add/Edit/Delete levels
    • Uses TanStack Query mutations
  2. Users Page (app/(dashboard)/users/page.tsx)

    • Table view of portal users
    • Add/Edit/Delete users
    • Delete prevention (can't delete self)
  3. WeChat Users Page (app/(dashboard)/wx-users/page.tsx)

    • Search and pagination
    • Click to view user details + progress history
    • Batch delete progress records

UI Components

  • Button: shadcn/ui with variants (default, outline, ghost)
  • Input/Textarea: Form inputs
  • Dialog: Modal dialogs with header, content, footer
  • Spinner: Loading indicator
  • Card: Container component

Image Upload Flow

  1. User clicks upload in level dialog
  2. Frontend calls /api/cos/temp-key to get credentials
  3. Frontend uses Tencent COS SDK to upload directly to COS
  4. COS returns image URL
  5. URL stored in database

Form Submission Pattern

// TanStack Query mutation
const mutation = useMutation({
  mutationFn: async (data) => { /* API call */ },
  onSuccess: () => { queryClient.invalidateQueries(...) }
})

// On form submit
await mutation.mutateAsync(data)
// Automatic refetch on success

9. ENVIRONMENT VARIABLES

Required Variables

# Database
DATABASE_URL=mysql://user:password@host:port/database

# Better Auth
BETTER_AUTH_SECRET=32+ character random string
BETTER_AUTH_URL=https://domain.com (origin only, NO path)

# Public URLs (Client-side)
NEXT_PUBLIC_APP_URL=https://domain.com (same as BETTER_AUTH_URL)
NEXT_PUBLIC_BASE_PATH=/studio

# Admin Account (Seed script)
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=secure_password

# Tencent COS
COS_SECRET_ID=AKID...
COS_SECRET_KEY=...
COS_BUCKET=lookai-1308511832
COS_REGION=ap-guangzhou
COS_APPID=1308511832

Important Notes

  • BETTER_AUTH_URL: Must NOT contain path (e.g., https://domain.com/studio, https://domain.com)
  • NEXT_PUBLIC_BASE_PATH: Used client-side for apiFetch
  • COS_BUCKET: Can include or exclude APPID (utility handles both)

10. DEPLOYMENT & CONFIGURATION

Next.js Configuration (next.config.js)

{
  output: 'standalone',  // Single binary output
  basePath: '/studio',   // App served at /studio
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: '*.myqcloud.com' }  // Allow COS images
    ]
  }
}

Deployment Setup

Server: root@119.91.211.52 at /root/apps/meme-studio Process Manager: PM2 (ecosystem.config.js)

Deploy Script (./deploy.sh):

  1. Build locally: next build
  2. rsync files (excludes node_modules, .next)
  3. SSH to server, run:
    • npm install --production
    • npx prisma generate
    • Restart PM2 process

Key Gotchas:

  • Prisma is devDependency but needs to be generated on server
  • output: 'standalone' bundles Next.js runtime
  • Deployment requires DATABASE_URL set on server
  • Cross-platform binary target: rhel-openssl-3.0.x for Linux server

11. EXISTING PATTERNS & CONVENTIONS

API Route Pattern

// 1. Import required modules
import { auth } from '@/lib/auth'
import { prisma } from '@/lib/prisma'

// 2. Check session
const session = await auth.api.getSession({ headers: request.headers })
if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

// 3. Parse request
const body = await request.json()
const { searchParams } = new URL(request.url)

// 4. Validate input
if (!required_field) return NextResponse.json({ error: 'msg' }, { status: 400 })

// 5. Database operation
const result = await prisma.model.operation()

// 6. Return response
return NextResponse.json(result, { status: 201 })

Mutation Pattern (Client)

const mutation = useMutation({
  mutationFn: async (data) => {
    const res = await apiFetch('/api/endpoint', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    })
    if (!res.ok) {
      const error = await res.json()
      throw new Error(error.error || 'Failed')
    }
    return res.json()
  },
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['levels'] })
  },
})

mutation.mutate(data)

Type Definitions Pattern

// Database model
export interface Level {
  id: string
  imageUrl: string
  // ...
  createdAt: Date
  updatedAt: Date
}

// Form data (typically a subset)
export interface LevelFormData {
  imageUrl: string
  answer: string
  hint1?: string
  // ... (no id, dates for new records)
}

12. KEY GOTCHAS & IMPORTANT NOTES

1. basePath Handling

  • request.nextUrl.pathname excludes basePath (returns /levels, not /studio/levels)
  • Never manually prepend /studio in API routes
  • Client-side: use apiFetch() which prepends basePath automatically
  • router.push() auto-prepends basePath, don't add manually

2. Better Auth Configuration

  • CRITICAL: BETTER_AUTH_URL must be origin only, NO path component
  • Better Auth's withPath() silently ignores basePath if URL has path
  • Cookie naming: HTTPS adds __Secure- prefix
  • Middleware must check both cookie names

3. Session Validation

  • Middleware: Cookie check only (no Prisma in Edge Runtime)
  • API Routes: Full session validation with auth.api.getSession()
  • Middleware doesn't verify token validity, only presence

4. Database Relationships

  • No explicit join tables for many-to-many (not needed here)
  • One-to-many: WxUser → WxUserLevelProgress → Level
  • Cascade delete: Sessions/Accounts deleted when User deleted

5. Image Upload Flow

  • Frontend gets temp credentials from /api/cos/temp-key
  • Frontend uploads directly to COS (not through backend)
  • Backend only stores URL
  • URLs expire or become invalid if credentials expire

6. Authentication Flow

  • Login → Session created → Cookie set
  • Page navigation → Middleware checks cookie
  • Redirects to login if missing
  • All API calls check session in route handler

7. Search Patterns

  • WeChat users: OR condition on nickname OR openid contains
  • Case-sensitive by default (MySQL depends on collation)
  • Pagination: skip = (page - 1) * limit

13. ABSENCE OF SHARE/INVITE LOGIC

Current Status: NO sharing/invite functionality exists

What's Missing:

  • No share link/token model in schema
  • No invite API endpoint
  • No permissions/role system
  • All authenticated users have full admin access to:
    • Level management
    • User management
    • WeChat user data

Considerations for Implementation:

  • Determine if shares/invites are for:
    • Sharing levels with mini-program users?
    • Inviting new admins to platform?
    • Sharing user progress data?
  • Would need new database model
  • Permission checks in API routes
  • Share link generation and validation
  • Expiration logic

14. RECOMMENDATIONS FOR EXPLORATION

For Share/Invite Feature (if needed):

  1. Schema Design:

    • ShareToken model with expiry, permissions
    • Or UserRole model for permission levels
  2. API Endpoints Needed:

    • POST /api/shares - Generate share link
    • GET /api/shares/[token] - Validate share token
    • DELETE /api/shares/[id] - Revoke share
  3. Permission System:

    • Add role field to User model
    • Permission checks in middleware or API routes
  4. Frontend Needed:

    • Share dialog component
    • Permission management UI

SUMMARY TABLE

Category Item Details
Framework Next.js 14.2.28, App Router, Standalone output
Auth Better Auth Email/password, MySQL Prisma adapter
Database MySQL Prisma ORM, 7 models
Storage Tencent COS STS temp credentials, 30 min validity
UI shadcn/ui Tailwind, React Query, @dnd-kit
Deployment PM2 Server at 119.91.211.52, basePath=/studio
Auth Routes 5 endpoints Levels, Users, WxUsers, COS, Auth
Protected Routes YES Middleware + per-route checks
Sharing NONE Not implemented
Permissions FLAT All authenticated users = full admin
Search Implemented WeChat users only (nickname, openid)