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

Nova Gutenberg Laravel Package

jangvel/nova-gutenberg

A Laravel Nova field package that brings the Gutenberg block editor into Nova, letting you build and manage rich, block-based content directly in your admin panel with a familiar WordPress-style editing experience.

View on GitHub
Deep Wiki
Context7

Getting Started

This package wraps Laraberg (a Gutenberg/WordPress block editor port) as a Nova Field. Because it depends on Laraberg, most setup friction comes from Laraberg, not from this package.

  1. Install Laraberg first (it supplies the JS/CSS and migrations):

    composer require vanjaro/laraberg
    php artisan vendor:publish --provider="Vanjaro\Laraberg\LarabergServiceProvider"
    php artisan migrate
    

    This creates the laraberg_contents table used for block/media metadata.

  2. Install this field:

    composer require jangvel/nova-gutenberg
    
  3. Add a column on the model being edited. Content is stored as raw Gutenberg HTML (with block delimiters like <!-- wp:paragraph -->), so a longText/longtext column is appropriate:

    $table->longText('content')->nullable();
    
  4. Reference it in the Nova resource:

    use Jangvel\NovaGutenberg\Gutenberg;
    
    public function fields(Request $request)
    {
        return [
            Gutenberg::make('Content', 'content'),
        ];
    }
    

First use case: give editors a WYSIWYG/block editor on a Page or Post model, then render the saved HTML unescaped on the frontend ({!! $page->content !!}) after sanitizing.

Look first at: the package's src/ (usually one Field class + a compiled Vue component), then Laraberg's README for asset/migration quirks, then your config/laraberg.php.

Implementation Patterns

Basic page/post editor. The happy path is a single Gutenberg field on a resource backed by a longText column. On save, Laraberg serializes blocks back to the standard Gutenberg HTML format. On detail view, Nova may not render this read-only well — often you suppress the detail view and render the HTML on the public site instead:

Gutenberg::make('Content', 'content')
    ->hideFromDetail()
    ->rules('nullable', 'string');

Rendering on the frontend. Since content is HTML with block comments, do not {{ }}-escape it. Wrap it with a sanitizer (e.g. mews/purifier or symfony/html-sanitizer) before output:

{!! clean($page->content) !!}

Media handling. Laraberg can store uploaded media in laraberg_media if you enable it; otherwise use a plain URL/attachment block. For Nova projects I generally recommend keeping media in your own Media model via a separate File/Image field and letting the Gutenberg block pick from a URL — avoids two media systems fighting each other.

Reusable blocks / block templates. Laraberg supports registering custom blocks via its JS API. Add a small Nova tool or Nova::script() call to register block scripts so they load in the editor:

// NovaServiceProvider::boot
Nova::script('gutenberg-custom-blocks', __DIR__.'/../dist/js/blocks.js');

Multiple fields on one resource. You can put two Gutenberg fields on one resource (e.g. summary and body), but each must map to its own longText column — Laraberg keyed content is not per-field. Keep block IDs unique by not sharing content across fields.

Seeding & fixtures. Laraberg content is just strings — you can seed with file_get_contents(resource_path('stubs/page.html')) where the file contains valid Gutenberg markup. Good for demos; also makes round-trip tests easy.

Integration with existing editors. If you're migrating from a Markdown or Trix field, convert on save once (Markdown → HTML → wrap in <!-- wp:html -->), then let editors continue in Gutenberg. Don't try to sync both editors live — you'll get divergent serializations.

Gotchas and Tips

  • Nova compatibility drift. The package pins a Nova version range in composer.json. If you're on Nova 5 and the last release targeted Nova 4, composer require will fail. Check the constraint or fork and widen it — the Field is small.
  • Laraberg must be installed and published separately. The field fails silently (blank editor) if the Laraberg CSS/JS aren't published. Symptom: a grey box, no toolbar, Vue console error about Gutenberg undefined.
  • Assets in production. Nova compiles its own assets, but Laraberg's assets are served via its own published path. After composer install on a fresh server, run the publish step in your deploy script, not just in local setup.
  • Content is not escaped. Nova displays the field in preview; if your column contains user-authored HTML, an XSS payload will render on the detail page too. Sanitize on render, and consider a ->rules() that strips <script>.
  • Storing structure vs HTML. Gutenberg serializes to HTML with block comments embedded. That format is lossy for round-tripping custom block attributes — if you rely on block JSON attributes, also persist laraberg_contents (which stores the JSON) and read it for structured rendering.
  • No ->dependsOn() / reactive support out of the box. This is a plain field, not a FormField replacement; it won't repopulate on field dependency changes. Wrap it in a custom FormField if you need reactivity.
  • Small, low-traffic package. 8 stars, 0 dependents as of 2025-03. Treat it as a thin wrapper you may need to fork. The Field class is generally <200 lines — read it before debugging, since issues are usually Laraberg's.
  • Debugging tip. If saving produces an empty column, inspect the network response — Laraberg sometimes returns null when the block editor hasn't mounted yet (race between Nova's component lifecycle and Gutenberg's initialize). A ->default('') on the field or an updated callback that forces '' avoids null insertion errors on non-nullable columns.
  • Extension point: the Field's component() resolves to the package's Vue component. You can override it by publishing the field's Vue file and pointing ->component('your-custom-gutenberg') — useful for adding custom block categories or toolbar buttons.
  • Timezone/locale. Gutenberg's date blocks embed locale-formatted strings at save time. If you change app locale, previously saved date blocks won't reformat — they're stored as rendered text. Document this for editors.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle