Branding
One place that knows what the product is called.
@kreogen/branding is a single frozen object. It exists because "Acme Inc" was
hardcoded in the dashboard title, the unauthenticated layout, the marketing
header and the marketing footer — and the legal entity appeared nowhere at all,
so renaming a client project meant grepping for a string and hoping.
import { branding } from '@kreogen/branding';
<title>{branding.name}</title>What it holds
| Field | Used for |
|---|---|
name | Navigation, page titles, email signatures |
legalName | The legal entity, for terms, privacy and copyright lines |
description | Default meta description and og:description |
supportEmail | Where support mail goes; the address legal pages point at |
url | Canonical marketing origin |
social | x, github, linkedin |
name and legalName are separate on purpose. "Acme" belongs in a nav bar;
"Acme, Inc." belongs in a copyright line and a terms of service, and a project
that conflates them ends up with a legal document naming a brand rather than a
company.
Why it is not environment variables
These are build-time constants that differ per project, not per deployment. A missing environment variable would render an empty page title in production; a missing field here fails a typecheck.
url is the exception that proves the rule. It is the canonical marketing
origin, which is fixed for the project — the app, API and docs origins differ
per environment and live in NEXT_PUBLIC_*_URL instead, because one Docker
image has to serve staging and production.
Rebranding a project
Edit packages/branding/index.ts, then the
brand ramp in
globals.css. Between them that is the name and the colours; the rest of the
repository reads from both.
Anything user-visible and product-specific belongs here. If you find yourself writing the product's name into a component, that is the signal to add a field instead.