Site

1. Branding

The init wizard wrote application configuration into config/app.ts and environment values into .env.local. Review both, replacing placeholder branding, URLs and legal details. Init does not recolor the design tokens or replace image assets.

  • Logo — replace public/logo.svg, public/logo-dark.svg, public/icon.svg and public/favicon.svg; review the matching paths and dimensions in appConfig.logo.
  • OG image — provide a 1200×630 image and update appConfig.seo.openGraph.images. The default points to /og-image.png; supply that asset under public/ or configure your own existing URL.
  • Brand color — follow DESIGN.md and the oklch() tokens in app/globals.css. The current raspberry palette derives from --brand-h: 350; review hue, chroma and contrast in both themes rather than replacing isolated component colors. Tailwind and shadcn consume the tokens through @theme inline.

2. Business model: B2C or B2B?

Edit config/app.ts:

ts
export const appConfig = {
  // ...
  businessModel: 'b2c', // or 'b2b'
}
B2CB2B
Account model1 user = 1 personal accountN users = 1 workspace
OnboardingSingle signupSignup + workspace setup + invitations
PricingPer userPer workspace (with seats)
SidebarPersonal dashboard onlyPersonal + org dashboards

Changing the business-model flag does not migrate existing Accounts or subscriptions. Choose the intended model before admitting users and review any later transition separately.

3. Billing model

Also in config/app.ts:

ts
billingModel: 'subscription' // or 'one_time' or 'hybrid'
  • subscription — recurring payments through the provider selected during initialization. Default for SaaS.
  • one_time — license purchases; access duration comes from the configured license product and is not necessarily lifetime.
  • hybrid — both. Useful if you sell both a subscription tier and one-off add-ons.

The pricing page automatically shows only the purchase types your model enables.

4. Finalize your prices

Open config/pricing.ts and shape your plans / credit packs / licenses. Each plan has:

  • an id (kept as-is forever — it is what subscriptions.plan_id stores)
  • a name
  • an amount in whole currency units (e.g. 29 for €29)
  • provider catalogue bindings for every sold currency, billing interval, and dev/prod environment
Test IDs vs live IDs

The same config/pricing.ts file is used in dev and prod. Its providerCatalogIds map is keyed by internal offer, optional interval, and currency, then by Stripe/Lemon Squeezy/Paddle and { dev, prod }. Fill only the providers and commercial combinations you actually sell: Stripe and Paddle use Price IDs, while Lemon Squeezy uses Variant IDs. NEXT_PUBLIC_INSTANCE_MODE selects the environment slot; PAYMENTS_PROVIDER selects the provider server-side.

5. Languages (i18n)

The boilerplate ships with French (fr-FR), Swiss French (fr-CH), US English (en-US), and Canadian English (en-CA), URL-based: /fr-FR/..., /fr-CH/..., /en-US/..., and /en-CA/.... To remove one or add one:

  1. Edit i18n/config.ts: update the locales array, localeNames, localeFlags.
  2. Copy i18n/messages/en-US.json to your new locale (e.g. es-ES.json) and translate the values.
  3. Restart the dev server.

Full reference: Internationalization.

6. Email provider

If you picked noop earlier, switch to Brevo or Mailjet now:

  1. Open the provider dashboard → API keys → copy your key.
  2. Paste it in .env.local as BREVO_API_KEY or MAILJET_API_KEY_PUBLIC + MAILJET_API_KEY_PRIVATE.
  3. Set EMAIL_FROM_NAME and EMAIL_FROM_ADDRESS.
  4. Verify your sender domain inside the provider (SPF + DKIM). Magic links land in spam without this.
  5. Test by requesting a magic link from /en-US/login with a real email address.

7. Replace the placeholder content

  • Hero, features, testimonials, FAQ — landing components live in components/landing-*.tsx. Most read content from i18n message files, so edit i18n/messages/{locale}.json.
  • Logo cloud — drop SVGs in public/logos/ and reference them in components/logo-cloud.tsx.
  • Legal pages — /terms, /privacy, /legal are CMS pages. Edit them in /admin-dashboard/cms once logged in as admin.
You can move on when…
  • The landing page shows your real branding, real prices, no placeholders
  • Your locales array matches what you actually want to sell in
  • A magic link sent to a real inbox arrives within ~30 seconds, not in spam
  • Legal pages render with your company info, not Lorem Ipsum