PluginPlatform guides
Laravel
A route that signs the authenticated user and a Blade view that renders the editor iframe.
Laravel renders on the server, so a single route can sign the user and pass the finished URL to a Blade view. The secret stays in .env and config/services.php.
Before you start
Follow the first three steps of the quickstart: create a plugin, add localhost:8000 to its allowed domains, and copy the Plugin ID and Secret.
Configuration
MAILEDITOR_PLUGIN_ID=9f3c1e7a-4b21-4c8e-9a77-1d2f5b6c8e10
MAILEDITOR_PLUGIN_SECRET=your_plugin_secret
MAILEDITOR_EDITOR_BASE_URL=https://maileditor.net
MAILEDITOR_PLUGIN_VERSION=1.0.0'maileditor' => [
'plugin_id' => env('MAILEDITOR_PLUGIN_ID'),
'plugin_secret' => env('MAILEDITOR_PLUGIN_SECRET'),
'editor_base_url' => env('MAILEDITOR_EDITOR_BASE_URL', 'https://maileditor.net'),
'plugin_version' => env('MAILEDITOR_PLUGIN_VERSION', '1.0.0'),
],Reading through config() rather than env() in the route keeps php artisan config:cache working.
Sign on the server
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/editor', function (Request $request) {
$userId = 'user-' . $request->user()->id;
$expires = time() + 300;
$payload = sprintf('v1|%d:%s|%d', strlen($userId), $userId, $expires);
$signature = hash_hmac('sha256', $payload, config('services.maileditor.plugin_secret'));
$query = http_build_query([
'external_user_id' => $userId,
'identity_expires' => $expires,
'identity_signature' => $signature,
'plugin_version' => config('services.maileditor.plugin_version'),
]);
$src = config('services.maileditor.editor_base_url')
. '/plugin-editor/v1/' . config('services.maileditor.plugin_id')
. '?' . $query;
return view('editor', ['src' => $src]);
})->middleware('auth');The auth middleware guarantees $request->user() is set. PHP's strlen counts bytes, which is what the payload requires.
Render the iframe
<iframe
src="{{ $src }}"
title="Email editor"
allow="clipboard-write; fullscreen"
style="width: 100%; height: 100vh; border: 0"
></iframe>Blade escapes & to & inside the attribute, which the browser decodes back before loading the URL.
Next steps
- Add
template_idto the query to open one of the user's saved templates. See Embedding the editor. - If the iframe shows "Plugin editor unavailable", read
result.errorin thesessionresponse. See Error codes.

.png)