unlayer-integration について
React、Vue、Angular、またはプレーン JavaScript のアプリに Unlayer エディターを組み込むための開発スキルです。フレームワーク別のアクセス方法、初期設定、複数インスタンスの扱いを説明します。
主な機能
- 01React、Vue、Angular 用ラッパー
- 02プレーン JavaScript での組み込み
- 03フレームワーク別のエディターアクセス
- 04デザインの保存と読み込みパターン
- 05createEditor() による複数インスタンス
活用シーン
- 01Web アプリへのメールビルダー組み込み
- 02編集可能なデザインの読み込みと保存
- 03メール用と Web 用のエディターを別々に実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ unlayer/ unlayer-skills --skill unlayer-integrationインストール後、Claude Code で/unlayer-integrationを入力して読み込まれたか確認します。
詳細
Unlayer Editor の統合
概要
Unlayer は、React、Vue、Angular 用の公式ラッパーと、プレーン JavaScript 用の埋め込み機能を提供しています。すべてのラッパーで基盤となる API は共通で、異なるのはエディターへのアクセス方法だけです。
このスキルでは、メール、ページ、ポップアップ、ドキュメントのビルダーを扱います。スタンドアロンの Image Editor または
@unlayer/react-image-editor を使用する場合は、unlayer-image-editor を使用してください。
どのフレームワークを使うか
| フレームワーク | パッケージ | インストール | エディターへのアクセス |
|---|---|---|---|
| React | react-email-editor | npm i react-email-editor | useRef<EditorRef> → ref.current?.editor |
| Vue | vue-email-editor | npm i vue-email-editor | this.$refs.emailEditor.editor |
| Angular | angular-email-editor | npm i angular-email-editor | @ViewChild → this.emailEditor.editor |
| プレーン JS | CDN スクリプトタグ | <script> 埋め込み | グローバル unlayer オブジェクト |
⚠️ Unlayer のパッケージをインストールする前に、バージョンが npm に存在することを確認してください。
npm view react-email-editor version # 最新の公開バージョンを確認確認していないバージョン番号を指定しないでください。最新バージョンを取得するには、バージョンを指定せずに
npm install <package> --saveを実行するか、利用可能なすべてのバージョンを確認するにはnpm view <package> versions --jsonを実行してください。
React(完全な動作例)
npm install react-email-editor --save
import React, { useRef, useState } from 'react';
import EmailEditor, { EditorRef, EmailEditorProps } from 'react-email-editor';
const EmailBuilder = () => {
const emailEditorRef = useRef<EditorRef>(null);
const [saving, setSaving] = useState(false);
// Save design JSON + export HTML to your backend
const handleSave = () => {
const unlayer = emailEditorRef.current?.editor;
if (!unlayer) return;
setSaving(true);
unlayer.exportHtml(async (data) => {
try {
const response = await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
design: data.design, // Save this — needed to edit later
html: data.html, // The rendered HTML output
}),
});
if (!response.ok) throw new Error('Save failed');
console.log('Saved successfully');
} catch (err) {
console.error('Save error:', err);
} finally {
setSaving(false);
}
});
};
// Load a saved design when editor is ready
const onReady: EmailEditorProps['onReady'] = async (unlayer) => {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
unlayer.loadDesign(saved.design); // Pass the saved design JSON
}
} catch (err) {
console.log('No saved design, starting blank');
}
};
return (
<div>
<button onClick={handleSave} disabled={saving}>
{saving ? 'Saving...' : 'Save'}
</button>
<EmailEditor
ref={emailEditorRef}
onReady={onReady}
options={{
projectId: 123456, // Dashboard > Project > Settings
displayMode: 'email',
}}
/>
</div>
);
};
export default EmailBuilder;
バックエンドで受け付け、返す必要があるもの:
// POST /api/templates — save
{ design: object, html: string }
// GET /api/templates/:id — load
{ design: object, html: string, updatedAt: string }
React の Props:
| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
options | Object | {} | すべての unlayer.init() オプション(projectId、displayMode など) |
tools | Object | {} | ツールごとの設定 |
appearance | Object | {} | テーマとパネルの設定 |
onReady | Function | — | エディターの準備完了時に呼び出されます(unlayer インスタンスを受け取ります) |
onLoad | Function | — | iframe の読み込み時に呼び出されます(準備完了前) |
style | Object | {} | コンテナーのインラインスタイル |
minHeight | String | '500px' | エディターの最小の高さ |
ドキュメント:https://docs.unlayer.com/builder/react-component GitHub:https://github.com/unlayer/react-email-editor
Vue(完全な動作例)
npm install vue-email-editor --save
<template>
<div id="app">
<button v-on:click="handleSave" :disabled="saving">
{{ saving ? 'Saving...' : 'Save' }}
</button>
<EmailEditor ref="emailEditor" v-on:load="editorLoaded" />
</div>
</template>
<script>
import { EmailEditor } from 'vue-email-editor';
export default {
components: { EmailEditor },
data() {
return { saving: false };
},
methods: {
async editorLoaded() {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
this.$refs.emailEditor.editor.loadDesign(saved.design);
}
} catch (err) {
console.log('No saved design, starting blank');
}
},
handleSave() {
this.saving = true;
this.$refs.emailEditor.editor.exportHtml(async (data) => {
try {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
} catch (err) {
console.error('Save error:', err);
} finally {
this.saving = false;
}
});
},
},
};
</script>
Props: minHeight、options、tools、appearance、locale、projectId。
ドキュメント:https://docs.unlayer.com/builder/vue-component GitHub:https://github.com/unlayer/vue-email-editor
Angular(完全な動作例)
npm install angular-email-editor --save
モジュール(app.module.ts):
import { EmailEditorModule } from 'angular-email-editor';
@NgModule({ imports: [EmailEditorModule] })
export class AppModule {}
コンポーネント(app.component.ts):
import { Component, ViewChild } from '@angular/core';
import { EmailEditorComponent } from 'angular-email-editor';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
@ViewChild(EmailEditorComponent)
private emailEditor: EmailEditorComponent;
saving = false;
async editorLoaded() {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
this.emailEditor.editor.loadDesign(saved.design);
}
} catch (err) {
console.log('No saved design');
}
}
handleSave() {
this.saving = true;
this.emailEditor.editor.exportHtml(async (data) => {
try {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
} catch (err) {
console.error('Save error:', err);
} finally {
this.saving = false;
}
});
}
}
テンプレート(app.component.html):
<div>
<button (click)="handleSave()" [disabled]="saving">
{{ saving ? 'Saving...' : 'Save' }}
</button>
<email-editor (loaded)="editorLoaded($event)"></email-editor>
</div>
プレーン JavaScript
<script src="https://editor.unlayer.com/embed.js"></script>
<div id="editor-container" style="height: 700px;"></div>
<script>
unlayer.init({
id: 'editor-container',
projectId: 1234,
displayMode: 'email',
});
unlayer.addEventListener('editor:ready', async function () {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
unlayer.loadDesign(saved.design);
}
} catch (err) {
console.log('Starting blank');
}
});
function handleSave() {
unlayer.exportHtml(async function (data) {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
});
}
</script>
複数のエディターインスタンス
init() の代わりに createEditor() を使用します。
const editor1 = unlayer.createEditor({ id: 'email-editor', displayMode: 'email' });
const editor2 = unlayer.createEditor({ id: 'web-editor', displayMode: 'web' });
editor1.loadDesign(emailDesign);
editor2.loadDesign(webDesign);
よくある間違い
| 間違い | 修正方法 |
|---|---|
| コンテナーが小さすぎる | 最小サイズは幅 1024px x 高さ 700pxです。エディターはコンテナーいっぱいに表示されます。 |
| 準備完了前にメソッドを呼び出す | 必ず editor:ready イベントまたは onReady コールバックを待ってください |
複数のエディターに init() を使用する | 代わりに unlayer.createEditor() を使用してください |
projectId がない | Dashboard > Project > Settings から取得してください |
| HTML だけを保存し、デザイン JSON を保存しない | 必ず両方保存してください。デザイン JSON があれば、ユーザーは後から編集できます |
| 保存中の読み込み状態がない | 二重保存を防ぐため、保存ボタンを無効にしてください |
| 存在しないパッケージバージョンを指定する | バージョンを指定する前に npm view <package> version を実行して確認してください。最新バージョンを取得するには、バージョンを指定せずに npm install <package> --save を使用してください。 |
トラブルシューティング
| エラー | 原因 | 解決方法 |
|---|---|---|
| エディターに白い空白が表示される | コンテナーの div の高さが 0 になっています | 明示的に高さを設定します:min-height: 700px |
editor:ready が発火しない | スクリプトが読み込まれていないか、id が正しくありません | id が既存の div と一致していることを確認し、ネットワークタブで embed.js を確認します |
ref.current?.editor が undefined になる | マウント前にアクセスしています | onReady コールバック内でのみ使用します |
| デザインが読み込まれない | JSON の形式が不正です | JSON を検証し、schemaVersion フィールドを確認します |