This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The main application is in the main/ directory. Always cd into main/ before running commands:
cd main/npm run dev- Start development servernpm run build- Build production application (includes Prisma generation)npm run start- Start production servernpm run lint- Run ESLint for code quality
npm run db:generate- Generate Prisma clientnpm run db:migrate- Legacy migration command; do not use for the current database workflownpm run db:studio- Open Prisma Studio for database managementnpm run db:push- Push schema changes to databasenpm run db:pull- Pull schema from database
Current database iteration workflow:
- Run
npm run db:pullbefore editing to synchronize the database source of truth. - Update
prisma/schema.prisma. - Review the live database-to-schema diff.
- Run
npm run db:pushto update the database.
Do not add a Prisma migration for normal feature schema changes unless the team explicitly changes this workflow.
This is a Next.js 15 application for a Cantonese language learning platform with data annotation capabilities.
- Framework: Next.js 15 with App Router
- Database: PostgreSQL with Prisma ORM
- Authentication: NextAuth.js with WeChat, Email, and SMS providers
- UI: Radix UI components with Tailwind CSS
- State Management: Zustand stores
- Query Management: TanStack Query
- Web: NextAuth.js with WeChat OAuth, email-based, and SMS-based authentication
- Miniprogram: JWT-based authentication using WeChat openId/unionId
- Role-based access control with 4 user roles:
LEARNER,TAGGER_PARTNER,TAGGER_OUTSOURCING,RESEARCHER - Middleware protects routes based on user roles
- Marker-specific routes require
TAGGER_PARTNERorTAGGER_OUTSOURCINGroles
- Users: Core user information with role-based permissions
- Corpus Data: Cantonese language corpus with annotations (
cantonese_corpus_all) - Data Annotation: Update history tracking for corpus modifications
- Categories & Apps: Content organization and application management
- API Keys: User API access management
app/- Next.js App Router pages and API routescomponents/- Reusable UI components organized by typelib/- Utilities, API clients, auth configuration, and storesprisma/- Database schema; current feature changes use db pull/db pushproviders/- Authentication and query providers
/api/auth/- NextAuth.js authentication endpoints (Web)/api/miniprogram/- WeChat miniprogram API endpoints (JWT-protected)/api/miniprogram/auth/login- Miniprogram login with WeChat code/api/miniprogram/auth/refresh- Refresh access token/api/miniprogram/user/*- User-related operations
/api/marker/- Marker-specific operations (role-protected)/api/public/- Public API endpoints/api/user/- User management operations
lib/auth.ts- NextAuth configuration with WeChat/Email/SMS providers (Web)lib/services/aliyun-sms.ts- Aliyun SMS service for phone verificationlib/miniprogram-jwt.ts- JWT token generation and verification for miniprogramlib/miniprogram-auth.ts- Miniprogram authentication middlewaremiddleware.ts- Route protection and role-based access controlprisma/schema.prisma- Database schema with multilingual corpus datalib/store/- Zustand state management stores
This project requires PostgreSQL database connection and WeChat OAuth credentials for full functionality.
# Database
DATABASE_URL="postgresql://..."
DIRECT_URL="postgresql://..."
# NextAuth (Web)
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key" # Used for both web and miniprogram JWT
# WeChat Web OAuth
NEXT_PUBLIC_WECHAT_CLIENT_ID="your-wechat-web-appid"
WECHAT_CLIENT_SECRET="your-wechat-web-secret"
# WeChat Miniprogram
WECHAT_MINIPROGRAM_APPID="your-miniprogram-appid"
WECHAT_MINIPROGRAM_SECRET="your-miniprogram-secret"The miniprogram uses WeChat's wx.login() to get a code, then exchanges it for access tokens.
Endpoint: POST /api/miniprogram/auth/login
Request:
{
"code": "wx_login_code_from_wx.login()"
}Response:
{
"accessToken": "jwt_access_token",
"refreshToken": "jwt_refresh_token",
"user": {
"id": "user_id",
"name": "User Name",
"avatar": "avatar_url",
"role": "LEARNER",
"isSystemAdmin": false
}
}Note: Users must register via web first. The miniprogram login will fail if the user doesn't exist in the database.
Access tokens expire after 7 days. Use the refresh token to get a new access token.
Endpoint: POST /api/miniprogram/auth/refresh
Request:
{
"refreshToken": "jwt_refresh_token"
}Response:
{
"accessToken": "new_jwt_access_token",
"refreshToken": "new_jwt_refresh_token"
}Include the access token in the Authorization header:
Authorization: Bearer <accessToken>
Example: GET /api/miniprogram/user/profile
Use the authentication middleware from lib/miniprogram-auth.ts:
import { requireMiniprogramAuth } from "@/lib/miniprogram-auth";
export async function GET(req: NextRequest) {
return requireMiniprogramAuth(req, async (req, user) => {
// user contains: userId, openId, unionId, role, isSystemAdmin
// Your logic here
return NextResponse.json({ data: "your data" });
});
}Available middleware:
requireMiniprogramAuth- Basic authenticationrequireMiniprogramRole- Require specific rolesrequireMiniprogramMarker- Require TAGGER_PARTNER or TAGGER_OUTSOURCINGrequireMiniprogramAdmin- Require system admin