---
title: "Configuration, MailKaro Docs"
description: "When you use EmailEditor directly, a config object tailors appearance, branding, panels, localization, AI, and more."
---

# Configuration

The editor

# Configuration

When you use [EmailEditor](https://mailkaro.com/docs/react) directly, a `config` object tailors appearance, branding, panels, localization, AI, and more.

ts

```
interface MailkaroConfig {
 appearance?: { mode?: "light" | "dark"; direction?: "ltr" | "rtl"; theme?: MailkaroTheme; customCss?: string | string[] };
 branding?: { badge?; assetLibraryTitle?; templateLibraryTitle?; paletteLogoUrl?; paletteLogoAlt?; toolbarName?; toolbarLogoUrl? };
 ui?: { panels?: { content?; blocks?; body? }; minimap?: boolean; rowInset?: boolean; builderLook?: boolean; devices?: { id; label; width; icon? }[]; toolbar?: { … } };
 localization?: { locale?: string; messages?: Partial<MailkaroMessages> };
 assets?: { googleDrive?; s3Connector?; unsplashConnector?; pexelsConnector? };
 blocks?: { disabled?: BlockType[]; limits?: Partial<Record<BlockType, number>> };
 colors?: { presets?: string[]; brand?: string[]; recent?: boolean | number };
 sendTestEmail?: (email: { html; subject; to }) => Promise<void>;
 linkTypes?: { id; label; url_template?; prefix?; placeholder? }[];
 comments?: { key?; user; members?; canWrite?; canModerate?; load; create; reply; resolve; remove }; // see Comments
 textEditor?: { customButtons?: { name; label?; icon?; text?; onAction? }[] };
 ai?: { adapter?: MailkaroAiAdapter; defaultPrompt?; defaultSubjectCount? };
 collaboration?:{ sessionId; user; adapter?; showPresence? };
 role?: "owner" | "admin" | "editor" | "viewer"; // "viewer" ⇒ read-only editor
 entitlements?: MailkaroEntitlements; // usually server-supplied
 policy?: MailkaroProjectPolicy;
 plugins?: MailkaroPlugin[];
}
```

ℹ `role` gates the acting user in the embedded editor, a `viewer` gets a read-only editor (same effect as `policy.read_only`); `editor` / `admin` / `owner` can edit. Managing a team roster (inviting members, assigning their roles) is a dashboard concern, separate from this.

## appearance

`mode` switches light/dark; `direction` supports RTL; `theme` overrides CSS variables, `bg`, `panel`, `text`, `accent`, `accentStrong`, `canvas`, `font`, `radiusLg`, `shadow`, and more.

tsx

```
<EmailEditor
 config={{
 appearance: {
 mode: "dark", theme: { accent: "#0d9488", accentStrong: "#0f766e", font: "Inter" }
 }
 }}
/>
```

## branding & ui

- `branding.paletteLogoUrl`, your logo in the palette footer (needs the `branding.white_label` entitlement).
- `branding.toolbarName` and `branding.toolbarLogoUrl`, your own name and logo at the left of the toolbar instead of MailKaro (needs the `branding.white_label` entitlement).
- `ui.toolbar.brand`, set it `false` to hide that brand block, for example when your page already shows your logo. This works on every plan.
- `ui.panels`, hide any of `content`, `blocks`, `body` by setting it `false`.
- `ui.devices`, the screen sizes in the toolbar, as `{ id, label, width, icon? }`. The default is Desktop and Mobile. The first size is the one the editor opens in, `desktop` keeps the design's own content width, and no size is ever wider than that width.
- `ui.minimap`, `true` adds a small map of the whole email at the top right of the canvas, a box for each row and a frame for what is on screen. Click or drag it to scroll, or use the arrow keys. It is off by default, it hides when the whole email already fits, and it is not shown while previewing.
- `ui.rowInset`, `true` draws each row's left and right padding on the canvas, as the sent email does, so the colour behind the cards shows around them. Off by default, which keeps the canvas as it always was.
- `ui.builderLook`, `true` gives each builder its own look on the canvas: a sheet of paper for `document`, a browser frame for `page` and a floating card for `popup`. Off by default, and it never changes the exported HTML, PDF or document, only how the editor draws the canvas.
- `ui.toolbar`, toggle `undoRedo`, `deviceToggle`, `preview`, `saveVersion`, `exportJson`, `exportHtml`, or add `customActions`. Paid toolbar items also require the matching entitlement.

## blocks

`blocks.disabled` removes block types from the palette and stops them being added. `blocks.limits` caps how many blocks of a type one design can hold; the palette tile says "Limit reached" until a block is deleted. The config only narrows what the plan already allows. Blocks already in a design stay, and drag, click, duplicate and paste all follow the same rules.

tsx

```
<EmailEditor config={{ blocks: { disabled: ["video", "raw-html"], limits: { image: 6, button: 3 } } }} />
```

## colors

Every color field has a small arrow beside the swatch that opens your saved colors: `colors.brand` first, then `colors.presets`, then the colors the person used last. `recent` is `true` (8 colors) by default, a number sets how many, and `false` turns it off. Recent colors live in the browser's local storage; when storage is blocked the picker still works. Values must be hex colors such as `#0d9488`, and anything else is ignored. With no palette and recent colors off, the field is just the native picker.

tsx

```
<EmailEditor config={{ colors: { brand: ["#0d9488", "#134e4a"], presets: ["#ffffff", "#111827"], recent: 6 } }} />
```

## linkTypes

`linkTypes` adds your own kinds of button link to the Action Type list, such as WhatsApp or a booking page. The person types a value and the editor builds the link: give a `url_template` with `{value}` in it, or a `prefix` the value is added to. The value is URL-encoded (merge tags in it are kept), the finished link is stored on the button, and the typed value is kept so it can be edited later. A type is ignored unless it starts with `https://`, `http://`, `mailto:`, `tel:` or a merge tag, because email clients drop other kinds of link. The ids `open-website`, `send-email`, `call-phone`, `unsubscribe` and `view-in-browser` are taken.

tsx

```
<EmailEditor
 config={{
 linkTypes: [
 { id: "whatsapp", label: "WhatsApp", url_template: "https://wa.me/{value}", placeholder: "919876543210" },
 { id: "booking", label: "Booking page", prefix: "https://cal.example.com/", placeholder: "team-name" }
 ]
 }}
/>
```

## comments and sendTestEmail

- `comments` keeps comment threads on your own server instead of in the browser. See [Comments](https://mailkaro.com/docs/comments) for the adapter.
- `sendTestEmail` adds a "Send a test email" button that calls your function. See [Test email](https://mailkaro.com/docs/test-email). `ui.toolbar.sendTestEmail: false` hides it.

## textEditor

`textEditor.customButtons` adds up to eight buttons to the text and heading toolbar. A button either inserts `text` or runs `onAction(selectedText, apply)`; `apply(text)` replaces the selection, or inserts at the cursor when nothing is selected. It writes plain text, never HTML, and it can be called later (after a fetch) because the selection is remembered when the button is clicked. A button needs a `name` made of letters, numbers, dashes or underscores, and one of `text` or `onAction`; others are ignored. A function that throws does not break editing.

tsx

```
<EmailEditor
 config={{
 textEditor: {
 customButtons: [
 { name: "signature", label: "Insert signature", icon: "Sg", text: "Warm regards, The team" },
 { name: "upper", label: "Make uppercase", icon: "AA", onAction: (selected, apply) => apply(selected.toUpperCase()) }
 ]
 }
 }}
/>
```

## ai & collaboration

Plug your own AI backend via `ai.adapter` (four async methods: generate design, rewrite text, subject lines, alt text). Enable live presence via `collaboration`. Both are gated by [plan + policy](https://mailkaro.com/docs/plans).

## policy

A per-project policy can only *remove* capability the plan granted: `read_only`, `allow_ai`, `allow_exports`, `allow_uploads`, `allow_collaboration`, `allow_raw_html`, `allow_external_images`, `allow_custom_fonts`. See [Plans & entitlements](https://mailkaro.com/docs/plans).

Source: https://docs.mailkaro.com/configuration
