Recipes

Personalize a landing page from a domain

Use brandRNA's brand pack to render a tailored landing page that mirrors the target's visual identity.

When a sales prospect lands on your site from an outbound email, generic copy and stock visuals waste the moment. With brandRNA you can fetch their brand identity from a domain in one HTTP call and render a landing page that looks like a continuation of their product — same colours, same fonts, same logo in your hero.

This recipe shows the end-to-end flow.

When this is useful

  • Outbound landing pages — sales pages personalised to the prospect's brand at click-through time.
  • Reverse-trial onboarding — show the new signup what their dashboard looks like with their own colours plugged in before they invite the team.
  • Pitch decks / demo videos — script-driven reskins of a product walkthrough.

Prerequisites

  • A brandRNA API key — see Quickstart if you don't have one. Store it in BRANDRNA_API_KEY (env var, never committed).
  • A landing-page rendering layer that can take colour + font tokens at request time. Tailwind is shown below; CSS variables work just as well.

Step-by-step

Fetch the brand pack

Hit the cached consolidated endpoint with the prospect's domain:

curl -H "Authorization: Bearer $BRANDRNA_API_KEY" \
     https://api.brandrna.com/api/v1/pack/stripe.com
import os
import httpx

KEY = os.environ['BRANDRNA_API_KEY']

async def fetch_pack(domain: str) -> dict:
    async with httpx.AsyncClient(timeout=30) as client:
        r = await client.get(
            f"https://api.brandrna.com/api/v1/pack/{domain}",
            headers={"Authorization": f"Bearer {KEY}"},
        )
        r.raise_for_status()
        return r.json()
const KEY = process.env.BRANDRNA_API_KEY!;

export async function fetchPack(domain: string) {
  const res = await fetch(
    `https://api.brandrna.com/api/v1/pack/${domain}`,
    { headers: { Authorization: `Bearer ${KEY}` } },
  );
  if (!res.ok) throw new Error(`brandRNA ${res.status}`);
  return res.json();
}

Extract colours and fonts

The response is a flat document — pull what you need:

const pack = await fetchPack("stripe.com");

const tokens = {
  colors: {
    primary: pack.colors.primary,         // "#635BFF"
    secondary: pack.colors.secondary,     // "#0A2540"
    accent: pack.colors.accent,           // "#00D4FF"
    bg: pack.colors.background,           // "#FFFFFF"
    text: pack.colors.text,               // "#0A2540"
  },
  font: pack.fonts[0]?.family ?? "Inter", // "sohne-var"
};

Inject into the page at render time

For Tailwind-based stacks, see Use brand colours in a Tailwind config for a build-time approach. For request-time injection, write CSS variables into the page head:

export default async function LandingPage({ domain }: { domain: string }) {
  const pack = await fetchPack(domain);
  const c = pack.colors;
  return (
    <html>
      <head>
        <style>{`
          :root {
            --brand-primary: ${c.primary};
            --brand-secondary: ${c.secondary};
            --brand-bg: ${c.background};
            --brand-text: ${c.text};
          }
          body { font-family: ${pack.fonts[0]?.family ?? "Inter"}, sans-serif; }
        `}</style>
      </head>
      <body className="bg-[var(--brand-bg)] text-[var(--brand-text)]">
        <Hero pack={pack} />
        <Features pack={pack} />
      </body>
    </html>
  );
}

Use the canonical logo in the hero

The brand pack returns multiple logo variants. Use role: "wordmark" where you have horizontal space, role: "icon" for tight slots:

const wordmark = pack.logos.find((l: any) => l.role === "wordmark");
const url = wordmark?.url; // hosted by brandRNA, no CORS issues

<img src={url} alt={`${pack.brand} logo`} className="h-10" />

For dark backgrounds, prefer the dark variant:

const darkUrl = wordmark?.variants?.includes("dark")
  ? wordmark.url.replace(/\.svg$/, ".dark.svg")
  : wordmark.url;

Cache the pack server-side

A request-time fetch adds ~80ms latency on cache hits. For high-traffic landing pages, cache the pack in your own backend with the same 24h TTL brandRNA uses internally. See Cache brand packs in your own backend for the recommended schema and invalidation hooks.

Final result

A landing page that mirrors the prospect's brand without manual design work. Pair this with a copy-rewriter (LLM or template) keyed on the same domain to personalise the headline too.

Famous domains return instantly from cache (metadata.cached: true, $0). Novel domains trigger a 5–15s extraction and count toward your quota. Plan your timeouts accordingly.

What's next

On this page