Secondary Development Guide
This document guides developers on how to perform secondary development based on the Hex2077 Starter Template, covering the entire process from adding business logic to customizing UI.
Pre-Development Preparation
Before starting development, please ensure you have read the following basic documents:
- Getting Started - Quick start and architecture overview
- Engineering Guide - Engineering coding standards and layered architecture
- Database Initialization - Database initialization and permission role configuration
Database Extension
This project uses Drizzle ORM, supporting PostgreSQL and SQLite.
Adding New Tables
-
Define Schema:
- For SQLite, modify
src/drizzle-sqlite-schema.ts - For PostgreSQL, modify
src/drizzle-postgres-schema.ts - Note: Keep field structures consistent in both files for database switching
- For SQLite, modify
-
Generate and Push Changes:
pnpm drizzle-kit generate
pnpm drizzle-kit push
- Update Type Declarations: If referencing new tables in code, ensure exports in
src/drizzle-schema.ts
Business Logic Development (Service Layer)
The project uses Service layer to encapsulate business logic. All core logic should be placed in src/lib/services directory.
Creating New Services
-
File Location:
- End user logic:
src/lib/services/client/ - Admin dashboard logic:
src/lib/services/admin/
- End user logic:
-
Writing Pattern:
// src/lib/services/client/my-service.ts
export class MyService {
async doSomething(userId: string, data: any) {
// 1. Business logic processing
// 2. Database operations (db.insert, db.select...)
// 3. Return results
}
}
export const myService = new MyService();
API Routes & Permissions
Adding New API Routes
Create corresponding route files under src/app/api.
Authentication & Permission Validation
User Verification:
import { verifyUserInApiRoute } from '@/lib/server/admin-api-utils';
const session = await verifyUserInApiRoute(req);
Admin Permission Verification:
import { checkPermissionWithResponse } from '@/lib/server/admin-api-utils';
import { Permission } from '@/lib/constants/permissions';
await checkPermissionWithResponse(req, Permission.USER_VIEW);
Frontend UI Development
Component Development
- Base Components: Use Shadcn UI components under
src/components/ui/ - Business Components: Place in
src/components/ - Styling: Must use Tailwind CSS 4. Prohibit fixed colors, use semantic variables (e.g.,
text-[var(--color-text-primary)])
Internationalization (i18next)
-
Add Translations: Modify JSON files under
public/locales/{lang}/ -
Code Usage:
- Server Component:
const { t } = await useTranslation(lang, 'common') - Client Component:
const { t } = useTranslation('common')
- Server Component:
Payment Gateway Integration
If you need to add new payment methods or modify existing logic:
- Gateway Interface: Reference
PaymentGatewayinterface insrc/lib/payment/types.ts - Add Implementation: Create new gateway class under
src/lib/payment/gateways/ - Register Gateway: Add logic in
src/lib/payment/gateway-factory.ts - Webhook Handling: Add corresponding normalizer in
src/lib/payment/webhook-handlers/
Admin Dashboard Extension
- Add New Pages: Create subdirectories under
src/app/[lang]/admin/ - Menu Configuration: Add navigation items in admin sidebar component
- Breadcrumb Navigation: Breadcrumbs show current page path, helping users navigate quickly
- Logging: Important operations must be logged
import { adminOperationLogs } from '@/lib/services/admin/admin-service';
await adminOperationLogs.log({ action: 'UPDATE', module: 'USER', ... });
import { logSimpleOperation } from '@/lib/services/admin/admin-service';
await logSimpleOperation({ action: 'UPDATE', module: 'USER', ... });
Common Utility Functions
| Function | Description |
|---|---|
cn(...) | Class name merging |
useDateFormat() | Date localization |
formatPrice(amount, currency) | Price formatting |
fetchPost(url, body) | Encapsulated network request |
Modifying Fixed Page Content
This section describes how to modify fixed content on pages, including language/currency, company info, SEO configuration, and social media links.
Language and Currency Configuration
For detailed language and currency configuration, see i18n & Currency Configuration.
Main files involved:
src/i18n/settings.ts: Language configurationsrc/lib/utils.ts: Currency-language mapping, price formattingpublic/locales/: Multilingual translation file directory- Admin settings page:
src/app/[lang]/admin/system/settings/page.tsx
Company Information Configuration
Company information is used for privacy policy, terms of service, and other page displays.
Configuration Methods
Method 1: Environment Variables (Recommended for initialization)
Set in .env file:
NEXT_PUBLIC_COMPANY_NAME="Your Company Name"
NEXT_PUBLIC_COMPANY="Your Company"
NEXT_PUBLIC_PRIVACY_EMAIL="privacy@yourcompany.com"
NEXT_PUBLIC_SUPPORT_EMAIL="support@yourcompany.com"
NEXT_PUBLIC_WEBSITE="https://yourcompany.com"
NEXT_PUBLIC_ADDRESS="Your Company Address"
NEXT_PUBLIC_PHONE="+1 (555) 123-4567"
NEXT_PUBLIC_DPO_EMAIL="dpo@yourcompany.com"
NEXT_PUBLIC_DPO_ADDRESS="DPO Address"
Method 2: Admin Dashboard Configuration (Recommended for runtime changes)
Modify through admin system settings page. Settings are stored in admin_settings table with key format company.xxx.
Usage in Code
import { getCompanySettings } from '@/lib/services/settings/company-settings-service'
const companySettings = await getCompanySettings()
console.log(companySettings.name) // Company name
console.log(companySettings.support_email) // Support email
console.log(companySettings.website) // Company website
SEO Configuration
SEO settings support multilingual configuration for website metadata, Open Graph, and Twitter Card.
Configuration Methods
Method 1: Environment Variables (Recommended for initialization)
Set in .env file:
NEXT_PUBLIC_SITE_NAME="Your Site Name"
NEXT_PUBLIC_SITE_DESCRIPTION="Your site description"
NEXT_PUBLIC_SITE_KEYWORDS="keyword1,keyword2,keyword3"
NEXT_PUBLIC_SITE_URL="https://yoursite.com"
NEXT_PUBLIC_OG_IMAGE="/og-image.png"
NEXT_PUBLIC_TWITTER_HANDLE="@yourhandle"
NEXT_PUBLIC_TWITTER_CARD="summary_large_image"
Method 2: Admin Dashboard Configuration (Recommended for runtime changes)
Modify through admin system settings page, supporting separate SEO configuration for each language.
Usage in Code
import { getSEOSettings, getSEOSettingsForLang } from '@/lib/services/settings/seo-settings-service'
// Get all SEO settings
const seoSettings = await getSEOSettings()
console.log(seoSettings.siteUrl) // Website URL
console.log(seoSettings.localized['zh-CN']) // Chinese SEO settings
// Get SEO settings for specific language
const zhSEO = await getSEOSettingsForLang('zh-CN')
console.log(zhSEO.siteName) // Chinese site name
console.log(zhSEO.siteDescription) // Chinese site description
Footer Social Media Configuration
Footer social media links are configured in src/components/Footer.tsx.
Modifying Social Media Links
Find the socialPlatforms configuration object and modify the href attribute for each platform:
// src/components/Footer.tsx
const socialPlatforms = {
// International platforms
international: [
{ name: 'X', icon: XLogoIcon, href: 'https://x.com/yourhandle', type: 'phosphor' },
{ name: 'GitHub', icon: GithubLogoIcon, href: 'https://github.com/yourorg', type: 'phosphor' },
{ name: 'Discord', icon: DiscordLogoIcon, href: 'https://discord.gg/yourinvite', type: 'phosphor' },
// ... other platforms
],
// China platforms
china: [
{ name: 'WeChat', icon: WechatLogoIcon, href: '#', type: 'phosphor' },
{ name: 'Bilibili', icon: SiBilibili, href: 'https://space.bilibili.com/yourid', type: 'si' },
// ... other platforms
],
}
Adding/Removing Social Platforms
- Add New Platform: Add new object to corresponding array
- Remove Platform: Remove corresponding object from array
- Icon Types:
phosphor: Use@phosphor-icons/reacticonssi: Usereact-icons/siiconstext: Plain text display (no icon)
Modifying Copyright Information
Modify copyright text at the bottom of Footer component:
<p className="text-sm text-[var(--color-text-muted)]">
© 2025 Your Company. All rights reserved.
</p>