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

Laravel Nova Visual Composer Laravel Package

novius/laravel-nova-visual-composer

A visual page composer for Laravel Nova that lets you build and arrange content blocks with a drag-and-drop interface, so editors can assemble layouts without touching code.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This package is a Nova field, not a rendering engine or CMS. It occupies a narrow seam in the architecture: a single JSON column on an Eloquent model, a config-declared block registry (key, label, editor component, nested Nova fields), and a Vue field component that provides drag-and-drop composition inside the Nova admin. Everything downstream of the column — routing, Blade/API rendering, caching, media resolution, localization — is application code you own. That is a good architectural fit for teams that already treat Nova as their internal admin surface and want structured content instead of a single rich-text blob or hand-authored HTML. It is a poor fit for anything that expects the package to be a content service, an API layer, or a customer-facing builder. The critical architectural property is that content is stored as portable JSON with a type discriminator, so the persistence model survives the package's abandonment even if the editor does not. That decoupling is what makes this evaluable at all at 14 stars.

Integration feasibility. Mechanically low-effort: composer require, publish config/assets, add a json('content')->nullable() column, cast to array, register VisualComposer::make('Content', 'content') on a resource, define two block types. Realistically a one-day spike to prove round-trip. The gating question is not effort but resolution: last release July 2022, sitting in the Nova 3/Vue 2 → Nova 4/Vue 3 transition window. Two facts must be confirmed before any commitment: whether composer require --dry-run resolves against your pinned laravel/nova constraint, and whether the shipped Vue component targets Vue 2 or Vue 3. Those answers determine whether the field renders at all — and because a non-hydrating field can save an empty payload over existing content, this check must happen on a throwaway branch against non-production data.

Technical risk. The dominant risk is abandonment, not defects. Zero dependents means no one else is filing the bugs you will hit, and Nova support explicitly will not touch third-party fields. Secondary risks, in order of consequence:

  • Silent content overwrite — the field submits an empty payload when the Vue component fails to load (Nova upgrade, unpublished/unbuilt asset, unrelated JS error) with no error surfaced. This is the failure mode to design against.
  • Asset build ambiguity — if no pre-compiled dist/ ships, you inherit an npm run prod step inside a PHP deploy pipeline, a permanent maintenance cost.
  • Schema drift — removed block types persist in the database forever; renames without backfills corrupt stored payloads.
  • Malformed JSON — manual edits, partial saves, and imports produce undecodable payloads that 500 a live page without a guard.
  • Editor extensibility ceiling — per-block conditional fields, dynamic defaults, or custom validation UX require patching the Vue component, which is a fork decision, not configuration.
  • No localization — a per-locale column or translatable cast must be designed before block authoring begins; retrofitting means backfilling every page.

Key questions.

  1. Does it resolve and render on our exact Nova/Laravel/PHP pins — verified, not assumed?
  2. Does it ship compiled assets, or do we own a front-end build step?
  3. Who is the named internal owner of the fork, and is the ~1 day of internalization budgeted?
  4. Is the requirement internal bounded block authoring, or does product actually need previews, versioning, scheduling, localization, accessibility guarantees, or multi-tenant authoring? The latter set is a buy/build decision, not this package.
  5. Do we accept schema ownership — schema_version from day one, save-time validation, skip-unknown-on-render?
  6. What is our rollback story if a Nova upgrade breaks the field in production?

Integration Approach

Stack fit. Acceptable only where the stack matches the era it was built for: Laravel 8/9, PHP 8.0/8.1, Nova 3/4, Vue 2 or early Vue 3. Against Laravel 11/12 + Nova 5 there is no compatibility guarantee and no maintainer to provide one. The practical test is the resolver plus a visual check of the field in the Nova resource edit screen on a staging environment.

Migration path. Recommend a fork-first posture rather than a dependency posture. Copy the field class, the Vue component, and the config into an application namespace, pin it, and treat upstream as a reference implementation. Roughly one day of work that removes most of the abandonment risk and gives you a legal place to patch Nova 5 compatibility later. Adoption sequence:

  1. Spike (1 week, throwaway branch): install, publish, add column + cast, register two block types (rich_text, image), save a page, dd($page->content), render via Blade. Freeze the observed payload shape as your schema and add schema_version to every stored block immediately.
  2. Fork and vendor into application namespace; pin versions; document the block contract internally.
  3. Harden: save-time validation rule (known type + fields array + block-count cap ~100), decode guard treating malformed JSON as empty with a log, View::exists() guard on render, content:repair-blocks artisan command.
  4. Safety net: column backup or revisions table, plus a saved observer that warns when a previously non-empty column is written empty.
  5. First production use case: one resource, bounded block set, one rendering path.

Compatibility. Two hard constraints. First, renderer/editor version coupling — a Vue 2 field will not hydrate in a Vue 3 Nova, and the failure is silent. Second, payload compatibility is entirely on you — the package has no migration tooling for block shapes, so any change to the registry requires a backfill command that rewrites stored JSON. Never rename a block key in place. Treat templates as JSON fixtures in seeders/config rather than database-only, so staging and production stay in sync.

Sequencing. Do not parallelize editor work and rendering work. Prove the round trip end to end with two block types before adding a third. Build the renderer before the block library grows, because the renderer's skip-unknown behavior is what makes schema evolution survivable. Defer nesting (columns, accordions, sections) until the flat contract is frozen and tested — nesting makes the payload recursive and roughly doubles the blast radius of a schema mistake. If localization is even a plausible requirement, add the per-locale column before authoring begins.

Operational Impact

Maintenance. Budget ~2–3 days per year plus a defined task in every Laravel and Nova major upgrade. The recurring work is not the package code — it is the schema: backfills on every block rename, repair runs on malformed JSON, and renderer updates as the block library evolves. Internalizing the code converts unpredictable "upstream is dead" risk into predictable "we own a small field" work, which is the trade worth making. Deploy runbook must carry vendor:publish next to migrate, plus a post-deploy smoke test that loads the resource edit page — a blank field in admin is almost always an unpublished or unbuilt asset, not a bug, and that distinction saves hours of misdirected debugging.

Support. There is effectively no upstream support channel: single small-agency maintainer, no release since 2022, no dependents, and Nova support will not diagnose third-party fields. Internal onboarding therefore depends on documentation you write: the block contract, the payload schema, the renderer's skip-unknown semantics, the publish step, and the fork/patch procedure. Handing a second developer the vendor directory without that doc is a bus-factor problem, not a knowledge-transfer problem.

Scaling. The single-JSON-column design scales fine for pages and bounded documents. It degrades on documents with hundreds of nested blocks: save payload size and per-request render time both creep. Mitigations are cheap — cache rendered fragments around the render loop or via a cached model accessor for high-traffic pages, cap block count per document, and keep block partials free of N+1 media lookups by resolving images through the existing conversion/thumbnail pipeline rather than the raw File value. If the requirement grows toward a customer-facing builder or API-first content delivery, this column shape is the wrong substrate and the migration cost is real.

Failure modes.

Failure Symptom Mitigation
Vue component fails to hydrate Empty payload written over existing content, no error Revisions/backup column, staging check on every Nova upgrade, saved observer warning on non-empty→empty
Unpublished/unbuilt assets Blank field in admin Publish step in deploy runbook + post-deploy smoke test
Unknown block type in stored JSON Cosmetic gap or 500 on live page View::exists() guard; skip on render, reject on save
Malformed JSON Unhandled decode exception try/catch → empty block list + log; content:repair-blocks command
Removed/renamed block key Data orphaned or renders wrong component schema_version per document, backfill command, never rename in place
Document bloat Slow saves and slow renders Block-count rule, fragment caching

The asymmetry worth institutionalizing: fail loudly for the editor, degrade gracefully for the visitor. Reject unknown types on save; skip them on render.

Ramp-up. Low. The config schema reads in twenty minutes and the extension points are few — the field class, the Vue component, and the block registry. A competent Laravel developer is productive in the spike on day one and comfortable owning the fork within a week. The genuine ramp-up cost is organizational, not technical: naming an owner, committing to the quarterly maintenance budget, and getting product to accept that the block registry is the content model — which means block changes are schema migrations, not configuration tweaks.

Verdict. Adopt as a reference implementation and spike candidate, not a platform dependency. Green-light a one-week, two-block, end-to-end validation on a throwaway branch to confirm the block-based content model is the right product decision. Treat a production commitment as contingent on the fork being internalized, a named owner assigned, schema_version in the payload from day one, and the renderer's safety guards written before the editor ships. Look elsewhere if the requirement is really previews, versioning, scheduling, localization, accessibility guarantees, or multi-tenant authoring — those are CMS requirements this package does not address.

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