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 Tiptap Laravel Package

manogi/nova-tiptap

A Tiptap-based rich text editor field for Laravel Nova, giving you a clean, customizable WYSIWYG experience with configurable extensions and JSON/HTML output for your resource forms.

View on GitHub
Deep Wiki
Context7

Getting Started

Step 0 — decide you're forking, not installing. The repo is archived (last release 2024-06-27), zero dependents, health score 1.64. You are not consuming a dependency; you are adopting source. Budget the fork before your first composer require.

  1. Check the compatibility matrix before anything else. Nova major ↔ Laravel/PHP ↔ Vue 2/3 ↔ bundled Tiptap version. Version mismatch is the #1 failure mode for Nova fields, and it is the first thing that will burn a day. Read the composer.json constraint against your Nova version, then confirm the compiled component in dist/ was built against the Vue version Nova ships.
  2. Install against a fork you control. If Composer can't resolve manogi/nova-tiptap, add a VCS repository pointing at your fork and pin an exact tag:
    {
      "repositories": [{ "type": "vcs", "url": "[email protected]:yourorg/nova-tiptap.git" }],
      "require": { "manogi/nova-tiptap": "3.2.6" }
    }
    
    Run php artisan vendor:publish if it ships publishable assets.
  3. Smoke-test on one resource only:
    use Manogi\Tiptap\Tiptap;
    
    public function fields(Request $request)
    {
        return [
            Tiptap::make('Content')
                ->buttons(['bold', 'italic', 'link', '|', 'heading', 'bulletList', 'codeBlock'])
                ->rules('nullable'),
        ];
    }
    
  4. Where to look first. The README for the ->buttons([...]) token list and options; then src/Tiptap.php for component(), resolve(), fill(), and the meta methods; then resources/js / dist for the Vue component. Because it's archived, the source is the documentation for every edge case.
  5. First real use case. Replace Nova's default text/Trix field on a Pages or Posts resource where authors need headings, lists, links, and code blocks. The exit criteria for your spike: the editor renders, saves, and reloads a real document, and you know exactly what lands in the database column (ProseMirror JSON vs HTML — verify empirically, don't trust the README).

If the Nova version isn't in the supported range, stop. Porting an unmaintained field is not a spike, it's a project.

Implementation Patterns

  • Toolbar as per-field config. Don't accept defaults everywhere. A marketing "Page" gets headings, lists, links, '|' separators. A short "Bio" gets ['bold', 'italic', 'link']. This is the lever you touch weekly — build a small helper so each resource declares its own toolbar.
  • Settle storage format and cast it immediately. If it persists ProseMirror JSON:
    protected $casts = ['content' => 'array'];
    
    One renderer, shared by preview, API, and email — a server-side JSON→HTML converter — so schema drift can't creep in between environments.
  • Never leak raw JSON into index columns or API responses. Use an accessor or ->displayUsing() running the same JSON→HTML path, then Str::limit(strip_tags($html), 120). This is the single most common integration point and the most common place a reviewer catches you.
  • Validate shape, not just presence. Pair nullable|json with a custom rule that walks the doc for required node types ("must contain at least one paragraph"). Tiptap will happily submit a structurally empty doc.
  • Split forms vs detail. ->onlyOnForms() where the editor shouldn't appear on detail, and render a formatted read-only view instead. Better authoring UX, less confusion.
  • Seed and factory with real documents. Fixtures must be ProseMirror docs ({"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"..."}]}]}), not plain strings, or round-trip tests lie.
  • Sanitize server-side, always. Allowed-list sanitizer (mews/purifier / HTMLPurifier) before persist and before render. The package will not do this for you and client-side sanitization does not count.
  • Custom nodes are a permanent fork. Callouts, embeds, footnotes: publish the JS assets, add the Tiptap extension in the Vue component, and mirror the schema server-side in your renderer. Do it sparingly and log each one.
  • Document the fork as a product. FORK.md with provenance, pinned versions, compatibility matrix, custom nodes, and the fallback path (native Nova field + small custom Vue component). Add it to the Nova upgrade checklist.

Gotchas and Tips

  • Archived means frozen compatibility. Pin Nova and PHP in CI and keep a regression test that boots the field before every upgrade. A Nova 4→5 or PHP minor bump can silently break registration or asset loading.
  • Vue/asset pipeline mismatch. Nova ships its own Vue and asset tooling. Rebuild the field's JS against Nova's toolchain, not your app's — Mix vs Vite and Vue 2 vs 3 mismatches are a reliable source of friction.
  • Tiptap API drift. The bundled Tiptap version is fixed. Pulling a newer extension from a different Tiptap major throws schema/command errors at runtime. Match extension versions to the bundled editor, or upgrade the whole thing deliberately.
  • CSP will bite. A strict Content-Security-Policy blanks the editor with console errors only. Allow the published asset paths and watch for inline styles injected by Tiptap.
  • Empty-doc edge case. An untouched editor can submit {"type":"doc","content":[{"type":"paragraph"}]} instead of null. Normalize before saving or you'll get non-null "empty" records that break nullable assumptions and downstream if ($post->content) checks.
  • JSON round-trip loss. JSON→HTML→JSON quietly drops marks and nested lists. Write round-trip tests on representative documents — headings, nested bullets, links, code blocks — not one happy-path paragraph.
  • Debugging a blank editor — check in this order: (1) assets published and loading in the Network tab, (2) the field's component() name matches the compiled component, (3) field meta is serialized via withMeta()/meta(), (4) CSP. Nearly every "broken field" report is one of those four.
  • Extension points end at the toolbar. ->buttons() and meta are supported. Anything deeper means editing the Vue source — budget that as recurring cost at each Nova upgrade.
  • Support is you. No vendor path, no dependents, last release 2024-06-27. Keep the fallback (a small custom Vue field) on the shelf before you need it, and make sure the next maintainer can reconstruct your choices from FORK.md rather than reverse-engineering them.
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.
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
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect