iotronlab/tiptap-spatie-media
A Tiptap editor integration for Laravel's Spatie Media Library, letting you attach, browse, and embed media directly in rich-text fields. Adds a media picker and upload support to Tiptap within your Laravel app.
The v1.0.0 release notes only cover installation, so treat this as a first-pass assessment and verify the details against the package source before committing to it in a project.
composer require iotronlab/tiptap-spatie-media
From the package name, the intended role is clear: bridge a TipTap rich-text editor (front-end, JSON or HTML output) to spatie/laravel-medialibrary for image and file uploads. Expect TipTap to handle the editing UX and Spatie to own storage, conversions, and the media table relationship.
First steps after install:
php artisan vendor:publish --provider="Iotronlab\TiptapSpatieMedia\...ServiceProvider" (check the exact class with composer show iotronlab/tiptap-spatie-media) and look for a config/tiptap-spatie-media.php covering disk, allowed mime types, max upload size, and route prefix.php artisan route:list | grep -i tiptap and look in vendor/iotronlab/tiptap-spatie-media/database/migrations. If it registers an upload endpoint, that's the piece your editor's images upload handler should point at.vendor/iotronlab/tiptap-spatie-media/ — v1.0.0 notes are installation-only, so the README is the only source of truth for the expected model contract.First use case: a Post model with a content TipTap field. Add InteractsWithMedia to the model, register a content_images collection, render the editor in your form, point the editor's image-upload handler at the package's endpoint, and render the stored output on the front end with Spatie's getFirstMediaUrl() / getMedia() inside your own sanitisation layer.
Model setup. The package almost certainly expects the host model to use Spatie's trait. The standard shape:
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Post extends Model implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('content_images')
->acceptsMimeTypes(['image/jpeg', 'image/png', 'image/webp']);
}
}
Match the collection name to whatever the package's upload handler defaults to — this is the single most common integration failure.
Upload flow. Typical pattern for a TipTap image button: the editor POSTs the file, the package stores it against the model via addMediaFromRequest(), and returns JSON containing the media URL plus its ID. Store the media ID in the TipTap node attrs so you can later resolve conversions rather than hard-coding a URL — that way regenerating conversions or switching disks doesn't break old content.
Storage format. Decide early whether you persist TipTap JSON or HTML. JSON is cleaner for re-editing and lets you walk the document to extract media IDs; HTML is simpler to render but requires sanitisation on output. Pick one and keep the renderer and editor on the same contract.
Rendering. Don't just {!! $post->content !!}. Use a HTML purifier (e.g. mews/purifier) with an allowlist that includes figure, img, srcset, and your TipTap node classes. If the package ships a renderer or Blade component, prefer it and only fall back to manual rendering where it can't express your markup.
Conversions and responsive images. Register registerMediaConversions() for the sizes your editor emits (thumb, medium, large) and render srcset from getMedia('content_images') rather than storing absolute URLs in the content blob.
Queued conversions. Set queue_conversions_by_default to true in config/media-library.php and run a worker. Uploads feel instant; conversions catch up. For v1.0.0 with no documented performance characteristics, assume sync conversions will be slow on large images.
composer.json in the package for require constraints and read the source — a 1.0.0 with no documented surface area means you're the QA.addMediaCollection / collection string literals.config/media-library.php disk_name and any package-level disk override. If uploads return 200 but the URL 404s, it's almost always disk/symlink (php artisan storage:link) or a mismatched APP_URL.content against the media table, or you'll accumulate dead files.auth middleware and that your JS sends X-CSRF-TOKEN. A 419 on upload is the classic symptom."iotronlab/tiptap-spatie-media": "^1.0" rather than a floating constraint. A pre-1.1 package with sparse docs is likely to shift under you.media-library log or wrap the upload call in a try/catch and Log::debug() the ValidationException / FileDoesNotExist — Spatie throws specific, informative exceptions that are easy to lose behind a generic 500 from the package's controller.How can I help you explore Laravel packages today?