mantix/livewire-jodit-text-editor
A Livewire 3/4 WYSIWYG rich text editor component built on Jodit. Drop it into your Blade views for a full-featured editor with customizable toolbars, multiple editor support, and programmatic content updates.
Architecture fit. The package is a thin Livewire wrapper around Jodit, delivered as a single Blade component with wire:model two-way binding. There is no service provider to configure, no persistence layer, no PHP API surface, and no second state store beyond the editor's own document. For a Laravel + Livewire app this is the right shape: the editor behaves like a form control, not a subsystem, so it neither earns nor demands architectural review time. The two surfaces we actually govern are the published Blade view (php artisan vendor:publish --tag=livewire-jodit-text-editor-views) and the global browser event update-jodit-content, optionally scoped by an identifier for multi-editor pages. That event is the one abstraction leak: programmatic writes bypass Livewire's parent/child data flow and must be treated as an imperative escape hatch, not a pattern to build features on.
What we are not buying. The scope is the editing surface only — no server-side HTML sanitization, no image/video upload or storage backend, no revision history, no approval workflow, no ACL, no asset version pinning. For expectation-setting: adoption saves roughly one to two engineering days of component plumbing. It does not save the cost of sanitization or the media upload endpoint, both of which we own under any editor choice. Anyone framing this as "rich text solved" should be corrected in the kickoff.
Integration feasibility. Low effort to first render: Composer require, then a choice between CDN <script>/<link> tags or an NPM build importing Jodit and its plugins into app.js/app.scss. Basic usage is one line. The NPM path is the only production-correct choice because it puts Jodit under our lockfile and bundler; the CDN path is an unpinned third-party runtime dependency and is acceptable solely for a spike. The genuinely uncertain area is media: the README documents loading the Jodit resizer and video plugins but never defines an upload endpoint contract. A time-boxed spike must confirm whether uploads wire through Jodit's own config via the options passthrough (v1.10) or require custom handling — before any delivery date is committed.
Technical risk — rated, with owner and mitigation trigger.
| Risk | Rating | Why | Mitigation trigger |
|---|---|---|---|
| Adoption | High | 31 stars, 0 dependents. We would be a de facto early adopter; edge cases are ours to find. | Spike covers the three flows we need; anything uncovered gets a fallback plan |
| Maintainer continuity | Medium-high | Single maintainer, bus factor of one. Recent releases and a maintained changelog are the only evidence of continuity. | Fork-and-own contingency noted in the ADR; no contractual dependency assumed |
| Framework coupling | Medium | Sits on two moving targets: Jodit's JS API and Livewire's DOM lifecycle. v1.8 and v1.10 exist specifically to fix wire:ignore/wire:navigate duplicate-editor behavior. |
Regression test for navigate-away-and-back in the QA checklist |
| Security (XSS) | High if unmanaged | A WYSIWYG field stores HTML; Jodit is not a sanitizer. | Server-side sanitization with tag/attribute/URL allow-list is a launch gate, not a follow-up |
| Version skew | Medium | Package does not pin Jodit; we do. Docs demonstrate 4.1.16; the next Jodit major is ours to absorb. | Pin exact version in lockfile and record it in the ADR |
| Supply chain | Low-medium | Present only on the CDN path; eliminated by NPM + lockfile. | NPM-only standard |
| Livewire 4 path | Medium | Support landed in v1.9, so it has the least field exposure in the supported matrix. | Confirm target Livewire version before scoping |
Key questions to resolve before committing.
{!! !!} output in the app; each one changes the risk profile immediately.Stack fit. Strong where the app is Laravel + Blade + Livewire 3 or 4. Weak or wrong where the front end is Inertia/Vue/React: in that case the Livewire wrapper is dead weight and the team should consume Jodit directly. The decision gate is therefore one question — is the target screen a Livewire component? — and the answer routes the work, it does not start it.
Compatibility matrix to pin in the ADR. Livewire 3 (longest field exposure), Livewire 4 (since v1.9, newer), Jodit 4.1.x (we pin exactly; package does not), PHP version per the app's existing baseline, and browser targets if authors use low-end hardware or tablets.
Migration path. Two tracks:
Sequencing (with decision gates).
options. Gate: upload path proven or custom endpoint scoped.wire:navigate duplicate regression test, error-state re-render behavior, debounce policy for wire:model.live on long forms.Maintenance. Assign a named owner — a front-end-capable engineer — at adoption, not after the first incident. Standing obligations: pin and bump Jodit deliberately, watch upstream releases (the changelog shows the brittle seam is Livewire lifecycle, not editing features), and keep the fork-and-own option documented. If this becomes a standardized pattern across many editors, the cost shifts from negligible to a recurring line item of a few days per year plus upgrade risk on each Livewire major.
Support. No vendor SLA. Upstream support is GitHub issues from a single maintainer; our support is our own team. Documentation is adequate for install and basic usage, thin on media upload and on server-side content handling — the two areas that generate the tickets. Write the internal runbook covering "editor duplicates after navigation," "content out of sync after validation error," and "why did my pasted content lose formatting," because those will be the first three tickets.
Scaling. Two axes. Client-side: multiple Jodit instances on one page multiply JS cost, so cap instances per screen and lazy-init where possible — low-end hardware and tablets are the constraint, not servers. Round-trip: wire:model.live sends HTML on every keystroke-adjacent change, which is heavy for long documents; use debounce or plain wire:model for large bodies. Storage: HTML blobs grow and cannot be diffed cheaply; if revision history is ever needed it is a new subsystem, not a config change.
Failure modes to plan for. Duplicate editor instances after wire:navigate (known seam, repeated fixes upstream); content desync when Livewire re-renders on validation failure; global update-jodit-content event collisions on pages with unrelated editors; unpinned CDN asset disappearing or changing; XSS through stored HTML rendered outside the trusted author group; upload endpoint abuse if it ships without limits; silent sanitization stripping content that authors believed was saved. Each one maps to a named test or a named control — none should be discovered in production.
Ramp-up. Engineering: under a day for a Livewire-fluent developer. Content authors: a short guide on the restricted toolbar and what happens to pasted formatting. QA: a specific checklist for the navigate/re-render seams, without which "the editor is broken" reports are unactionable. Product: explicit statement in the release notes that rich text fields are sanitized on save and that unsupported formatting is dropped by design.
Recommendation. Fund it as a time-boxed spike for a scoped, internal, trusted-author use case with sanitization as a launch gate. Do not mandate it as a product standard until it has survived one real feature shipped to production and one Livewire or Jodit upgrade without incident.
How can I help you explore Laravel packages today?