Customization
How to customize pricing, product workflows, theme, locales, and app pages.
Modify Products and Pricing
Edit constants/billing.ts.
The starter ships with four subscription plans generated from subscriptionTierConfigs: Basic monthly, Basic yearly, Pro monthly, and Pro yearly. Replace the Stripe Price IDs with IDs from your own Dashboard before accepting payments.
const subscriptionTierConfigs = [
{
key: "basic",
plans: {
monthly: {
creditsPerCycle: 1000,
stripePriceId: "price_your_basic_monthly",
},
yearly: {
creditsPerCycle: 12000,
stripePriceId: "price_your_basic_yearly",
grantSchedule: {
mode: "installments",
grantsPerCycle: 12,
intervalMonths: 1,
creditsPerGrant: 1000,
initialGrants: 1,
},
},
},
},
];Plan keys are derived as ${tierKey}_${billingCycle}. Annual plans use grantSchedule for monthly installment credit grants.
Add Product-Specific Workflows
Add product-specific workflows under features/* and keep server-only provider or billing logic inside features/*/server, modules/*, or extensions/*. If a workflow spends credits before external work completes, preserve the createCreditCompensation(...) refund pattern.
Add Blog Posts
Add blog source files under content/blog/<slug>/.
Each post should provide one MDX file per supported locale, such as en.mdx and zh.mdx, and export a blog metadata object:
export const blog = {
title: "Post title",
description: "Short summary",
author: {
name: "NimBuild",
src: "/logo.png",
},
date: "2026-05-26",
};After adding, renaming, or removing posts, run pnpm generate:blog-manifest so features/blog/blog-manifest.generated.ts matches the source files.
Add a New Language
- Copy
messages/en.jsontomessages/XX.json - Copy
messages/seo.en.jsontomessages/seo.XX.json - Translate both files
- Add the locale to
i18n.config.ts
export const locales = ["en", "zh", "XX"] as const;- Add matching docs MDX files in
content/docs, such asquickstart.XX.mdx - Update docs locale labels in
features/docs/localization.tsand 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 imported directly in app/[locale]/docs/layout.tsx from fumadocs-ui/style.css, which is compatible with the project's Tailwind v4 setup.
Add New Protected Pages
- Create a page under
app/[locale]/(protected)/your-page/page.tsx - Compose route-specific UI directly in that
page.tsx, using feature components as needed - Put server queries or mutations in the matching
features/*/servermodule - Add navigation keys in
components/navigation/config.ts - Add user-facing labels in both
messages/en.jsonandmessages/zh.json
The protected layout calls getActiveSessionUser() from modules/auth, so pages in this route group require an authenticated user.