Image

Brand kits

Give the editor your brand's logo, colors, text styles, and writing rules.

A brand kit is the data of one brand: its name, logo, colors, text styles, and the way it writes. You pass one kit or many in templateMetadata. The editor then offers the brand's colors and text styles in the places where the user picks them, and it adds the brand to AI requests.

This page is about the brand of the design. Theme Studio has a different setting that is also called "Brand color". It sets the colors of the editor's own buttons and panels. See Theming. The two do not affect each other.

Setup

Pass the kits in templateMetadata.brands. Pass activeBrandId to choose the kit that is active when the editor opens:

import { ImageEditor, type BrandKit } from '@layermetry/media-editor/react';

const brands: BrandKit[] = [
  {
    id: 'northwind',
    name: 'Northwind Studio',
    logoUrl: 'https://cdn.example.com/northwind-logo.png',
    description: 'Boat charters and harbour tours.',
    colors: {
      primary: '#1F4E79',
      secondary: '#F2B134',
      palette: { 'Harbour blue': '#1F4E79', 'Buoy yellow': '#F2B134' },
    },
    textStyles: {
      headline: {
        textStyleName: 'Headline',
        fontFamily: 'Georgia',
        fontSize: 96,
        fontWeight: 700,
        lineHeight: 1.1,
        fontStyle: 'normal',
        textDecoration: 'none',
      },
    },
    voice: 'warm, plain and precise',
    locale: 'en-GB',
  },
  { id: 'harbourbrew', name: 'Harbour Brew', colors: { primary: '#6B3E26' } },
];

export default function App() {
  return (
    <div style={{ position: 'fixed', inset: 0 }}>
      <ImageEditor
        licenseKey="YOUR_LICENSE_KEY"
        onClose={() => console.log('The editor was closed')}
        templateMetadata={{ metadata: {}, brands, activeBrandId: 'northwind' }}
        onBrandChange={(brandId) => console.log(`Brand: ${brandId}`)}
      />
    </div>
  );
}

Expected result: the tool rail has a Brand entry right after Text, with the name "Northwind Studio" under it. Because two kits are listed, the panel has a menu that switches the kit.

Default: no brand, no Brand entry, and every color picker looks as it did before.

The one-brand form

The form that earlier versions used keeps working. The editor reads colors, textStyles, logoUrl, and description at the top of templateMetadata, the id from metadata.brandId, and the name from metadata.brandName. It treats them as a list of one kit.

templateMetadata={{
  metadata: { brandId: 'northwind', brandName: 'Northwind Studio' },
  colors: { primary: '#1F4E79', secondary: '#F2B134' },
  textStyles: { headline: { textStyleName: 'Headline', fontFamily: 'Georgia', fontSize: 96 } },
  logoUrl: 'https://cdn.example.com/northwind-logo.png',
}}

A list in brands with at least one entry wins. The one-brand fields next to it are then ignored. Without metadata.brandId, the kit has an empty id. An empty id is never saved with a design, and onBrandChange is not called for it.

Brand kit fields

id and name are the only required fields. Every other field is optional.

FieldTypeDescription
idstringYour stable id for the brand. activeBrandId, onBrandChange, and a saved design's brandKitId use it.
namestringThe name that people see. A long name is cut with "…" and shown in full in a tooltip.
logoUrlstringAn address that the editor can load the logo from. The logo server must allow cross-origin reads.
descriptionstringOne or two sentences that the Brand panel shows.
colors{ primary?, secondary?, palette? }primary and secondary are hex colors. palette is a map from a color name to a hex color.
textStylesRecord<string, TextStyle>Named text styles. The fields are the same as in Brand text styles.
voiceTraits{ name, description?, example? }[]Detail behind voice.
tone{ formal?, playful?, bold?, calm? }Four sliders. Each is a whole number from 1 (not at all) to 5 (very).
toneByChannel{ channel, tone }[]The tone for each channel, such as Instagram.
audiencestringWho the brand speaks to.
localestringA language tag such as 'en-GB'. It sets the spelling of generated text.
accentstringThe accent for voice-overs, such as "British English". The image editor has no voice-overs, so it does not use it.
pillarsstring[]The themes that the brand talks about.
guidelinesobjectsummary, dos, donts, photography, graphics, motion, color, logo, and typography. Each is text, except dos and donts, which are lists of short rules.

A panel shows only the logo, the colors, the text styles, and the description. The writing fields are never shown. They go to the Generate boxes, so that people do not type them again.

Each color must be a hex color: #rgb, #rgba, #rrggbb, or #rrggbbaa. Any other value, such as navy or rgb(31, 78, 121), is left out. Every color action of the editor accepts only hex, so a swatch never offers a color that an action refuses.

Which kits are kept

The editor keeps a kit that has an id and at least one thing it can use. That is a logo, a main color, a text style, or any writing field. A kit that has only a name is left out, and the console shows a warning that starts with [Brand]. A kit without an id, or with an id that is already listed, is left out with a warning too.

A kit that has only writing fields is kept, and it reaches the Generate boxes. It has no Brand entry, because its panel would be empty.

Names on screen

With a name, the editor shows the name, such as "Brand: Northwind Studio". A kit without a name shows its id when two or more kits are listed, so that people can tell them apart. A single kit without a name shows only "Brand", and no id.

Choosing the active kit

When the editor opens, it picks the active kit in this order:

  1. The brandKitId saved in the design, if you still list that kit.
  2. Your activeBrandId, if you list that kit.
  3. The first kit in the list.

If you pass a different activeBrandId later, the editor switches to that kit, if it is listed. A new templateMetadata object with the same ids changes nothing, so a React page that writes templateMetadata={{ ... }} inline does not undo a switch that the user made.

When the user opens a saved design from the Templates panel, the design's kit becomes active, if it is listed.

Force one brand

To make the editor use one brand and offer no choice, pass only that brand. The menu appears from two kits, so a list of one kit has no menu.

templateMetadata={{ metadata: {}, brands: brands.filter((kit) => kit.id === currentCustomerBrandId) }}

A saved design from another brand then does not change the kit, because the editor does not list that kit.

Brand change events

onBrandChange(brandId) is called when the editor opens with a kit, and again on every switch. The argument is the id of the active kit. The custom element <media-editor-image> sends a brandchange event too, and its detail is the id.

const editor = document.querySelector('media-editor-image');
editor.addEventListener('brandchange', (event) => {
  console.log(`brandchange: ${event.detail}`);
});

A switch does not change the design. It is not an undo step, and it does not mark the design as unsaved. If your function throws an error, the console shows it and the editor continues.

Saved designs

A saved design remembers its kit as template.brandKitId. Saving a template or a draft writes it. The editor gives it back when the design opens. It is never written into your metadata.

The editor leaves brandKitId out when the active kit has an empty id. It ignores a saved id that you no longer list.

Brand panel

The Brand panel is in the tool rail right after Text. In the compact layout, the dock tile says "Brand", and the first line of the sheet names the brand. With two or more kits, the panel heading has a menu that switches the kit.

The panel shows these parts, in this order. It leaves out a part that the kit does not have.

PartWhat it does
The brand lineShows "Brand: " and the name. It is read-only.
ColorsA click sets the color of every selected text and shape.
Text stylesA click styles the selected text. With nothing selected, it adds new text in that style.
LogoShows the logo. The image editor has no button that adds it to the page.
DescriptionThe description of the brand, cut to two lines.

A color click goes to every selected text and shape. Each click is one undo step. A picture or the background is not changed, and a message next to the colors says so.

A text style click sets the font, size, weight, italic, underline, and line height that the style names. It sets each value and never switches one. A bold text box stays bold when it gets a bold style. Each click is one undo step.

Your page must load the brand font, as for Brand text styles. The image editor does not wait for the font to load before it styles the text.

Brand styles in the Text panel

The Text panel has a Brand styles card with the same text styles and, with two or more kits, the same menu. The card is not shown when the active kit has no text styles.

Brand colors in color pickers

Every color picker has a Brand colors row with the name of the brand and one dot for each color of the kit. The row is not shown when the kit has no colors. The kit menu is not in the pickers. It is only in the panel heading, the first line of the compact sheet, and the Brand styles card.

Hide or rename the panel

ui.panels.brand hides the Brand entry in the rail and the dock, or changes its name:

<ImageEditor
  licenseKey="YOUR_LICENSE_KEY"
  onClose={() => console.log('The editor was closed')}
  templateMetadata={{ metadata: {}, brands }}
  ui={{ panels: { brand: { label: 'Company brand' } } }}
/>
KeyTypeDefaultDescription
visiblebooleantruefalse hides the Brand entry, the panel, and the Brand styles card.
labelstringBrandThe name in the rail, the dock, the panel heading, and the tooltip.

ui.toolRail.hidden and ui.dock.hidden with the id brand hide the entry as well. See UI customization.

Generate with brand

When the editor has an active kit, each Generate box shows a Use brand switch. The switch adds a few brand words after the person's own words. Under the switch is one chip for each part of the brand that the request uses, such as Colors, Look, Voice, or Dos and don'ts. A chip that is turned off is missing from the prompt and from the data that goes to your server.

Above the Generate button, one line shows what will be added, for example "Added to your request: voice, tone, dos and don'ts, spelling (185 characters)". It opens to the exact words.

The row appears only when all four of these are true:

  • The editor has an active kit.
  • The editor has an AI service.
  • You did not set ai.brand to false.
  • The kit has something for this kind of request. If it has nothing, the row is hidden and the box is as it was before.

The switch and the chips are remembered for each kind and each kit while the editor is open. They are not saved in the design.

What each kind gets

"Words" is the text added to the prompt. "Data" is what input.brand carries.

KindWords addedData in input.brand
imageThe colors, and the look from guidelines.photography.colors, visualStyle
stickerThe colors, and the look from guidelines.graphics.colors, visualStyle
svgPathThe colors.colors
imageEditThe colors and the look. The switch starts off.colors, visualStyle
textThe voice with the brand name, the tone in words, the audience, up to 3 dos and 3 don'ts, and the spelling from locale.voice, tone, audience, dos, donts, locale
textRewriteThe same as text. The words go into instruction, never into text.The same as text

Rules that always hold

  • The brand words come after the person's own words, after one blank line. For a sticker, the words come after the filled sticker template, so they never land inside the subject.
  • A picture prompt never carries the brand name or the dos and don'ts.
  • A color is written as a name and a code, such as "Harbour blue (#1F4E79)". The name comes from colors.palette. Without a name, only the code is written.
  • Every kit field is cleaned before use. Each line break and control character becomes a space, so a field cannot start a new paragraph in the prompt. A field is cut to 160 characters (the look) or 80 characters (voice, audience, a color name, and one rule).
  • The whole addition has at most 300 characters for pictures and stickers, and at most 600 characters for text. A part that does not fit is left out, and so is every part after it. It is left out of the words and of the data, and the line above Generate names it.

Settings: ai.brand

ai.brand changes how the feature works. Its value is false or an object:

<ImageEditor
  licenseKey="YOUR_LICENSE_KEY"
  onClose={() => console.log('The editor was closed')}
  templateMetadata={{ metadata: {}, brands }}
  ai={{
    endpointUrl: '/api/ai',
    brand: { addToPrompt: false, operations: { imageEdit: true, sticker: false } },
  }}
/>
SettingDefaultDescription
ai.brand = falseBrand is onRemoves the switch from every box. Nothing is added to any prompt, and input.brand is never sent.
ai.brand.addToPrompttruefalse keeps the switch and sends input.brand, but adds no words to the prompt. The line above Generate then says "Your words are sent as typed. The brand facts go with the request for the server to use."
ai.brand.operationsOn for every kind except imageEditSets, for each kind, whether the switch starts on. The person can still change it in the box.

The editor refuses these values and names the setting in the error: operations.soundEffect or operations.captions, because those never use a brand and the image editor has no such request; an unknown key, such as ai.brand.addToPrompts; true; and any other value that is not true or false.

Your own server: input.brand

With a brand, the request to your server carries input.brand. A server that words its own prompts can read it and can remove the added words with an exact match on addedToPrompt:

{
  "type": "text",
  "prompt": "A headline\n\nWrite in a warm, plain and precise voice.",
  "input": {
    "operation": "text",
    "prompt": "A headline\n\nWrite in a warm, plain and precise voice.",
    "brand": {
      "kitId": "northwind",
      "name": "Northwind Studio",
      "addedToPrompt": "\n\nWrite in a warm, plain and precise voice.",
      "used": ["voice"],
      "voice": "warm, plain and precise"
    }
  }
}

The example is shortened, and the real words of addedToPrompt are longer. The fields of input.brand are:

FieldTypeDescription
kitId, namestringThe id and the name of the kit.
addedToPromptstringThe exact words added, with the blank line before them. It is '' when nothing was added.
usedstring[]The parts used: colors, visualStyle, voice, tone, audience, rules, spelling.
colors{ role, hex, name? }[]The colors used.
voice, audience, locale, visualStylestringThe parts used.
tone{ formal?, playful?, bold?, calm? }The tone sliders.
dos, dontsstring[]The rules used.

input.brand is missing when no brand is active, when ai.brand is false, and for requests that never use a brand. A part that the person turned off is missing from input.brand too.

The name brand is reserved. A model field cannot use it, and a brand key that arrives with the model settings is removed before the editor adds its own. See Custom AI endpoint.

Configuration

NameTypeDefaultDescription
templateMetadata.brandsBrandKit[]noneThe brand kits.
templateMetadata.activeBrandIdstringfirst kitThe kit that is active when the editor opens, unless the design saved its own.
onBrandChange(brandId: string) => voidnoneCalled when the editor opens and on every switch.
ui.panels.brand{ visible?, label? }visible, BrandHides or renames the Brand entry.
ai.brandfalse or { addToPrompt?, operations? }onControls Use brand in the Generate boxes.

Troubleshooting

Additional resources

On this page