Engineering Coding Standards & Collaboration Guide
This document aims to unify the project's code style, architecture design, and collaboration workflow to ensure maintainability, extensibility, and consistency of the codebase. All contributors must read and follow this guide before submitting code.
Core Architecture Design Principles
Layered Architecture
This project adopts a clear layered architecture with strict separation of concerns:
- API Layer (
src/app/api): Handles HTTP requests, performs parameter validation and permission checks, then calls the Service Layer. Should not contain core business logic. - Service Layer (
src/lib/services): Home of core business logic. Responsible for handling specific business rules, data assembly, calling ORM and other services.client/: Services for end users (e.g.,subscription-service.ts,credits-service.ts)admin/: Services for administrators (e.g.,admin-service.ts)settings/: System configuration related services
- Data Access Layer (
src/lib/database.ts, Drizzle ORM): Responsible for database interactions - Lib/Utils (
src/lib): Common utility functions, constant definitions, third-party library wrappers (e.g.,src/lib/payment,src/lib/email)
Dependency Injection & Singleton Pattern
- For complex external dependencies (e.g., payment gateways, storage services), use Factory Pattern or Strategy Pattern for encapsulation, providing a unified interface
- Example:
src/lib/payment/gateway-factory.tsdynamically returnsStripeGatewayorCreemGatewayinstances based on configuration
- Example:
- Service classes typically export singleton instances for direct invocation while maintaining state consistency (if needed)
- Example:
export const subscriptionService = new SubscriptionService();
- Example:
Database Adaptation
- Multi-database Support: Project supports both SQL (PostgreSQL) and SQLite
- Schema Definition: Must maintain both
src/drizzle-postgres-schema.tsandsrc/drizzle-sqlite-schema.ts, ensuring consistent field structures (type definitions may vary slightly) - ORM Usage: Use Drizzle ORM for database operations, prefer type-safe builder syntax, avoid handwritten SQL strings to ensure cross-database compatibility
Coding Standards
TypeScript Standards
- Strict Types: Enable
strict: true. Prohibit usingany, must define explicit interfaces or types - Type Definition Location:
- Component props defined within component files
- Public data models defined in
types.tsor related module type files (e.g.,src/lib/payment/types.ts)
- Non-null Assertions: Avoid using
!non-null assertions, prefer optional chaining?.and nullish coalescing??, or explicit null checks
Component Development Standards (React/Next.js)
- Component Structure:
- Prefer functional components + Hooks
- Server Components vs Client Components: Default to Server Components. Only add
'use client'directive when interaction is needed (onClick, useState, useEffect) - File Naming: Component files use
PascalCase.tsx(e.g.,Button.tsx), page files usepage.tsx
- Props Naming:
- Use
interfaceto define Props, naming followsPascalCase+Propssuffix (e.g.,SubscriptionManagerProps) - Event handler Props start with
on(e.g.,onSave,onClick)
- Use
- Hooks: Custom Hooks should be placed in
src/lib/hooksdirectory, named starting withuse - Internationalization: All UI text must use
i18nextfor internationalization- Server Component: Use
useTranslation(async) fromsrc/i18n - Client Component: Use
useTranslationfromsrc/i18n/client - Text Key naming:
namespace:category.key(e.g.,home:hero.title)
- Server Component: Use
Frontend Development Standards
Styling & UI Standards
This project uses Tailwind CSS 4 + Shadcn/ui as the core UI solution.
Color Semantics (Mandatory)
Fixed color values are strictly prohibited. Must use semantic CSS variables defined in the design system to ensure theme switching works properly.
- Background:
bg-[var(--color-bg-main)],bg-[var(--color-bg-surface)],bg-[var(--color-bg-subtle)] - Text:
text-[var(--color-text-primary)],text-[var(--color-text-secondary)],text-[var(--color-text-tertiary)] - Border:
border-[var(--color-border-subtle)],border-[var(--color-border-strong)] - Brand:
bg-brand-500,text-brand-500 - Functional:
text-[var(--color-text-error)],bg-[var(--color-bg-success)]
Styling Principles
- Atomic First: Prohibit writing traditional CSS/SCSS files. All styles should be implemented through Tailwind utility classes as much as possible
- Responsive Design: Follow Mobile First principle. Write mobile styles by default, use
sm:,md:,lg:prefixes to override for larger screens - Class Name Merging: Use
cnfunction fromsrc/lib/utils.tsfor conditional class names- ✅
className={cn("p-4 rounded", isActive && "bg-brand-500", className)}
- ✅
Common Frontend Utilities
The project encapsulates many practical tools in src/lib/utils.ts and src/lib/hooks. Please use them first to avoid reinventing the wheel.
- Style Merging:
cn(...inputs: ClassValue[])- Merge Tailwind class names, resolve conflicts - Date Formatting:
useDateFormatHook - Handle timezone and localized date displayformatDate(date, formatStr?): Format dateformatTime(date): Format timeformatDateTime(date): Format date and time
- Price Formatting:
formatPrice(amount, currency)- Format price display based on currency - Network Requests:
src/lib/fetch.ts- Encapsulated fetch methods with language parameters and error handlingfetchGet(url, options)fetchPost(url, body, options)
- Auth State:
useAuthContext- Get current user info (user) and loading state (isPending)
New Page Development Checklist
When creating a new page, must include the following elements:
- File Location:
- Route pages go in
src/app/[lang]/.../page.tsx - Pages requiring permission control (e.g., admin) should be in
(auth)oradminroute groups
- Route pages go in
- Internationalization (i18n):
- Page component must receive
params: { lang: string } - Server-side translation:
const { t } = await useTranslation(lang, 'namespace') - Client components receive
langvia props or useuseTranslationhook
- Page component must receive
- Layout & Container:
- Use semantic tags (
main,section,article) - Page content typically wrapped in
Layoutordivcontainer with standard padding
- Use semantic tags (
- Error Boundary:
- Complex pages should add
error.tsxto handle runtime errors - Use
notFound()function when resource not found
- Complex pages should add
- Loading State:
- For async data loading, display
loading.tsxor skeleton (Skeleton)
- For async data loading, display
Example Page Structure:
import { useTranslation } from '@/i18n'
export default async function Page({ params: { lang } }) {
const { t } = await useTranslation(lang, 'home')
return (
<main className="bg-[var(--color-bg-main)] min-h-screen">
<div className="container mx-auto px-4 py-8">
<h1 className="text-[var(--color-text-primary)] text-2xl font-bold">
{t('title')}
</h1>
{/* Page Content */}
</div>
</main>
)
}
Core Business Module Development Guide
Authentication
- Better Auth: All authentication logic based on
src/lib/auth.ts - Hooks:
before: For pre-login checks (e.g., captcha, login lockout, registration restrictions)after: For post-login processing (e.g., logging, sending welcome emails)
- Session: Frontend uses
useAuthContextto get current user info
Payment & Subscription
- Flow: Create Checkout Session -> User Payment -> Webhook Callback -> Update Database State
- Webhook: All state changes must rely on Webhook notification processing results, not frontend callbacks
- Credits Logic:
creditsService.addCredits: Add credits, distinguish betweenFree(gifted) andPaid(purchased)creditsService.consumeCredits: Consume credits, prioritize deductingFree Credits
- Idempotency: Webhook processing logic must be idempotent, receiving the same event multiple times should not cause data errors (e.g., duplicate credit distribution)
Admin Dashboard
- API Permission Control: Admin API endpoints must strictly check administrator permissions. Use
checkPermissionWithResponse(request, Permission)in API Routes; verify session and permissions in Server Actions - Page Access Control: All admin dashboard page components must perform permission validation. Use
PermissionGuardcomponent to wrap restricted content, ensuring unauthorized users cannot see specific features or pages - Logging: All sensitive operations (create, update, delete) must be logged. Call
adminOperationLogsservice orlogSimpleOperation, recording operator, module, action, and target ID
Performance, Security & Deployment
Performance Optimization
- Image Optimization: Must use
next/imagecomponent with properly configuredsizesattribute for responsive loading - Component Lazy Loading: For non-critical above-the-fold components (e.g., modals, large charts), use
next/dynamicfor lazy loading - Server Components: Default to Server Components to reduce client bundle size
- Font Optimization: Use
next/fontto load fonts, avoiding layout shift (CLS)
Security Standards
- Input Validation: All API endpoints must use Zod for parameter validation to ensure input data legality and security
- Authentication: Client API endpoints handling user privacy or personalized data must first call
verifyUserInApiRoute(request)to verify user Session status - CSRF Protection: All POST/PUT/DELETE requests must be automatically handled through Next.js Server Actions or API Routes
- Sensitive Data: Prohibit exposing API Keys, Secrets, or database connection strings in client code. Environment variables must distinguish
NEXT_PUBLIC_prefix - Authorization: Any interface involving data modification must re-verify on the server side whether the current user has permission to perform the specific operation
Deployment Process
- Vercel Deployment: Recommend using Vercel for deployment, leveraging its Edge Network and Serverless Functions
- Environment Variables: Before production deployment, ensure all necessary environment variables are configured in Vercel Dashboard
- Database Migration: Deployment process should include
drizzle-kit migratestep to ensure database structure is up to date
Commit & Collaboration Standards
Git Commit Messages
Follow Conventional Commits specification:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code formatting (no logic changes)refactor: Code refactoring (no new features or bug fixes)chore: Build process or auxiliary tool changes
Example: feat(auth): add google login support
Branch Management
main: Main branch, keep stable, deployable at any timedevelop: Development branch, daily development merges herefeature/*: Feature branches, checkout fromdevelop, PR back todevelopwhen completefix/*: Fix branches
Code Review
- Self-test before submitting PR and ensure lint checks pass
- PR description should clearly explain changes, purpose, and testing methods
- Core logic changes (especially payment, permissions) must undergo strict review
Common Commands Reference
| Command | Description |
|---|---|
pnpm dev | Start development server |
pnpm build | Build project |
pnpm drizzle-kit generate | Generate database migration |
pnpm drizzle-kit push | Push database migration |
pnpm prettier --write . | Format code |