Docs

10 — Brand kit (`@framework/brand`)

Princípio

Um lugar para rebrandar: nome, domínios, cores, tipografia, logos, favicons, tokens de tema, SEO default e shell de email vivem em packages/brand. Apps consomem — não duplicam.

packages/brand (editar no fork)
    ├── config.ts / brand-data.json   → identidade + domínios + SEO
    ├── assets/                       → logos, favicons, og-image
    ├── theme.css                     → tokens shadcn (HSL)
    └── helpers (metadata, email, tailwind preset)
           ↓
    @framework/ui  →  apps/app, apps/backoffice
    imports diretos → apps/website, apps/service

O que o pacote exporta

ImportQuando usar
@framework/brandReact: BrandLogo, APP_NAME, getBrandMetadata, getThemeStorageKey, getLogoUrl
@framework/brand/configbrandConfig tipado (Next.js metadata, URLs derivadas)
@framework/brand/nodeService (CJS): APP_NAME, wrapEmailContent, resolveEmailBrand — ou apps/service/src/lib/brand.ts
@framework/brand/theme.cssTokens CSS — não copiar para apps; já importado por @framework/ui
@framework/brand/tailwind-presetpresets: [brandPreset] nos tailwind.config.js
brandPublicPlugin({ surface })Vite (app/backoffice): sync de assets + injeção de metadata no index.html

Design guide (dev)

pnpm dev:brand    # http://localhost:6007 — catálogo visual
pnpm build:brand  # dist-guide/

Obrigatoriedade — quando deve usar @framework/brand

Use o pacote (nunca hardcode) nestes casos:

SituaçãoObrigatórioComo
Rebrand / fork (Fase 0)SimEditar packages/brand + pnpm rebrand:sync
Nome do produto na UISimAPP_NAME, brandConfig.name ou i18n alimentado pelo rebrand
Logo na interfaceSimBrandLogo ou getLogoUrl() / paths em brandPublicPaths
Favicon / OG imageSimassets/icons/ + sync (brandPublicPlugin ou sync-public.mjs)
Domínios em códigoSimbrandConfig.domains, getAppUrl(), getWebsiteUrl(), etc.
Cores da identidadeSimTokens em theme.css / classes Tailwind (bg-primary, bg-accent) — não hex #071952 em componentes
Metadata (title, description, OG)SimgetBrandMetadata(surface) ou plugin no index.html
Tema claro/escuro (storage key)SimgetThemeStorageKey('app' | 'backoffice')
Tipografia da marcaSimtypography em config + getGoogleFontsCssUrl() / getNextFontOptions()
Emails transacionais (service)SimShell wrapEmailContent + variáveis {{primaryColor}}, {{appName}}
Fallback de APP_NAME / URL no serviceSimAPP_NAME, getAppUrl() via src/lib/brand.ts — não 'Framework' ou domínio fixo
Tailwind — cores semânticasSimPreset @framework/brand/tailwind-preset

Gate de revisão (PR/commit mental)

Antes de mergear código que toca identidade, pergunte:

  1. Existe string com nome do produto, domínio *.forestbit.io ou hex da paleta fora de packages/brand?
  2. Existe logo/favicon copiado manualmente para public/ sem passar por assets/?
  3. O CSS de tema foi duplicado em apps/*/src/index.css em vez de importar @framework/ui/styles.css?

Se sim em qualquer item → corrigir para usar @framework/brand.


Quando não é obrigatório (e o que fica fora)

SituaçãoOnde ficaNota
Componentes shadcn (variants, layout)@framework/uiConsome tokens do brand; não move componentes para brand
Logos de integrações (Stripe, Shopify…)public/ do websiteConteúdo de produto, não marca
Ilustrações de blog / campanhasapps/website/content/Marketing por página
IDs de analyticsenv — website: NEXT_PUBLIC_GTM_ID; app: VITE_GA4_ID, VITE_HOTJAR_IDDomínios do cross-domain linker vêm de brandConfig.domains · ver 06-tracking-attribution.md
Copy longo de marketing / legaldocs/, locales do websiteAtualizar no rebrand (spec 001); não precisa import TS em runtime
Help docs in-appapps/app/public/docs/Conteúdo de produto
Placeholders de StorybookstoriesFixtures de demo

Uso por app

apps/app e apps/backoffice (Vite + React)

import { APP_NAME, BrandLogo, getThemeStorageKey } from '@framework/brand'
IntegraçãoDetalhe
CSSsrc/index.css → @import '@framework/ui/styles.css' apenas
VitebrandPublicPlugin({ surface: 'app' | 'backoffice' })
Tema<ThemeProvider storageKey={getThemeStorageKey('app')}>
ConstantesRe-export em src/shared/lib/constants.ts é aceitável

Assets em public/brand/ e public/favicon.* são gerados no dev/build — não editar à mão.

apps/website (Next.js)

import { getBrandMetadata, getNextFontOptions } from '@framework/brand'
import { brandConfig } from '@framework/brand/config'
IntegraçãoDetalhe
LayoutgetBrandMetadata('website') em metadata / openGraph
CSS@import '@framework/brand/theme.css' em globals.css
URLslib/constants.ts: APP_URL via brandConfig.domains.app
Sign-upbuildSignUpUrl() / SIGN_UP_URL — não URL fixa no JSX
Prebuildsync-public.mjs no predev / prebuild

apps/service (NestJS)

import { APP_NAME, getAppUrl, resolveEmailBrand, wrapEmailContent } from '../../lib/brand'
IntegraçãoDetalhe
Nome / URLssrc/lib/brand.ts lê brand-data.json + node.cjs
EnvAPP_NAME, APP_URL, APP_LOGO_URL no .env — exemplos em .env.example
EmailsTemplates só com conteúdo; shell via wrapEmailContent
SwaggerExemplos de email/domínio devem seguir brand-data.json após rebrand

Após editar config.ts, rodar:

pnpm --filter @framework/brand sync-brand-data

@framework/ui

  • Importa @framework/brand/theme.css em src/index.css
  • Não duplicar tokens :root / .dark no UI ou nos apps

Anti-padrões (proibidos após centralização)

❌ Não fazer✅ Fazer
bg-[#071952] em componentesbg-primary ou var(--brand-primary)
name: 'Framework' como fallback de produtoAPP_NAME ou brandConfig.name
https://app.seudominio.com hardcodedgetAppUrl() ou brandConfig.domains
/images/logos/framework-logo.svg/brand/logos/logo.svg (sync do brand)
Copiar index.css completo do UI no app@import '@framework/ui/styles.css'
Editar favicon só em apps/app/public/Editar packages/brand/assets/icons/
Metadata estática no index.html (prod)brandPublicPlugin ou getBrandMetadata

Fluxo de rebrand (fork)

Ordem recomendada — detalhe em PLAYBOOK Fase 0:

  1. Editar packages/brand/src/config.ts e packages/brand/assets/
  2. pnpm rebrand:sync (env examples + cloud/dokploy)
  3. Copiar .env.example → .env nos apps; preencher secrets
  4. i18n: editar src/locales/ no Cursor
  5. Validar: pnpm dev:brand, pnpm dev, metadata e logos nos 4 apps

Não rebrandar app por app copiando assets ou cores.

Checklist detalhado: specs/001-setup-initial/checklists/requirements.md.


Relação com outras docs

DocumentoRelação
01-architecture-stackDomínios por app — valores vêm do brand
05-deploy-infrastructurecloud/dokploy/* alinhado via pnpm rebrand:sync
06-tracking-attributionGA cross-domain: domínios do brand
marketing/04-brand-communicationTom de voz e comunicação (negócio)
spec 001Checklist de rebrand (referência)

Links relacionados