Start here

Customize Your Product

Set the starter's identity, languages, visual preset, theme, legal details, and optional systems before you build product-specific features.

By the end of this page, the starter will look and route like your product, and you will have an explicit keep, configure, or remove decision for every optional system. Do this before changing individual screens: identity and product boundaries affect URLs, emails, legal copy, analytics, billing, and the admin console.

What ships and what you decide

AreaShipped behaviorYour decision
Product identitysaas.config.json tracks the neutral name, slug, support, and docs URLRun the customizer and review the tracked diff
SupportSupport email is an explicit tracked product valueSet a real support email before production; the configuration gate requires it
LanguagesEnglish, Chinese, Spanish, French, and Japanese are available; URL prefixes are as-neededChoose the default, enabled set, and browser-locale detection
Visual languagestudio is the build-time preset shared by the web and admin appsKeep it or choose glass, soft, editorial, or brutalist in code
Color modeThe customer app defaults to system through an environment variableChoose system, light, or dark; the admin app does not yet have a theme-mode switch
Legal pagesA visible draft skeleton describes the starter's default data flowsFill every identity and policy decision, then obtain legal review
Optional systemsBilling, storage, email, Slack, analytics, referrals, tasks, and reservations have code or adaptersKeep and configure each one, or remove its UI, validation, routes, and documentation together

Use a real product name, keep system color mode and the studio preset until the product's information architecture settles, and enable only languages your team can maintain. Keep analytics, advertising, referrals, and demo features off until you have a reason, user-facing copy, and an operating process for them.

The alternatives are valid, but they create work. More locales widen your audience and your translation obligation. A stronger visual preset creates differentiation but needs a complete light/dark and admin review. Enabling an integration is faster than building one, but it also adds credentials, failure modes, privacy disclosures, and support work.

Set identity and locale behavior

Run the tracked customizer before editing individual screens:

pnpm customize

pnpm customize -- \
  --name "Acme Cloud" \
  --slug acme-cloud \
  --preset glass \
  --locales en,fr \
  --default-locale en \
  --support-email support@example.com \
  --docs-url https://docs.example.com \
  --yes

The command validates and atomically writes saas.config.json, then synchronizes matching public values into existing ignored environment profiles without touching secrets. --dry-run prints the candidate; --no-env leaves profiles unchanged. Deployment variables may override public values, but the production config gate rejects an override that contradicts the tracked product identity.

Choose one visual preset

Choose the preset through pnpm customize or edit the tracked value:

{ "appearance": { "preset": "glass" } }

src/config/style.ts derives its typed value from this file. The same preset is rendered by web and admin; it is a build-time product choice, not a per-user picker.

Set the legal identity in the legal section of saas.config.json: registered entity and address, privacy/legal contacts, governing law, and effective date. src/config/legal.ts reads those values; edit that file only for product-specific policy text and LegalData.subProcessors. Until the required identity fields exist, LegalConfig.isConfigured remains false and the legal pages show a draft notice. Review both the identity and policy before launch.

The included text is a drafting skeleton, not legal advice or a finished policy. Remove providers you do not use, add providers that receive personal data, reconcile retention promises with account erasure, and have qualified counsel review the result.

Decide the product boundary

For every optional system, record one of three decisions:

  1. Keep: configure credentials, user copy, monitoring, failure handling, and an owner.
  2. Adapt: change the policy or provider behind the existing service boundary, then update tests and public guidance.
  3. Remove: remove routes, UI, production validation, jobs, and documentation in the same change. An empty credential is not a product decision.

Continue with Plans and Entitlements, Stripe Billing, Storage Uploads, Analytics and Consent, and Deployment and Security for systems you keep.

Verify before feature work

pnpm config:check
pnpm config:check:prod
pnpm lint
pnpm test:run
pnpm build:web
pnpm build:admin

Then verify the default locale is unprefixed, each enabled non-default locale resolves, the language selector cannot choose a disabled locale, the docs and support links go where promised, both apps use the selected preset, and the customer app behaves in light and dark mode. Open privacy and terms: a public launch is not ready while the draft warning or policy placeholders remain.

What is not finished for you

pnpm customize supplies the tracked brand/configuration workflow. Runtime preset selection, an admin dark-mode provider, environment-driven support email, a reviewed legal policy, and the choice of optional product systems remain adopter work. Support email comes from product.supportEmail in saas.config.json.

Source snapshot

Verified against starter commit e632762: