---
title: "NPM & Frameworks"
description: "Integrate the Topol Landing Page Editor through the official @topol.io/editor NPM packages, with dedicated components for React and Vue."
url: https://docs.topol.io/landing-page-editor/guide/npm-integration.html
---

# NPM Package Integration

The [Getting Started](https://docs.topol.io/landing-page-editor/guide/getting-started.html) guide embeds the editor with a plain `<script>` tag. In a project built around a bundler or a component framework, the **official NPM packages** do the same job with proper TypeScript types and lifecycle handling. The editor script is loaded for you, and in React and Vue the editor mounts and tears down together with the component that holds it.

> **Create your API token first**
>
> The packages wrap the editor, not the authorization. The editor still needs the **Public API key** from [Step 1 in Getting Started](https://docs.topol.io/landing-page-editor/guide/getting-started.html#step-1-create-your-api-token).

| Package | Framework |
| --- | --- |
| [`@topol.io/editor`](https://www.npmjs.com/package/@topol.io/editor) | Plain JavaScript or TypeScript |
| [`@topol.io/editor-react`](https://www.npmjs.com/package/@topol.io/editor-react) | React |
| [`@topol.io/editor-vue`](https://www.npmjs.com/package/@topol.io/editor-vue) | Vue 3 |

Landing Page Editor support ships in the **v1 alpha** of these packages, published under the `alpha` tag on npm:

**JS / TS**

```bash
npm install @topol.io/editor@alpha
```

**React**

```bash
npm install @topol.io/editor-react@alpha
```

**Vue**

```bash
npm install @topol.io/editor-vue@alpha
```

> **v1 is in alpha**
>
> The v1 packages are an early pre-release. We do not expect major changes to the API before the final release, but details can still move. Pin the exact version you integrate against and read the changelog before upgrading. The `@topol.io/editor-svelte` package does not include the Landing Page Editor yet.

> **Let an AI agent do the wiring**
>
> [TOPOL-io/skills](https://github.com/TOPOL-io/skills) has two skills for coding agents, written as plain markdown. `topol-editor-integration` sets up either editor in a new project and `topol-v1-upgrade` moves an existing integration from 0.x to v1. They install as a Claude Code plugin (`/plugin marketplace add TOPOL-io/skills`) or into any agent with `npx skills@latest add TOPOL-io/skills`.

All packages take the same configuration as the script-tag integration: options go under `config`, callbacks are top-level properties. Everything documented in [Editor Options](https://docs.topol.io/landing-page-editor/reference/topol-options.html) applies unchanged.

## JavaScript / TypeScript

`@topol.io/editor` exports a `LandingPageEditor` object with an async `init()` method. It loads the editor script, creates an instance, and resolves with it. The resolved instance is the same one the global `LandingPageEditor()` factory returns, with an added `destroy()` method for cleanup:

```typescript
import { LandingPageEditor } from "@topol.io/editor";

const editor = await LandingPageEditor.init({
  config: {
    authorize: {
      apiKey: "YOUR_API_KEY", // Public API key from your Topol account
      userId: "user-123", // Any unique ID for your user
    },
  },
  onSave({ json, html }) {
    // `json` is the template definition, `html` the rendered page
    console.log("Saved landing page:", json, html);
  },
  onInit() {
    console.log("Landing Page Editor is ready");
  },
});

// Render the editor into a container element
editor.render("#landing-page-editor");

// Optionally load a template
editor.load(templateJson);

// Clean up when the editor is no longer needed
editor.destroy();
```

Two differences from the script-tag integration:

-   `init()` is **asynchronous**. It resolves once the editor script has loaded, and rejects if loading fails.
-   The instance has a **`destroy()`** method that removes the editor and cleans up its resources. Call it when navigating away from the page that hosts the editor.

The container element works the same as in the script-tag setup, and still needs an explicit width and height:

```html
<div id="landing-page-editor" style="width: 100%; height: 100vh;"></div>
```

## React

`@topol.io/editor-react` exports a `LandingPageEditor` component. It renders its own container, initializes the editor on mount, and destroys it on unmount. Callbacks are passed as props, and programmatic control (`load`, `save`) goes through a ref:

```tsx
import { useRef } from "react";
import {
  LandingPageEditor,
  type LandingPageEditorRef,
  type IReactLandingPageOptions,
} from "@topol.io/editor-react";

const options: IReactLandingPageOptions = {
  authorize: {
    apiKey: "YOUR_API_KEY",
    userId: "user-123",
  },
};

export default function PageBuilder() {
  const editorRef = useRef<LandingPageEditorRef>(null);

  const loadTemplate = (template: unknown) => {
    editorRef.current?.load(template);
  };

  return (
    <LandingPageEditor
      ref={editorRef}
      options={options}
      onSave={({ json, html }) => {
        console.log("Saved landing page:", json, html);
      }}
      onLoaded={() => {
        // A good place to call editorRef.current?.load(template)
      }}
    />
  );
}
```

Notes:

-   The `options` prop takes the contents of `config` directly (the component wraps it for you).
-   The component renders an absolutely positioned container that fills its parent (`100%` width, `100vh` height), so place it inside a positioned wrapper sized to where the editor should appear.
-   The ref exposes `load(template)` and `save()`; unmounting the component destroys the editor.
-   Every editor callback is available as a prop: `onSave`, `onSaveAndClose`, `onLoaded`, `onInit`, `onEditorClose`, `onPreview`, `onAlert`, `onEditorError`, and the rest of the [callback set](https://docs.topol.io/landing-page-editor/reference/topol-options.html#callbacks-reference). Each receives the same single payload object as in the script-tag integration.

## Vue

`@topol.io/editor-vue` exports a `LandingPageEditor` component for Vue 3. Configuration goes into the `options` prop, callbacks arrive as events, and `load`/`save` are exposed on the template ref:

```vue
<script setup lang="ts">
import { ref } from "vue";
import {
  LandingPageEditor,
  type IVueLandingPageOptions,
} from "@topol.io/editor-vue";

const options: IVueLandingPageOptions = {
  authorize: {
    apiKey: "YOUR_API_KEY",
    userId: "user-123",
  },
};

const editorRef = ref<InstanceType<typeof LandingPageEditor> | null>(null);

const handleSave = ({ json, html }: { json: unknown; html: unknown }) => {
  console.log("Saved landing page:", json, html);
};

const loadTemplate = (template: unknown) => {
  editorRef.value?.load(template);
};
</script>

<template>
  <LandingPageEditor
    ref="editorRef"
    :options="options"
    @on-save="handleSave"
    @on-loaded="loadTemplate(myTemplate)"
  />
</template>
```

Notes:

-   Events carry the same single payload object as the callbacks: `@on-save` receives `{ json, html }`, `@on-alert` receives `{ notification }`, and so on.
-   Event names follow Vue conventions: `onSave` becomes `@on-save`, `onLoaded` becomes `@on-loaded`, and so on.
-   The component destroys the editor automatically before it unmounts.

## TypeScript support

All three packages are written in TypeScript and export the Landing Page Editor types:

```typescript
import type {
  ILandingPageOptions, // full init() argument: { config, ...callbacks }
  ILandingPageCallbacks, // just the callback signatures
  ILandingPageEditorInstance, // render / load / save / destroy
  TopolSection, // block payload used by onBlockSave
} from "@topol.io/editor";
```

The framework packages re-export these, plus their own component types (`IReactLandingPageOptions`, `LandingPageEditorRef` in React; `IVueLandingPageOptions` in Vue).

## Next steps

-   Configure the editor with [Editor Options](https://docs.topol.io/landing-page-editor/reference/topol-options.html)
-   Control it programmatically with the [instance methods](https://docs.topol.io/landing-page-editor/reference/topol-plugin.html)
-   Migrating from the 0.x packages: [NPM Packages: Upgrading from 0.x to v1](https://docs.topol.io/email-editor/guide/npm-v1-migration.html) lists everything that changed.
-   The Landing Page Editor lives in the same packages as a named export next to `EmailEditor`, so one install covers both editors.

> **INFO**
>
> Running into trouble while integrating the NPM package? **Contact our support team** [here](https://topol.io/contact) and we'll help you get it working.
