Installation
composer require georgeboot/laravel-tiptap
yarn add laravel-tiptap
Add to app.js:
import Alpine from 'alpinejs'
import LaravelTiptap from 'laravel-tiptap'
Alpine.data('tiptapEditor', LaravelTiptap)
Alpine.start()
First Usage Include the component in a Blade view:
<x-tiptap-editor />
This renders a basic Tiptap editor with default configurations.
Key Files to Review
resources/views/vendor/laravel-tiptap/ (Blade components)node_modules/laravel-tiptap/dist/ (JS/CSS assets)config/tiptap.php (published via php artisan vendor:publish --provider="GeorgeBoot\LaravelTiptap\LaravelTiptapServiceProvider")Basic Editor Integration
Use <x-tiptap-editor /> for a pre-configured editor with default extensions (bold, italic, lists, etc.).
Pass a model prop to bind to a Laravel model:
<x-tiptap-editor :model="$post->content" />
Customizing Extensions
Override default extensions via config (config/tiptap.php):
'extensions' => [
'StarterKit',
'Underline',
'CodeBlock', // Add custom extensions
],
Or dynamically via Alpine:
Alpine.data('tiptapEditor', (defaultConfig) => ({
...defaultConfig,
extensions: [
...defaultConfig.extensions,
'CodeBlock',
],
}))
Image Uploads
Enable with <x-tiptap-editor enable-image-upload />.
Ensure S3 disk is configured (see README) and add a route for uploads:
Route::post('/tiptap-upload', [TiptapController::class, 'upload'])->name('tiptap.upload');
Form Submission
Bind the editor to a form field (e.g., textarea hidden via CSS):
<form method="POST">
<x-tiptap-editor name="content" />
<textarea name="content" style="display: none;"></textarea>
<button type="submit">Save</button>
</form>
Dynamic Initialization Use Alpine to conditionally load the editor:
@if(auth()->check())
<x-tiptap-editor :model="$user->bio" />
@endif
HasTiptapContent trait (if provided) or manually cast attributes:
protected $casts = [
'content' => 'tiptap',
];
$request->validate([
'content' => 'required|string',
]);
tailwind.config.js to purge the package’s views (as shown in README).Missing Alpine Initialization
Forgetting to add Alpine.data('tiptapEditor', LaravelTiptap) will break the editor.
Fix: Ensure app.js includes the line after Alpine is imported.
S3 Uploads Without CloudFront
If using S3 directly (without CloudFront), URLs may return 403 Forbidden due to S3’s default permissions.
Fix: Configure CORS for your bucket or use CloudFront.
Tailwind Purge Issues
Forgetting to add the package’s views to purge in tailwind.config.js may cause styles to disappear.
Fix: Include:
'./vendor/georgeboot/laravel-tiptap/resources/views/**/*.blade.php'
CSRF Token for Uploads
Image uploads require CSRF protection. Ensure your upload route includes @csrf in Blade or the token in the request headers.
Fix: Add @csrf to your Blade form or include _token in AJAX requests.
Editor State Not Persisting If the editor’s content isn’t saved, check:
textarea has the correct name attribute.textarea (not just the editor’s DOM).Console Errors
Check browser console for errors like Uncaught ReferenceError: Tiptap is not defined. This usually means the JS bundle isn’t loaded.
Fix: Verify yarn build was run and assets are published (php artisan tiptap:assets).
Upload Failures If images fail to upload, check:
.env.chmod -R 775 storage).Extension Conflicts If the editor behaves unexpectedly, disable custom extensions one by one to isolate the issue.
Custom Toolbar Override the toolbar via config:
'toolbar' => [
'bold', 'italic', 'bulletList', 'orderedList', 'codeBlock',
],
Or dynamically in Alpine:
toolbar: [
'bold', 'italic', 'image', // Customize toolbar
],
Dark Mode Support
Add a dark prop to the component:
<x-tiptap-editor dark />
(If not supported, extend the package’s CSS.)
Local Development
Use yarn dev for hot-reloading during development:
// vite.config.js
export default defineConfig({
server: {
hmr: {
host: 'localhost',
},
},
});
Extending the Package Publish the config and views for customization:
php artisan vendor:publish --provider="GeorgeBoot\LaravelTiptap\LaravelTiptapServiceProvider" --tag="config"
php artisan vendor:publish --provider="GeorgeBoot\LaravelTiptap\LaravelTiptapServiceProvider" --tag="views"
Performance Lazy-load the editor if it’s not always needed:
@if($shouldShowEditor)
<x-tiptap-editor />
@endif
How can I help you explore Laravel packages today?