Skip to main content

Getting designs out

Everything your users make can leave Lettrove in seven forms, from your page (the design exactly as on screen) or from your server (the design as last saved).

You wantFrom the pageFrom your server (@lettrove/node)
The HTML to send or publisheditor.exportHtml()lettrove.designs.export(id, { user })
The HTML in pieces, for your own pageexportHtml() → chunksthe same → chunks
Plain texteditor.exportPlainText()designs.export → text
A PDFeditor.exportPdf()designs.export(id, { user, format: 'pdf' })
A PNG pictureeditor.exportImage()designs.export(id, { user, format: 'png' })
A ZIP (HTML, text, images)editor.exportZip()designs.export(id, { user, format: 'zip' })
The design itself, to keepeditor.getDesign()lettrove.designs.get(id, { user })

Each mode offers what makes sense for it: an email all of them, a popup no PDF. Every export is recorded, and the images it shows are marked as sent, so they are never deleted.

HTML: exportHtml()​

const out = await editor.exportHtml({
merge: { contact: { first_name: 'Ada' }, unsubscribeUrl: 'https://acme.com/u/123' }, // optional
text: { links: true, images: true, preheader: false }, // optional
});
Field
htmlThe whole HTML document, minified, ready to send or host
chunks{ body, css, js, fonts } — the same HTML in pieces to place inside your own page (Landing page, Popup)
textThe plain-text version
subject, preheaderAn email's subject and preheader, merged the same way
mergeTagsMerge tags still in it, exactly as written — fill them before it goes to anyone
warningsAnything an inbox would do to it that you should know, e.g. Gmail clipping past ~102 KB
bytesThe HTML's size
modeemail, page, popup or document
designId, revisionWhich design, and the saved revision the screen was based on
exportIdThis export's record, for your logs and for support
rendererVersionThe renderer that made it
designThe design document, to keep (what you may rely on)

Without merge, every merge tag stays exactly as written — handy when your own email service fills them. See Merge tags.

An image your user pasted straight into the design (not uploaded) is uploaded on the way out, so the HTML only ever points at https:// images: inboxes drop embedded ones.

Plain text: exportPlainText()​

const { text } = await editor.exportPlainText({
links: true, // write each link's address beside its label (default true); false keeps labels, drops buttons
images: true, // speak each image by its alt text (default true)
preheader: false,// start with the preheader (default false)
merge: { contact: { first_name: 'Ada' } }, // optional, as for exportHtml
});

Send it as the text/plain part beside the HTML: inboxes that do not show HTML show this, and spam filters like to see both.

Files: exportPdf(), exportImage(), exportZip()​

const pdf = await editor.exportPdf();
const png = await editor.exportImage({ fullPage: true }); // false: the first screen only
const zip = await editor.exportZip();

Each resolves with the same shape:

{
"url": "https://…/q3-proposal.pdf",
"filename": "q3-proposal.pdf",
"format": "pdf",
"bytes": 48213,
"expiresAt": null,
"warnings": [],
"exportId": "01J9ZR…",
"designId": "01J9ZQ3W8D2K7M5T1V4XG6HB0R",
"revision": 7,
"mode": "document",
"design": { }
}

Fetch the file from url. expiresAt is null while the file is kept; read it rather than assume it, since how long files are kept may change.

The url is long and unguessable, and works without a key for anyone who has it, as a link to a file on a CDN does. Hand it only to whoever should have the file, or download the file to your own storage and share that.

FormatWhat is in it
PDFA document on its own paper, with header, footer and page numbers. Any other design on A4.
PNGThe design drawn as a picture, the whole length (fullPage: true, the default) or the first screen
ZIPindex.html, the plain text, the images Lettrove hosts for it, and a short README. Images hosted elsewhere stay as links.

All three take merge too.

The design itself: getDesign()​

const { designId, revision, design } = await editor.getDesign();
await myDb.saveCopy(designId, design); // keep it as it is

The design is yours to keep. Store it as it is and hand it back to render it on your server (lettrove.render({ doc: design })) — see Keeping your own copy.

From your server​

import { Lettrove } from '@lettrove/node';
const lettrove = new Lettrove({ secretKey: process.env.LETTROVE_SECRET_KEY });

// HTML (and text, chunks, subject…) — the same fields as exportHtml
const email = await lettrove.designs.export(designId, { user: { id: userId }, merge: { contact } });

// A file
const pdf = await lettrove.designs.export(designId, { user: { id: userId }, format: 'pdf' });
const png = await lettrove.designs.export(designId, { user: { id: userId }, format: 'png', fullPage: false });

The server exports the design as last saved; the page exports it as on screen. For the same saved design, both give the same HTML.

In the editor: the Download menu​

Your users can download the same files themselves from the Download menu in the editor's bar. To hide it (because your product handles files), pass features: { download: false }; your code can still export.