RivermarkRivermark
Guides

Brand extraction, then on-brand content

Extract a user's brand once, then create everything on-brand.

The most common integration: during onboarding, extract the user's brand once, then power every subsequent design request with it. Brand extraction is the most expensive single call you'll make — and the one you'll make the least often.

1. Gather brand references

Let the user provide any mix of:

  • their website — just a URL,
  • images — logos, previous posts, packaging photos,
  • a .zip of brand guidelines — the full drop from their designer,
  • Canva designs or existing materials.

A single reference works; more references give a more complete picture. Don't make users hunt for perfect inputs — Rivermark reconciles conflicting signals (like a website palette that differs from official guidelines) into one coherent brand.

2. Extract the brand kit

onboarding.ts
const api = (path: string, body: object) =>
  fetch("https://api.rivermark.ai" + path, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.RIVERMARK_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  }).then((r) => r.json());

// 1. Upload any files the user attached
const references = [];
for (const file of userAttachments) {
  const form = new FormData();
  form.append("file", file);
  const uploaded = await fetch("https://api.rivermark.ai/upload", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.RIVERMARK_API_KEY}` },
    body: form,
  }).then((r) => r.json());
  references.push({ type: "file", id: uploaded.id });
}
// 2. Add their website
if (userWebsite) references.push({ type: "url", url: userWebsite });

// 3. Extract the brand
const brandkit = await api("/brandkit", {
  references,
  allow_fetch: true, // let it reach the About page, media kit, etc.
});

// 4. Store the design ID — this is your permanent brand handle
await db.brandkits.create({ userId: user.id, designId: brandkit.design_id });

The response gives you a structured brand definition plus ready-made visuals:

Response (trimmed)
{
  "design_id": "rmd_cj4hbqz4f0005mz6x7p9q2xr",
  "name": "Acme Coffee Co.",
  "tagline": "Slow mornings, fast coffee",
  "palette": [{ "hex": "#2D1B0E", "name": "Roast", "role": "primary" }],
  "fonts": [{ "family": "Fraunces", "role": "title" }],
  "brand_board": "https://cdn.rivermark.ai/rmd_cj4hbqz4f0005mz6x7p9q2xr/q7m2xk4d/board.png",
  "brand_header": "https://cdn.rivermark.ai/rmd_cj4hbqz4f0005mz6x7p9q2xr/q7m2xk4d/header.png",
  "cost": 0.75
}

3. Use what you got

In your interface:

  • brand_board — a full visual board of the brand; great as an onboarding "this is what we found" confirmation screen.
  • brand_header — a compact 1200x900 card (logo, tagline, palette); use it wherever the user needs to identify the brand, like a brand picker.

Download both immediately — rendered URLs are ephemeral.

In Rivermark: design_id is the brand handle. Everything the agent makes with it uses the extracted fonts, colors, logos, and imagery as-is — never approximated or redrawn. No brand parameters to configure, no style JSON to maintain.

4. Create on-brand content

Now every content request is one call referencing the brand kit:

const design = await api("/design", {
  task: [
    "Create an Instagram post announcing our new seasonal roast.",
    "Headline: 'The Autumn Roast is here'.",
    "Subline: 'Notes of fig, cedar, and bonfire smoke.'",
  ].join(" "),
  references: [{ type: "design", id: brandkit.design_id }],
  output: [{ id: "post", size: "1080x1350" }],
});

The agent will use the brand kit's fonts, hex values, logos, and imagery as-is. No brand parameters to configure, no style JSON to maintain.

Economics

A brand extraction is done once per user and amortizes across every design they ever create — see Costs for typical numbers, and the user-created templates guide for how to make each subsequent design even cheaper.

On this page