community-sdks / unlayer-livewire
Livewire wrapper for the unofficial Unlayer Alpine.js SDK.
Package info
github.com/community-sdks/unlayer-livewire
pkg:composer/community-sdks/unlayer-livewire
Requires
- php: ^8.2
- illuminate/http: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- livewire/livewire: ^3.0|^4.0
Requires (Dev)
- laravel/pint: ^1.24
README
Livewire wrapper for @community-sdks/unlayer-alpinejs, which wraps @community-sdks/unlayer-ts.
This package gives Laravel apps a Livewire component for the Unlayer editor while keeping the editor lifecycle in the TypeScript SDK and Alpine adapter.
Version Compatibility
@community-sdks/unlayer-livewireuses@community-sdks/unlayer-alpinejsand@community-sdks/unlayer-tsinternally.- Keep the published browser asset in sync by running the package install command again after upgrading the package.
Getting Started
Install the PHP package:
composer require community-sdks/unlayer-livewire
Install the browser asset:
php artisan unlayer-livewire:install
This publishes the compiled browser file to:
public/unlayer-livewire.js
After upgrading the package or rebuilding the browser asset locally, publish the new file again:
php artisan vendor:publish --tag=unlayer-livewire-assets --force
If you want to customize upload storage, publish the config file too:
php artisan unlayer-livewire:install --config
To overwrite previously published files:
php artisan unlayer-livewire:install --force
You can also publish assets or config manually:
php artisan vendor:publish --tag=unlayer-livewire-assets --force php artisan vendor:publish --tag=unlayer-livewire-config
Basic Usage
Use the Livewire component anywhere in a Blade view:
<livewire:unlayer-livewire.editor :state="$content" display-mode="email" height="720px" />
state is an array with this shape:
[
'html' => '',
'design' => [],
]
Cast your model column to an array:
protected function casts(): array { return [ 'content' => 'array', ]; }
Examples
Laravel-ready example snippets are included in this repository:
examples/routes/web.php.stub examples/views/basic.blade.php examples/views/templates.blade.php
Copy the example routes into your app's routes/web.php, then copy the example views into resources/views/unlayer-livewire-examples/.
The basic example renders the editor with an empty state. The template example enables the built-in picker UI and the same-origin Laravel template proxy.
Stock Templates
Template search and loading comes from the underlying TypeScript SDK and works through the Alpine adapter. Unlayer's public stock template search endpoint does not allow browser CORS requests, so this package includes Laravel proxy routes:
GET /unlayer-livewire/templates
GET /unlayer-livewire/templates/{template}
These are same-origin relative URLs. For example, /unlayer-livewire/templates becomes https://your-app.test/unlayer-livewire/templates.
If you replace the built-in template client with a backend on another domain, use full URLs and make sure that backend allows CORS for your frontend domain.
The browser calls these same-origin routes, and Laravel calls Unlayer from the backend. You can pass default filters and enable the built-in editor tab:
<livewire:unlayer-livewire.editor :state="$content" :template-search="[ 'search' => 'newsletter', 'type' => 'email', 'premium' => false, 'limit' => 20, 'offset' => 0, 'collection' => '', 'sort' => 'recent', ]" :template-picker="[ 'showTrigger' => true, 'triggerLabel' => 'Templates', ]" />
You can customize the route prefix and middleware in config/unlayer-livewire.php:
'routes' => [ 'prefix' => 'unlayer-livewire', 'middleware' => ['web'], ],
The template trigger is shown in a small toolbar above the editor. The picker opens over the editor itself, without a page backdrop.
Behind the proxy, /unlayer-livewire/templates calls:
POST https://unlayer.com/templates/search Content-Type: application/json
The Livewire template-search values map to Unlayer's request body:
search -> filter.name type -> filter.type premium -> filter.premium, "true" when true, "" when false limit -> perPage offset -> page, calculated as floor(offset / limit) + 1 collection -> filter.collection sort -> filter.sortBy
Example upstream body:
{
"page": 1,
"perPage": 20,
"filter": {
"premium": "",
"collection": "",
"name": "newsletter",
"sortBy": "recent",
"type": "email"
}
}
Template thumbnails use https://api.unlayer.com/v2/stock-templates/{slug}/thumbnail?width=500.
/unlayer-livewire/templates/{template} loads the design through:
POST https://studio.unlayer.com/api/v1/graphql
Using StockTemplate(slug: $slug) { StockTemplatePages { design } }.
The Alpine component exposes:
mount() isReady() getState() setState(state) loadDesign(design) exportState() searchTemplates(options) refreshTemplates() loadTemplate(slug) chooseTemplate(templateOrSlug) openTemplates() closeTemplates() setTemplateSearch(search)
When templatePicker is enabled, the built-in picker UI from @community-sdks/unlayer-ts is mounted inside the editor surface. The Livewire wrapper delegates to the updated Alpine adapter for opening, closing, and refreshing that picker.
Livewire Methods
The PHP Livewire component exposes:
setState(array $state): void loadDesign(array $design): void clear(): void exported(array $state): void resolveUploadedImage(string $temporaryFilename): string
Uploads
Image uploads use Livewire's JavaScript upload API. The editor uploads a file to the component property imageUpload, then calls resolveUploadedImage() to store it and return the public URL.
Configure storage in config/unlayer-livewire.php:
return [ 'upload' => [ 'disk' => 'public', 'path' => 'unlayer-livewire', 'visibility' => 'public', ], ];
Make sure your public disk is linked:
php artisan storage:link
Development
Build the browser adapter:
npm install npm run build
Republish the built asset into a Laravel app:
php artisan vendor:publish --tag=unlayer-livewire-assets --force
Run TypeScript checks:
npm run typecheck
Format PHP:
vendor/bin/pint
License
MIT