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

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:

Database Extension

This project uses Drizzle ORM, supporting PostgreSQL and SQLite.

Adding New Tables

  1. 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
  2. Generate and Push Changes:

pnpm drizzle-kit generate
pnpm drizzle-kit push
  1. 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

  1. File Location:

    • End user logic: src/lib/services/client/
    • Admin dashboard logic: src/lib/services/admin/
  2. 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)

  1. Add Translations: Modify JSON files under public/locales/{lang}/

  2. Code Usage:

    • Server Component: const { t } = await useTranslation(lang, 'common')
    • Client Component: const { t } = useTranslation('common')

Payment Gateway Integration

If you need to add new payment methods or modify existing logic:

  1. Gateway Interface: Reference PaymentGateway interface in src/lib/payment/types.ts
  2. Add Implementation: Create new gateway class under src/lib/payment/gateways/
  3. Register Gateway: Add logic in src/lib/payment/gateway-factory.ts
  4. Webhook Handling: Add corresponding normalizer in src/lib/payment/webhook-handlers/

Admin Dashboard Extension

  1. Add New Pages: Create subdirectories under src/app/[lang]/admin/
  2. Menu Configuration: Add navigation items in admin sidebar component
  3. Breadcrumb Navigation: Breadcrumbs show current page path, helping users navigate quickly
  4. 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

FunctionDescription
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 configuration
  • src/lib/utils.ts: Currency-language mapping, price formatting
  • public/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 links are configured in src/components/Footer.tsx.

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

  1. Add New Platform: Add new object to corresponding array
  2. Remove Platform: Remove corresponding object from array
  3. Icon Types:
    • phosphor: Use @phosphor-icons/react icons
    • si: Use react-icons/si icons
    • text: Plain text display (no icon)

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>
Secondary Development Guide - Hex2077 Starter