@lettrove/vue

: the embeddable drag-and-drop email editor and page builder as a Vue 3 component. White-labeled, AI built in, HTML that renders in every inbox.
770
Install
npm install @lettrove/vue
Latest Version:1.1.0
Vue:3
License:MIT
Last Updated:Oct 13, 2026
Links: npm
Maintainer: lettrove-team

@lettrove/vue

npm licence docs

The embeddable drag-and-drop email editor and page builder, as a Vue 3 component. Your users design emails, landing pages, popups and documents inside your product, under your name and logo, with AI built in, and with HTML that renders in every inbox.

Website · Docs · Vue guide · Your projects and keys · Changelog · Support

This README describes the version of @lettrove/vue you installed: it is published with it.

<LettroveEditor /> is built on @lettrove/embed, which it installs. The editor itself loads from https://lettrove-embed.com, so this package stays small and fixes reach your users without a reinstall. Vue 3.3 or newer, and Nuxt.

What you get

  • Four kinds of design in one editor: emails, landing pages, popups and print-ready documents.
  • Your product, not ours: your logo and name, your colours through theme tokens, light and dark.
  • Email that works: compiled for every major email client, images hosted, merge tags with fallbacks.
  • Every way out: HTML, plain text, PNG, PDF and ZIP, from the page or later from your server.
  • Saved as your users work, with restore points.
  • Made for Vue: one component, one emitted event per editor event, the editor handle on a template ref, and safe under server rendering.

Before you start

  1. Sign up at lettrove.com and open Settings → Embed.
  2. Create a project and copy its two test keys: the publishable key (lt_pk_test_…, for your page) and the secret key (lt_sk_test_…, for your server).
  3. Add a route on your server that mints editor tokens with the secret key, using @lettrove/node. The secret key never reaches the browser.

Test keys work on localhost, so nothing needs adding to the allowed sites while you build.

Quick start

npm install @lettrove/vue

Your server, e.g. POST /lettrove-token behind your own login (in Nuxt, a server route):

import { Lettrove } from '@lettrove/node';

const lettrove = new Lettrove({ secretKey: process.env.LETTROVE_SECRET_KEY! });

export async function POST(request: Request) {
  const user = await currentUser(request); // yours
  const { token } = await lettrove.tokens.create({ user: { id: user.id }, origin: request.headers.get('origin')! });
  return Response.json({ token }, { headers: { 'cache-control': 'no-store' } });
}

Your page:

<script setup lang="ts">
import { ref } from 'vue';
import { LettroveEditor } from '@lettrove/vue';

const savedDesignId = ref<string | undefined>(undefined);

async function getToken() {
  const response = await fetch('/lettrove-token', { method: 'POST' });
  return (await response.json()).token;
}
</script>

<template>
  <LettroveEditor
    publishable-key="lt_pk_test_…"
    :get-token="getToken"
    :design-id="savedDesignId"
    @design-saved="({ designId }) => (savedDesignId = designId)"
    style="height: 720px"
  />
</template>

Lettrove saves the design as your user works. Keep the designId from @design-saved to open the same design next time.

The whole thing step by step: Vue.

Props

Every option of createEditor from @lettrove/embed is a prop, except container, signal and on, which the component provides. In a template, write them in kebab-case and bind values with :.

Prop
publishable-key Required. lt_pk_test_… or lt_pk_live_….
get-token Required. Resolves with a fresh token string from your server.
design-id The design to open. Left out, a new one is started.
release The editor release: '1' (the default line), '1.2', '1.2.3' or 'stable'.
mode 'email', 'page', 'popup' or 'document': a check against the project's mode.
tabs { blocks, layers, brand, inspector, images, history }: false removes a panel.
tools { disabled, order }: which tools the palette offers, and in what order.
features { undoRedo, preview: { mobile }, ai: { images }, themeSwitch, download }.
branding { poweredBy }. Your logo and name are set on the project, not here.
appearance { theme, variables, darkVariables, panels }: theme tokens and docking.
storage, providers Keep your users' images or designs in your own storage.

class and style go to the element the editor fills: give it a height.

Every option, its type and its default: @lettrove/embed options. Options can only narrow what the project allows.

<LettroveEditor
  publishable-key="lt_pk_test_…"
  :get-token="getToken"
  :tools="{ disabled: ['html'] }"
  :features="{ download: false }"
  :appearance="{ theme: 'auto', variables: { accent: '#5b3df5', radius: '10px' } }"
  style="height: 100vh"
/>

Events

Event Payload
@ready The editor handle, once the editor is on screen
@error A LettroveEmbedError (code, message, docsUrl): it could not open, or reported an error while open
@design-loaded { designId, designVersion, upgradedFrom?, hasNewerBlocks? }
@design-updated { design, revision, change: { kind, blockId? } }; kind is edit, undo, redo, restore or assistant
@design-saved { designId, revision }
@selection-changed { blockId, type }, both null when nothing is selected
@image-uploaded { url, width?, height?, id? }
@theme-changed { theme, applied }
@config-adjusted { option, reason }: an option was dropped or changed

Every payload, field by field: Events.

The editor handle on a template ref

A template ref to the component is a LettroveEditorInstance. Its editor is the editor handle once the editor is open, and null before and after.

<script setup lang="ts">
import { ref } from 'vue';
import { LettroveEditor, type LettroveEditorInstance } from '@lettrove/vue';

const designer = ref<LettroveEditorInstance | null>(null);

async function exportEmail() {
  const email = await designer.value?.editor?.exportHtml({ merge: { contact: { first_name: 'Ada' } } });
  if (email) await sendWithMyProvider(email.subject, email.html);
}
</script>

<template>
  <button @click="exportEmail">Send</button>
  <LettroveEditor ref="designer" publishable-key="lt_pk_test_…" :get-token="getToken" style="height: 720px" />
</template>
Member of editor
design { designId, revision }
release The editor release running
exportHtml(options?) The design as on screen, as HTML to send, with subject, text, mergeTags and warnings
exportPlainText, exportImage, exportPdf, exportZip Plain text, or a PNG, PDF or ZIP kept for you to fetch
getDesign() The design document, to keep your own copy
setTheme(theme) Switch light or dark while open
on(event, listener) Listen for an event; returns a function that stops listening

The same handle in full, with every export's options and results: @lettrove/embed and Getting designs out.

Behaviour you can rely on

  • Server rendering (Nuxt): it renders an empty element, and the editor opens in the browser.
  • Changing props: inline functions and objects may change on every render without reopening the editor. A new publishable-key, design-id, release or set of options opens it again. A new appearance.theme switches the open editor without reopening.
  • An attribute that is not a prop (featurs, say) reaches the editor, which names it: refused with a test key, a warning with a live one. It is never silently lost.
  • Unmounting removes the editor and everything it set up.

Errors

@error receives a LettroveEmbedError with a stable code, a message saying what to fix and a docsUrl. When the editor cannot open, the element shows the same reason instead of an empty box.

Code Usually
options_invalid A prop is wrong; the message names it. With a test key the editor stops, so you catch it while you build
frame_blocked The site is not on the project's allowed sites, or your Content-Security-Policy needs frame-src https://lettrove-embed.com
token_invalid get-token threw, or resolved with something other than the token string
origin_not_allowed The token was minted for a different site than the page's
key_invalid The publishable key is wrong or revoked

Every code: Error codes. What to check first: Troubleshooting.

Versions

@lettrove/vue, @lettrove/embed, @lettrove/react and @lettrove/node share one version number and are published together, so @lettrove/vue@1.4.2 is built for @lettrove/embed@1.4.2. Within 1.x nothing is taken away and no prop changes meaning. Release candidates are published under the next tag and open with test keys only. More in Releases and pinning.

TypeScript

Types are included. The package exports LettroveEditor, LettroveEditorInstance and LettroveEmbedError, and the types of @lettrove/embed: EditorHandle, ExportResult, FileResult, EditorEvents, ErrorCode, ThemeTokens and the rest.

Documentation

The docs for this major version, at docs.lettrove.com:

Support

Questions, problems and security reports: support@lettrove.com.

Licence

MIT, for this package. The Lettrove editor it opens is a hosted service under the Lettrove terms; none of it is in this package.

Related Packages

@email-builder/vue

Vue 3 bindings for the email builder. A thin view layer over @email-builder/engi...

784 0
@naturaldevcr/vue-mail-designer

A visual drag & drop email builder for Vue 3. Exports email-client-compatible HT...

0 0
@templatical/editor

Vue 3 visual drag-and-drop email editor powered by Templatical

160,149 527
@aswin.dev/editor

Vue 3 visual drag-and-drop email editor powered by Templatical

4,314 527
@maildeno/editor

An open-source, framework-agnostic email template editor. Drag-and-drop block ed...

2,752 3

Version History

Version Released Vue License
1.1.0 >=3.3 MIT
1.0.1 >=3.3 MIT
1.0.0 >=3.3 MIT
Pre-releases (3)
Version Released Vue License
1.0.0-rc.1 >=3.3 MIT
1.0.0-rc.0 >=3.3 MIT
0.0.0-stage