marshmallow/nova-tiptap
A Tiptap-powered rich text editor for Laravel Nova. Replace Nova's default field with a modern, extensible WYSIWYG experience, featuring configurable toolbar options and clean JSON/HTML output for flexible content editing. Easy to install and customize for your admin panels.
Architecture fit. This is an admin-plane dependency with no value outside Laravel Nova — it plugs into Nova's field pipeline (a PHP field class plus a published Vue component) and touches no service layer, middleware, model, or API surface. Architecturally that is the best kind of third-party package: thin, isolated, and replaceable. The one decision it forces that does propagate into architecture is the content contract — whether the field persists HTML or ProseMirror JSON. That choice leaks downstream into search indexing, feeds, exports, mobile clients, and localization, so it must be made deliberately at adoption time rather than discovered later. Fit is strong only if Nova is already the committed admin plane and only if a nameable gap exists versus Nova 4+'s first-party Tiptap field; "we want rich text" is not a gap, "we need mention nodes / tables / a custom toolbar layout" is.
Integration feasibility. On paper, high: composer require, one vendor:publish, one field in one Resource, and a round-trip test. Real feasibility is gated by an unverified compatibility triangle — Nova major (the Vue 2 → Vue 3 boundary at Nova 3/4) × Tiptap major (v2 → v3 with breaking extension APIs) × build toolchain (Mix vs Vite). With ~20 stars and zero dependents there is no crowd-sourced evidence that any specific combination works. Feasibility should therefore be treated as unproven until demonstrated in a throwaway branch.
Technical risk. Concentrated and mostly mitigable, but not zero:
laravel.log. This is the dominant risk and the reason CI asset builds plus a browser smoke test are non-negotiable.composer update is how a breaking change arrives as a blank box rather than a changelog.{!! $model->body !!} requires a sanitizer allowlist equal to or stricter than the toolbar. A looser profile is a live vulnerability, not a lint warning.Key questions to resolve before approval.
Stack fit. Laravel + Nova + PHP 8.x with a Vue component compiled into Nova's asset pipeline. The package is a natural fit where the product already runs Tiptap on the front end — one mental model, one extension ecosystem, one set of rendering concerns. Where the front end uses a different editor, adoption introduces a second editor stack: a modest but compounding long-term tax that belongs in the decision record, not the footnotes.
Migration path. Treat migration as a data migration, not a field swap, and run it as a separate pass.
Compatibility. Prove the exact version matrix in a throwaway branch before committing: confirm the field class loads, the component mounts, and the asset publishes. Pin the exact version — no ^. Record the tested matrix (Nova major, Tiptap major, PHP version) in the repo README so the next upgrade is a checklist rather than an archaeology project.
Sequencing.
RichText class extending the package field, with toolbar/extensions from config. No Resource references the vendor class directly.saving observer, profile matched to the toolbar.Maintenance. Low absolute cost, but it is your cost, not a vendor's. The recurring obligations are version pinning, re-proving the compatibility matrix on any Nova or Tiptap bump, and keeping the published asset from going stale in CI. Assume a possible fork: MIT license, small surface area, realistically one to two days of work — but that estimate holds only if the wrapper discipline is real. The moment package APIs are called across dozens of Resources, exit cost stops being measured in days.
Support. No commercial support and effectively no community at 20 stars / zero dependents. Internal ownership is mandatory, and the hidden cost is not the package — it is Tiptap/ProseMirror literacy (schema, nodes, marks, extensions). Anything beyond a default toolbar requires it. Budget that as a line item, not an afterthought.
Scaling. The package itself does not create scaling cost; the content does. HTML storage means large markup blobs that need search indexing, excerpt derivation, and sanitization CPU on every write — and max:65535 validation hints at TEXT column ceilings that become a schema migration on long-form content. ProseMirror JSON trades those problems for a harder one: every downstream consumer (search, feeds, mobile, PDF export, localization) must implement a renderer. Index views need an explicit decision — override displayUsing() with a plain-text excerpt or exclude the field entirely — because raw HTML in a Nova index column renders as a wall of markup or truncates mid-tag.
Failure modes to instrument.
$errors redirect, which looks exactly like data loss and only appears on the error path.{!! !!} where the sanitizer profile is looser than the toolbar.Ramp-up. Roughly a sprint to a credible internal pilot — but only if someone owns the Tiptap learning curve and the pilot surface is genuinely internal. Where a broken editor costs an afternoon rather than a customer, the risk profile is acceptable at 20 stars; where it touches customer-facing publishing, it is not. The strategic framing to hold: this package signals light-touch content operations. A governed content platform is a different build, and choosing this for that purpose is a mismatch.
How can I help you explore Laravel packages today?