7 min readLast updated: 2025-12-31 12:12

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.ts dynamically returns StripeGateway or CreemGateway instances based on configuration
  • Service classes typically export singleton instances for direct invocation while maintaining state consistency (if needed)
    • Example: export const subscriptionService = new SubscriptionService();

Database Adaptation

  • Multi-database Support: Project supports both SQL (PostgreSQL) and SQLite
  • Schema Definition: Must maintain both src/drizzle-postgres-schema.ts and src/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 using any, must define explicit interfaces or types
  • Type Definition Location:
    • Component props defined within component files
    • Public data models defined in types.ts or 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 use page.tsx
  • Props Naming:
    • Use interface to define Props, naming follows PascalCase + Props suffix (e.g., SubscriptionManagerProps)
    • Event handler Props start with on (e.g., onSave, onClick)
  • Hooks: Custom Hooks should be placed in src/lib/hooks directory, named starting with use
  • Internationalization: All UI text must use i18next for internationalization
    • Server Component: Use useTranslation (async) from src/i18n
    • Client Component: Use useTranslation from src/i18n/client
    • Text Key naming: namespace:category.key (e.g., home:hero.title)

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 cn function from src/lib/utils.ts for 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: useDateFormat Hook - Handle timezone and localized date display
    • formatDate(date, formatStr?): Format date
    • formatTime(date): Format time
    • formatDateTime(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 handling
    • fetchGet(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:

  1. File Location:
    • Route pages go in src/app/[lang]/.../page.tsx
    • Pages requiring permission control (e.g., admin) should be in (auth) or admin route groups
  2. Internationalization (i18n):
    • Page component must receive params: { lang: string }
    • Server-side translation: const { t } = await useTranslation(lang, 'namespace')
    • Client components receive lang via props or use useTranslation hook
  3. Layout & Container:
    • Use semantic tags (main, section, article)
    • Page content typically wrapped in Layout or div container with standard padding
  4. Error Boundary:
    • Complex pages should add error.tsx to handle runtime errors
    • Use notFound() function when resource not found
  5. Loading State:
    • For async data loading, display loading.tsx or skeleton (Skeleton)

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 useAuthContext to 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 between Free (gifted) and Paid (purchased)
    • creditsService.consumeCredits: Consume credits, prioritize deducting Free 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 PermissionGuard component to wrap restricted content, ensuring unauthorized users cannot see specific features or pages
  • Logging: All sensitive operations (create, update, delete) must be logged. Call adminOperationLogs service or logSimpleOperation, recording operator, module, action, and target ID

Performance, Security & Deployment

Performance Optimization

  • Image Optimization: Must use next/image component with properly configured sizes attribute for responsive loading
  • Component Lazy Loading: For non-critical above-the-fold components (e.g., modals, large charts), use next/dynamic for lazy loading
  • Server Components: Default to Server Components to reduce client bundle size
  • Font Optimization: Use next/font to 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 migrate step to ensure database structure is up to date

Commit & Collaboration Standards

Git Commit Messages

Follow Conventional Commits specification:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: 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 time
  • develop: Development branch, daily development merges here
  • feature/*: Feature branches, checkout from develop, PR back to develop when complete
  • fix/*: 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

CommandDescription
pnpm devStart development server
pnpm buildBuild project
pnpm drizzle-kit generateGenerate database migration
pnpm drizzle-kit pushPush database migration
pnpm prettier --write .Format code
Engineering Guide - Hex2077 Starter