Everything that changes between one product and another lives in config/. Nothing in
config/ is code: it is data the apps read at build time, so rebranding is an edit, not a
refactor.
The files
| File | Controls |
|---|---|
branding.json |
Product name, primaryColor/secondaryColor (drive the site's CSS theme) and logoText |
product.json |
Positioning copy, feature list and the audience the site speaks to |
pricing.json |
Plans, intervals and what each tier includes |
features.json |
Feature flags that switch whole sections of the apps on or off |
seo.json |
Titles, descriptions and Open Graph defaults |
links.json |
External destinations: social, support, status page |
Apps read the mirrored env vars (.env), not config/*.json directly — run npm run bootstrap after editing branding.json/product.json/etc., or update .env by hand and
run npm run validate-config to confirm they still match. The logo mark itself
(public/brand-*.svg) is a static asset and is not generated from config; replacing it is a
manual step.
Validating a change
npm run validate-config
Each file has a schema, and the validator runs in CI as well as in the pre-commit hook. A value that fails the schema fails the build rather than rendering an empty section.
Secrets do not go here
config/ is committed. Anything secret (database URLs, provider keys, tokens) belongs in
environment variables. npm run validate:frontend-env reports which variables each frontend
expects and which are missing.