Skip to main content

Load & Save Designs

Export the editor's design as JSON, persist it to your backend, and load it back later.

import { useRef } from 'react';
import { PexelizeEditor, PexelizeEditorRef, DesignJson } from '@pexelize/react-editor';

function EmailEditor() {
const editorRef = useRef<PexelizeEditorRef>(null);

const handleSave = async () => {
const design = await editorRef.current?.editor?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
};

const handleLoad = async () => {
const res = await fetch('/api/designs/123');
const { design } = await res.json();
editorRef.current?.editor?.loadDesign(design);
};

return (
<>
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
editorMode="email"
onReady={() => handleLoad()}
/>
<button onClick={handleSave}>Save</button>
</>
);
}
Save JSON, not HTML

Always persist the design JSON from exportJson(). It contains the full editor state (structure, styles, content) and can be loaded back with loadDesign(). HTML is a one-way render — you cannot load HTML back into the editor.

Load a design at init

Pass the design JSON directly as a prop or config option instead of calling loadDesign() manually:

<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
design={savedDesignJson}
/>

Load a blank canvas

Call loadBlank() to reset the editor to an empty design:

editorRef.current?.editor?.loadBlank();

Auto-save with debounce

Listen to design:updated events and debounce to avoid hammering your API:

Debounce auto-save

The design:updated event fires on every keystroke and drag. Without debouncing, you'll send hundreds of requests per minute. Use at least a 1-second debounce.

import { useRef, useCallback } from 'react';
import { PexelizeEditor, PexelizeEditorRef, DesignJson } from '@pexelize/react-editor';

function AutoSaveEditor() {
const editorRef = useRef<PexelizeEditorRef>(null);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();

const handleChange = useCallback(() => {
clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(async () => {
const design = await editorRef.current?.editor?.exportJson();
await fetch('/api/designs/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design }),
});
}, 1000);
}, []);

return (
<PexelizeEditor
ref={editorRef}
editorKey="pk_your_key"
onChange={handleChange}
/>
);
}

Load with validation

Use loadDesignAsync() to get validation feedback when loading a design:

const result = await editorRef.current?.editor?.loadDesignAsync(design);
console.log(`Loaded ${result?.validRowsCount} rows, ${result?.invalidRowsCount} invalid`);
if (result?.errors) {
console.warn('Validation errors:', result.errors);
}

Method reference

MethodReturnsDescription
exportJson()Promise<DesignJson>Export the current design as a JSON object
loadDesign(json, options?)voidLoad a design JSON into the editor
loadDesignAsync(json, options?)Promise<{ success, validRowsCount, invalidRowsCount, errors? }>Load a design with validation feedback
loadBlank(options?)voidReset to an empty canvas
getDesign()Promise<{ html, json }>Get both HTML and JSON in one call
save()voidTrigger the save event (emits save on the event bus)

Next steps