# App Branding

> How to rename or rebrand the app so every surface — title, package metadata, PWA manifest, and icons — stays consistent. Use when a prompt establishes or implies a new app name, title, or visual identity, OR when you generate an app title, theme, or icon yourself while scaffolding an app from an initial prompt.

- Skill: `builderio/app-branding` (Agent Skill)
- Install (CLI): `npx skillmds@latest add builderio/app-branding`
- Raw SKILL.md: https://api.skillmd.com/api/skills/builderio/app-branding/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Builder.io (https://skillmd.com/u/builderio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/builderio/app-branding

---


# App Branding

## Trigger

Read this skill whenever the app's name, title, or visual identity is being
established or changed — whether the user states it or **you derive it yourself**.

- **Explicit** — the prompt names the app: "rename this app to …", "this is a
  Todo app called …", "call this app …".
- **Implicit / agent-generated** — the prompt describes what to build but leaves
  the branding to you: "build me a habit tracker", "turn this into a recipe
  manager", "make a CRM for my studio". The moment you decide on a title, theme
  color, or icon from that prompt, treat it as a branding change and apply the
  full checklist so your generated identity lands on every surface — not just
  the one screen you happen to be building.

If you are inventing an app title, theme, or icon as part of scaffolding a new
app from an initial prompt, that counts — run the checklist in the same pass.

## Rule

Apply **all** of the updates below in a single consistent pass. Depending on the
template, the app name may live in one source-of-truth module or be spread
across several files — either way, a partial rename leaves the app half-branded
(a stale tab title, launcher label, or icon).

Derive three values once, then reuse them everywhere:

- **Title** — human-readable display name, e.g. `"My Task App"`.
- **Slug** — URL/npm-safe form: lowercase letters, digits, and hyphens only,
  e.g. `"my-task-app"`.
- **Description** — one sentence describing what the app does.

## Locate the layout first

Branding lives in different places depending on the template. Detect which
layout you are in before editing:

- **Centralized layout** — `app/lib/app-config.ts` exists. It is the single
  source of truth for the name and title; the frontend surfaces (`<title>`,
  route `meta()`, header, sidebar, index heading, `apple-mobile-web-app-title`)
  derive from its `APP_NAME` / `APP_TITLE` exports, so you change the name in one
  place.
- **Inlined layout** — no `app/lib/app-config.ts`. The name and title are
  written directly into `package.json`, each route's `meta()`, and
  `app/root.tsx`. You must update each surface individually.

When in doubt, `grep -rn` the current title and slug across `app/`, `server/`,
`package.json`, and `public/` and fix every real hit — the two layouts share the
manifest and icon steps regardless.

## The Checklist

### Step 1 — App name + title source

**Centralized layout** (`app/lib/app-config.ts`): change both constants and stop —
the rest of the frontend derives from them.

- `rawAppName` → the **slug**.
- `rawAppTitle` → the **title**.

**Inlined layout** (no `app-config.ts`): set the title/slug at each surface.

- Every route `meta()` title under `app/routes/*.tsx` (e.g. `_index.tsx`,
  `agent.tsx`, `settings.tsx`) — replace the app title. These are seeded from a
  `{{APP_TITLE}}` placeholder at scaffold time and become plain literals
  afterward.
- Any `useActionQuery("hello", { name: … })` in `app/routes/_index.tsx` seeded
  with the title.
- `app/root.tsx` `apple-mobile-web-app-title` — a literal (often `"App"`); set it
  to the **title**.

### Step 2 — `package.json` (both layouts)

- `displayName` → the **title** (add the field if the template omits it).
- `description` → the **description** (add if absent).
- `name` → the **slug**. Only change this if the user explicitly asks to rename
  the package (it is the npm package identifier).

### Step 3 — Login / auth title (centralized layout only)

If `server/plugins/auth.ts` exists it keeps its **own** duplicate `rawAppTitle`,
used on the login/signup pages. Set it to the same **title** as
`app/lib/app-config.ts`. (The inlined layout's `server/middleware/auth.ts`
carries no app title — skip this step there.)

### Step 4 — `public/manifest.json` (both layouts)

This is a static file (not generated by a plugin). Update:

- `name` → the **title** (full install name in OS app drawers).
- `short_name` → a compact launcher label; keep it ≤12 characters, abbreviating
  the title if needed.
- `description` → the same **description** used in `package.json`.

### Step 5 — Icon SVG files (both layouts)

Replace the icon files with a new mark that reflects the app's identity. The set
present depends on the template; update each one you find:

| File | Purpose |
| --- | --- |
| `public/favicon.svg` | Browser tab favicon |
| `public/icon-180.svg` | Apple touch icon (iOS home screen) |
| `public/icon-192.svg` | PWA install icon (Android / Chrome) |
| `public/icon-512.svg` | PWA install icon (large / splash) |

Build the icon from **SVG primitives** — do not embed a base64-encoded PNG. All
files should share the same visual design; only the `width` and `height`
attributes differ. A simple, reliable approach: a filled rounded square in the
brand color with the first letter (or a relevant glyph) centered in white.

Template to adapt (change `fill`, the letter/glyph, and `rx` to suit the brand):

```svg
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 192 192">
  <rect width="192" height="192" rx="40" fill="#2563EB"/>
  <text x="96" y="130" font-family="system-ui, sans-serif" font-size="110"
        font-weight="700" fill="white" text-anchor="middle">A</text>
</svg>
```

Keep `width`/`height` at `180`, `192`, and `512` for the respective icon files;
`favicon.svg` can use any of these sizes (the `viewBox` keeps it scalable).

## What NOT to change

These are stable identifiers or template-internal files, not user-facing brand:

- `configureTracking({ app, template })` in `app/root.tsx` — analytics
  identifiers seeded at scaffold time; leave them. This holds even in the inlined
  layout, where `app` was seeded from the slug — changing it re-keys analytics
  history.
- `server/plugins/agent-chat.ts` `appId` (centralized layout) — a stable
  platform analytics/routing key; leave it exactly as scaffolded.
- `.github/workflows/*.yml` — template automation; references the repo/template
  identity, not the running app.
- `AGENTS.md` / `DEVELOPING.md` — developer docs for the template itself.

## Verification

- `pnpm typecheck` passes.
- Grep for the old title/slug across `app/`, `server/`, `package.json`, and
  `public/` — no unintended leftovers remain (except the intentional
  "do not change" identifiers above).
- The browser tab title, sidebar/header, and index heading all show the new
  title.

