Localess

Visual Editor

Preview and edit content in real time — see every change reflected instantly in your running application without leaving the Localess UI.

The Localess Visual Editor opens your frontend application inside an iframe alongside the content form. As you edit fields on the right, the changes are pushed to the preview on the left in real time. Clicking on any marked element in the preview jumps directly to the corresponding field in the form.

Visual Editor

How it works

  1. Localess renders your app inside an iframe in the left panel of the document editor.
  2. A small sync script loaded by your app opens a message channel to the Localess parent window.
  3. When a field changes in the form, Localess sends an input or change event through the channel.
  4. Your app receives the event, updates its local state, and re-renders — no page reload needed.
  5. Editable elements marked with data-ll-id and data-ll-schema attributes are highlighted so editors can click them to jump to the right field in the form.

Setup

Integrating the Visual Editor requires three steps in your frontend application.

Step 1 — Load the sync script

The sync script must be loaded in the browser. Use the SDK helper or add the script tag manually.

Via @localess/client:

import { loadLocalessSync } from "@localess/client";

// Call once on the client side, e.g. in your root layout or app entry point
loadLocalessSync("https://my-localess.web.app");

Or manually in HTML:

<script
  id="localess-js-sync"
  type="text/javascript"
  async
  src="https://my-localess.web.app/scripts/sync-v1.js"
></script>

Replace https://my-localess.web.app with your Localess instance origin.

Framework-specific SDKs can load the script automatically. Set enableSync: true when registering the provider:

SDKOption
@localess/reactlocalessInit({ enableSync: true })
@localess/angularprovideLocalessBrowser({ enableSync: true })

Step 2 — Mark editable elements

Add data-ll-id and data-ll-schema attributes to the root element of each content block so the Visual Editor can highlight and select it. Add data-ll-field to individual field elements for field-level selection.

Use the helper functions from @localess/client to set these attributes:

import { localessEditable, localessEditableField } from "@localess/client";

// Marks the block root as editable
// Returns: { 'data-ll-id': '...', 'data-ll-schema': '...' }
localessEditable(data)

// Marks a specific field as editable
// Returns: { 'data-ll-field': 'title' }
localessEditableField<MyPage>('title')

React example:

const HeroSection = ({ data, links }) => (
  <section {...localessEditable(data)}>
    <h1 {...localessEditableField<HeroSection>('title')}>{data.title}</h1>
    <p {...localessEditableField<HeroSection>('subtitle')}>{data.subtitle}</p>
  </section>
);

Vue example:

<template>
  <section v-bind="localessEditable(data)">
    <h1 v-bind="localessEditableField('title')">{{ data.title }}</h1>
  </section>
</template>

Svelte example:

<section {...localessEditable(data)}>
  <h1 {...localessEditableField('title')}>{data.title}</h1>
</section>

localessEditable and localessEditableField are no-ops outside the Visual Editor iframe — they return empty objects when the sync script is not active, so they are safe to use in production.


Step 3 — Subscribe to edit events

Listen for input and change events from window.localess and update your application state. Always guard the subscription with a browser check — window.localess only exists when the sync script is loaded inside the Visual Editor iframe.

import { isBrowser } from "@localess/client";

if (isBrowser() && window.localess) {
  window.localess.on(['input', 'change'], (event) => {
    if (event.type === 'input' || event.type === 'change') {
      // Replace your server-fetched content with the live editor data
      setPageData(event.data);
    }
  });
}

The input event fires on every keystroke for a real-time preview. The change event fires when a field value is confirmed. For most use cases, subscribing to both gives the smoothest editing experience.

Events reference

EventWhen it firesPayload
inputWhile a field is being edited (every keystroke){ type: 'input', data: ContentData }
changeWhen a field value is confirmed{ type: 'change', data: ContentData }
saveWhen the document is saved{ type: 'save' }
publishWhen the document is published{ type: 'publish' }
pongHeartbeat response from the editor{ type: 'pong' }
enterSchemaEditor cursor enters a schema block{ type: 'enterSchema', id, schema, field? }
hoverSchemaEditor cursor hovers over a schema block{ type: 'hoverSchema', id, schema, field? }

SDK integrations

Official SDKs provide built-in Visual Editor support with enableSync and helper utilities. For frameworks without a dedicated SDK, use @localess/client directly following the manual setup steps above.

FrameworkSDKGuide
TypeScript / Node@localess/clientTypeScript SDK
Angular@localess/angularAngular SDK
React / Next.js@localess/reactReact SDK
Vue / Nuxt@localess/clientVue
Svelte / SvelteKit@localess/clientSvelte
Astro@localess/clientAstro

On this page