NimBuild Docs

Customization

How to customize pricing, AI settings, theme, locales, and app pages.

Modify Products and Pricing

Edit constants/billing.ts.

The starter currently ships with a lifetime one-time pack enabled in oneTimePacks. Subscription plan keys are already typed, but subscriptionPlans is empty until you add real plans and Creem product IDs.

export const oneTimePacks = {
  lifetime: {
    key: "lifetime",
    kind: "one_time",
    priceCents: 9900,
    originalPriceCents: 15900,
    currency: "usd",
    credits: 0,
    planKeyToGrant: "lifetime",
    creemPriceId: "prod_xxx",
  },
};

When enabling subscriptions, add entries to subscriptionPlans and keep the key aligned with the PlanKey union in the same file. Annual plans can use grantSchedule for installment credit grants.

Modify Credit Costs

Generation costs are centralized in modules/ai/costs.ts:

FeatureConstantCurrent cost
ChatCHAT_CREDIT_COST10
Image generationIMAGE_GENERATION_CREDIT_COST20
Video generationVIDEO_GENERATION_CREDIT_COST50

The server workflows in features/demo/server/* import these constants, deduct credits through modules/credits, and use refund compensation when provider work fails.

Replace AI Provider

The current provider adapter lives in extensions/ai/volcano-engine/.

To switch from Volcano Engine to OpenAI, Anthropic, or another provider:

  1. Add a new adapter under extensions/ai/your-provider/
  2. Match the small surface used by features/demo/server/chat.ts, features/demo/server/image-generation.ts, features/demo/server/video-generation.ts, and features/demo/server/video-status.ts
  3. Update the imports in those server workflows
  4. Update environment variables in .env.example and deployment settings
  5. Preserve the createCreditCompensation(...) refund pattern after credit deduction

Add a New Language

  1. Copy messages/en.json to messages/XX.json
  2. Copy messages/seo.en.json to messages/seo.XX.json
  3. Translate both files
  4. Add the locale to i18n.config.ts
export const locales = ['en', 'zh', 'XX'] as const;
  1. Add matching docs MDX files in content/docs, such as quickstart.XX.mdx
  2. Update docs locale labels in features/docs/localization.ts and Fumadocs i18n if the docs site should expose the new locale

proxy.ts and lib/i18n.ts read from i18n.config.ts, so most locale routing follows that shared config.

Customize Theme

Colors are defined in app/globals.css using CSS custom properties:

:root {
  --background: 0 0% 100%;
  --foreground: 0 0% 3.9%;
  --primary: 0 0% 9%;
  /* ... */
}

Dark mode variables are in the .dark class.

Fumadocs CSS is handled separately. scripts/sync-fumadocs-style.mjs syncs the generated stylesheet to public/fumadocs-style.css, and features/docs/styles.tsx loads it only for docs routes.

Add New Protected Pages

  1. Create a page under app/[locale]/(protected)/your-page/page.tsx
  2. Compose the page from features/user-console/pages or create a new feature-owned page component
  3. Put server queries or mutations in the matching features/*/server module
  4. Add navigation keys in features/navigation/config.ts
  5. Add user-facing labels in both messages/en.json and messages/zh.json

The protected layout calls getActiveSessionUser() from modules/auth, so pages in this route group require an authenticated user.

On this page