---
title: "Export Options"
description: "How landing pages leave the editor as a JSON definition and rendered HTML, and which options control the output."
url: https://docs.topol.io/landing-page-editor/guide/template-export.html
---

# Export Options

## What a save produces

**Every save produces two artifacts, and both arrive through the save callbacks:**

-   **JSON definition**: the editable template structure. It comes straight from the editor's memory, with no network call. Store it so the page can be loaded back into the editor later with `load()`.
-   **Rendered HTML**: the production-ready page. Rendering happens server-side: the editor sends the template definition to Topol's API and receives the finished HTML back, so HTML export requires a network connection to Topol's services.

Both are handed to your application through the `onSave` and `onSaveAndClose` callbacks, which are passed as top-level properties next to `config`:

```js
const LPE = LandingPageEditor({
  config: TOPOL_OPTIONS,
  onSave: ({ json, html }) => {
    // json = template definition, html = rendered page as a string
    // persist both on your server
  },
  onSaveAndClose: ({ json, html }) => {
    // persist, then tear down the editor UI in your app
  },
});
LPE.render("#landing-page-editor");
```

A save (and therefore an export) can also be triggered programmatically from your application code:

```js
LPE.save();
```

If the rendering request fails, the editor shows an error notification and `onSave` is not called.

## Persisting asynchronously

Both save callbacks **may return a Promise**. The editor keeps its saving state (spinner, disabled button) until the Promise settles, so the user sees the save as finished only once your backend has actually stored the page:

```js
const LPE = LandingPageEditor({
  config: TOPOL_OPTIONS,
  onSave: async ({ json, html }) => {
    const res = await fetch("/api/pages/42", {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ json, html }),
    });
    if (!res.ok) throw new Error(`Save failed: ${res.status}`);
  },
  onSaveAndClose: async ({ json, html }) => {
    await persistPage(json, html); // throws on failure
    closeEditorPanel(); // only reached when persisting succeeded
  },
});
```

-   A **rejected** Promise (or a thrown error) is reported to the user as a save error; for `onSaveAndClose` it also keeps the editor open.
-   A Promise that never settles is released after **30 seconds** with a console warning, so a broken host handler cannot wedge the editor.
-   Returning nothing keeps the previous fire-and-forget behaviour.
-   Without an `onSaveAndClose` handler, _Save & Close_ delivers the payload to `onSave` and then removes the editor iframe.

> **WARNING**
>
> The editor also has a reserved internal property named `export`; it belongs to the iframe plumbing and is unrelated to template export. Use `onSave`/`onSaveAndClose` to receive exported pages.

## `htmlMinified`

The `htmlMinified` option (`boolean`, default `false`) minifies the rendered HTML by removing unnecessary whitespace:

```typescript
{
  htmlMinified: true
}
```

Minified output is smaller but harder to read and debug. The flag applies to preview HTML as well, not only to saved exports.

## Rendering outside the editor

The same rendering service is available as a REST endpoint for producing a page's HTML server-side from a stored JSON definition without opening the editor: [JSON to HTML (secret key)](https://docs.topol.io/landing-page-editor/guide/operations/convertPageJson2Html.html) authenticates with the `X-Secret-Key` header and reports fonts missing from the page, which makes it the right choice for backend jobs. [JSON to HTML (API key)](https://docs.topol.io/landing-page-editor/guide/operations/convertPageToHtml.html) is the endpoint the editor itself calls, authenticated with the public API key and hostname.
