> ## Documentation Index
> Fetch the complete documentation index at: https://www.logo.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Theme generated content with brand colors

> Make generated pages, slides, and emails look on-brand. One request returns a company's logo and color palette, ready to theme whatever you render.

export const BrandThemeDemo = () => {
  const TOKEN = "live_6a1a28fd-6420-4492-aeb0-b297461d9de2";
  const BRANDS = [{
    name: "Spotify",
    domain: "spotify.com",
    accent: "#00d84d"
  }, {
    name: "Netflix",
    domain: "netflix.com",
    accent: "#e50913"
  }, {
    name: "Stripe",
    domain: "stripe.com",
    accent: "#533afd"
  }, {
    name: "Figma",
    domain: "figma.com",
    accent: "#12c6bf"
  }];
  const [selected, setSelected] = useState(0);
  const brand = BRANDS[selected];
  return <div className="not-prose my-8 rounded-2xl border border-zinc-950/10 bg-gradient-to-br from-zinc-50 to-white p-6 shadow-sm sm:p-8 dark:border-white/10 dark:from-zinc-900 dark:to-zinc-950">
      <div className="mx-auto max-w-md space-y-4">
        <div className="flex flex-wrap gap-2">
          {BRANDS.map((b, i) => <button aria-pressed={i === selected} className={`relative rounded-full border px-3.5 py-2 text-xs font-medium transition-[background-color,scale] duration-150 before:absolute before:-inset-1 before:content-[''] focus:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950/20 motion-safe:active:scale-[0.96] dark:focus-visible:ring-white/20 ${i === selected ? "border-zinc-950/20 bg-zinc-100 text-zinc-950 dark:border-white/25 dark:bg-zinc-800 dark:text-white" : "border-zinc-950/10 bg-white text-zinc-600 hover:bg-zinc-50 dark:border-white/15 dark:bg-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800"}`} key={b.domain} onClick={() => setSelected(i)} type="button">
              {b.name}
            </button>)}
        </div>
        <div className="overflow-hidden rounded-xl border border-zinc-950/10 bg-white dark:border-white/10">
          <div className="flex items-center gap-2 border-b border-zinc-950/5 px-4 py-3">
            <img alt={`${brand.name} logo`} className="h-6 w-6 rounded object-contain" height="24" key={brand.domain} src={`https://img.logo.dev/${brand.domain}?token=${TOKEN}&size=24&retina=true&format=webp&theme=light`} width="24" />
            <span className="text-sm font-semibold text-zinc-950">
              {brand.name}
            </span>
            <div className="ml-auto flex gap-2">
              <div className="h-2 w-8 rounded bg-zinc-100" />
              <div className="h-2 w-8 rounded bg-zinc-100" />
            </div>
          </div>
          <div className="space-y-3 px-4 py-6">
            <div className="h-3 w-3/4 rounded bg-zinc-200" />
            <div className="h-3 w-1/2 rounded bg-zinc-100" />
            <div className="flex items-center gap-2 pt-2">
              <span className="inline-flex rounded-lg px-3.5 py-2 text-xs font-semibold text-white" style={{
    backgroundColor: brand.accent
  }}>
                Get started
              </span>
              <span className="text-xs font-medium" style={{
    color: brand.accent
  }}>
                Learn more
              </span>
            </div>
          </div>
          <div className="h-1.5 w-full" style={{
    backgroundColor: brand.accent
  }} />
        </div>
      </div>
    </div>;
};

AI builders, slide tools, and email generators all hit the same wall: the output looks like a template until it carries the customer's brand. The fix is the customer's real logo and accent color, applied automatically.

A user types a domain, and the generated page comes back wearing their logo and their colors. The [Brand API](/docs/brand/introduction) returns both in one request, so theming costs your pipeline a single fetch.

## Demo

Pick a brand and watch the page mockup re-theme:

<BrandThemeDemo />

The accent colors above are real `GET /brand/:domain` responses, fetched once and inlined because the Brand API takes a secret key.

## Build it with AI

<Prompt description="Want on-brand output in your app? This prompt gives your AI coding tool everything it needs to build it in your framework." actions={["copy", "cursor"]}>
  Theme generated content (a page, slide, or email) with a company's real brand using Logo.dev.

  * Fetch the brand server-side from the Logo.dev Brand API: GET [https://api.logo.dev/brand/:domain](https://api.logo.dev/brand/:domain) with header Authorization: Bearer LOGO\_DEV\_SECRET\_KEY. The response includes the company name, a ready-to-render logo URL, and an ordered palette of hex colors.
  * Pick an accent color by skipping near-neutral palette entries (black and white often lead the list). Fall back to a sensible default when every color is neutral.
  * Render the output with the logo in the header and the accent on primary buttons and highlights.
  * The logo field is an img.logo.dev URL and accepts size, retina=true, and format=webp parameters. For logo URLs built directly in client code, use [https://img.logo.dev/:domain?token=LOGO\_DEV\_PUBLISHABLE\_KEY\&size=32\&retina=true\&format=webp](https://img.logo.dev/:domain?token=LOGO_DEV_PUBLISHABLE_KEY\&size=32\&retina=true\&format=webp)
  * The secret key stays on the server; the publishable key is safe in client code.
  * Reference implementation: [https://www.logo.dev/docs/use-cases/brand-colors](https://www.logo.dev/docs/use-cases/brand-colors)
</Prompt>

## Code

This example is in React, but you can get the same result in any frontend framework: the pattern is one fetch, one accent pick, and inline styles. Fetch the brand with `get-brand.ts`, then hand the logo and accent to whatever renders your output.

<CodeGroup>
  ```ts get-brand.ts theme={null}
  type Brand = {
    name: string;
    domain: string;
    logo: string;
    colors: { hex: string }[];
  };

  export async function getBrand(domain: string): Promise<Brand> {
    const res = await fetch(`https://api.logo.dev/brand/${domain}`, {
      headers: { Authorization: `Bearer ${process.env.LOGO_DEV_SECRET_KEY}` },
    });
    if (!res.ok) {
      throw new Error(`Brand lookup failed: ${res.status}`);
    }
    return res.json();
  }

  // The palette is ordered, but black and white often lead it.
  // Take the first color saturated enough to work as an accent.
  export function pickAccent(colors: { hex: string }[]) {
    const isNeutral = (hex: string) => {
      const [r, g, b] = [1, 3, 5].map((i) =>
        parseInt(hex.slice(i, i + 2), 16)
      );
      return Math.max(r, g, b) - Math.min(r, g, b) < 30;
    };
    return colors.find((c) => !isNeutral(c.hex))?.hex ?? "#18181b";
  }
  ```

  ```tsx BrandedHero.tsx theme={null}
  type BrandedHeroProps = {
    name: string;
    logoUrl: string;
    accent: string;
    headline: string;
  };

  export function BrandedHero({
    name,
    logoUrl,
    accent,
    headline,
  }: BrandedHeroProps) {
    return (
      <section className="rounded-xl border border-zinc-950/10 bg-white p-8">
        <img
          alt={`${name} logo`}
          className="h-8 w-8 object-contain"
          height={32}
          src={logoUrl}
          width={32}
        />
        <h1 className="mt-4 text-2xl font-semibold">{headline}</h1>
        <button
          className="mt-6 rounded-lg px-4 py-2.5 text-sm font-semibold text-white"
          style={{ backgroundColor: accent }}
          type="button"
        >
          Get started
        </button>
      </section>
    );
  }
  ```

  ```tsx Usage theme={null}
  import { BrandedHero } from "./BrandedHero";
  import { getBrand, pickAccent } from "./get-brand";

  export async function renderWelcome() {
    const brand = await getBrand("spotify.com");
    return (
      <BrandedHero
        accent={pickAccent(brand.colors)}
        headline={`Welcome to ${brand.name}`}
        logoUrl={brand.logo}
        name={brand.name}
      />
    );
  }
  ```
</CodeGroup>

<Note>
  Your [publishable key](/docs/platform/api-keys) is built for client-side code, so
  you can ship it in the browser as-is. Your secret key powers the
  `get-brand.ts` fetch and stays on the server.
</Note>

## How it works

* **Each brand is one request.** `GET /brand/:domain` from the [Brand API](/docs/brand/introduction) returns the name, logo URL, and an ordered color palette together, so a generation pipeline adds exactly one fetch.
* **The logo URL is ready to use.** The `logo` field is an `img.logo.dev` URL that accepts the usual `size`, `format`, and `theme` [image parameters](/docs/logo-images/introduction#parameters), so the same response themes a thumbnail or a hero.
* **Neutrals need filtering.** Palettes often lead with black or white, so `pickAccent` skips low-saturation colors and buttons never render in #000.

## Make it your own

* **Reuse the theme for slides and emails.** The same logo and accent pair drives a slide master, an email header, or a PDF cover. Import the full kit with the [brand asset import](/docs/use-cases/brand-assets) pattern when you need banners too.
* **Pair it with onboarding.** Get the domain from the user's work email with the [onboarding autofill](/docs/use-cases/onboarding-personalization) pattern, then theme their whole workspace.

## Next steps

<CardGroup cols={2}>
  <Card title="Brand API" icon="swatchbook" href="/docs/brand/introduction">
    Get the full brand profile: logo, brandmark, banners, and colors.
  </Card>

  <Card title="Onboarding personalization" icon="wand-magic-sparkles" href="/docs/use-cases/onboarding-personalization">
    Capture the domain at signup and theme from day one.
  </Card>
</CardGroup>
