Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dropblockeditor Laravel Package

jeffreyvr/dropblockeditor

Dropblockeditor is a customizable block-based editor for Laravel apps, featuring drag-and-drop content blocks, image uploads, and JSON storage. It integrates with Blade and Tailwind CSS, making flexible page building and rich content editing simple without a complex CMS.

View on GitHub
Deep Wiki
Context7

Getting Started

jeffreyvr/dropblockeditor is a Laravel block editor (Livewire + Alpine based) for authoring JSON-structured content and rendering it back through Blade views. Version 0.4.0 is the Laravel 11 compatibility release — no new end-user features — so install it as composer require jeffreyvr/dropblockeditor:^0.4 on Laravel 11 (or ^0.3 on Laravel 10).

Minimal path to a working editor:

  1. Publish config and assets, then check config/dropblockeditor.php for asset/route settings:
    php artisan vendor:publish --provider="Jeffreyvr\Dropblockeditor\DropblockeditorServiceProvider"
    
  2. Add a nullable json (or longtext) content column and cast it in the model: protected $casts = ['content' => 'array'];.
  3. Create one block: a PHP block class (input name, optional validation rules, form view, render view) plus the two Blade partials. Start with a plain text block.
  4. Register your blocks in an Editor class (extends the package's Editor) that returns the block classes available for that resource.
  5. Drop the Livewire editor component into a form, bind its value to your model property, save, then render the stored JSON by looping blocks and switching on block type to a render partial.

Where to look first: the package src/ directory (Editor, Blocks/Block, the Livewire component), resources/views for the editor shell, the config file, and any stub block shipped with the publish command. Those four define everything you will touch.

First use case: a "Page" resource with a text block and a heading block, edited in an admin form and rendered on the frontend. Get that end-to-end before adding media or nested blocks.

Implementation Patterns

One block class per content type. Keep the editing form view and the frontend render view as separate files (e.g. blocks.text.form / blocks.text.render). The form view is admin-only and can use Livewire bindings; the render view must be plain, server-side Blade with no Livewire dependency.

Per-resource Editor classes. Rather than one global editor, define PageEditor, PostEditor, etc., each returning its own block list. That keeps the block picker tight and stops content authors from pasting a block into a resource whose renderer doesn't handle it.

Store JSON, render by type. Cast the column to array, then render with a mapping loop and a whitelist:

@foreach ($page->content ?? [] as $block)
    @switch($block['type'])
        @case('text')
            <x-blocks.text :data="$block" />
            @break
        @case('heading')
            <x-blocks.heading :data="$block" />
            @break
    @endswitch
@endforeach

Never @include a view name taken straight from the stored JSON — that is a template-injection vector.

Wrap rendering in a Blade component. A <x-block-content :content="$model->content" /> component hides the switch statement and gives you one place to add block types, fallbacks for unknown types, and empty-state handling.

Livewire form integration. Wrap the editor in your normal Livewire CRUD form and treat its content property like any other field: validate on save(), then persist. If you use a plain Blade form (no Livewire), post the JSON through a hidden input and json_decode server-side.

Nested/child blocks. If your block form supports children, store them as a nested children array and make the render partial recursive. Keep depth capped in validation — recursive rendering of user-supplied JSON is a denial-of-service risk otherwise.

Media and relations. For image/file blocks, persist the storage disk path or model ID in the block data, not a rendered URL, so you can swap disks/CDNs later. Resolve URLs at render time.

Gotchas and Tips

0.x semver means breaking changes ship in minor bumps. There is nothing to migrate from 0.3.1 to 0.4.0 beyond the Laravel 11 support, but pin ^0.4 and read the changelog before every upgrade. Staying on Laravel 10? There is no reason to upgrade yet.

Livewire version alignment is the most common install failure. Laravel 11 implies Livewire 3; an old Livewire 2 install will throw JS errors and broken block interactions. Check the package's composer.json constraint against your livewire/livewire version before debugging anything else.

Re-publish assets after upgrading. After composer update, run php artisan vendor:publish --force (watch that --force doesn't overwrite your customised views — publish to a backup first) and then php artisan view:clear. Stale published JS against new PHP is a classic silent breakage.

Null content is the most frequent runtime error. Pass [] (not null) into the editor and the renderer. Cast with a default: $page->content ?? [].

CSS collisions in the admin. The editor styles can fight your app's Tailwind build. Keep the published editor CSS scoped to the admin layout rather than the global stack, and avoid double-loading Alpine (Livewire 3 already ships it) — double Alpine causes blocks that render but never respond.

Sanitise block HTML. Rich-text blocks store markup. Escape by default, and if you must output raw HTML, run it through a purifier. Validation rules on the block class protect the editor, not your frontend.

Preview endpoints need auth. If you add a preview route (a common pattern: render unsaved JSON via a controller), put it behind your admin middleware — it's an arbitrary-block-render endpoint otherwise.

Testing. Don't try to drive the editor UI in tests. Assert two things: the block class validation rules, and the render output for a fixture JSON array. Blade component tests ($this->blade('<x-block-content :content="$json" />')) cover the risky half cheaply.

Extension points. Customise by subclassing Editor, adding block classes, and overriding published views — not by editing vendor/. If the package doesn't expose a hook you need, prefer wrapping it in your own Blade component over forking; at 0.x, a fork will drift fast.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource