Installation
composer require firefly/filament-blog
Publish the package assets and config:
php artisan vendor:publish --provider="Firefly\FilamentBlog\FilamentBlogServiceProvider" --tag="filament-blog-config"
php artisan vendor:publish --provider="Firefly\FilamentBlog\FilamentBlogServiceProvider" --tag="filament-blog-migrations"
php artisan migrate
Register the Plugin
Add to app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
\Firefly\FilamentBlog\FilamentBlogPlugin::make(),
]);
}
First Use Case
/admin/blog).Post Management
published_at in the Filament form to auto-publish posts later.SEO Optimization
Post model’s getMetaTags() method or override the MetaTags widget in your plugin instance:
FilamentBlogPlugin::make()
->metaTags(function (Post $post) {
return [
'title' => "Custom Title: {$post->title}",
'description' => "Custom description for {$post->slug}",
];
})
Frontend Integration
@filamentBlogPosts(
limit: 5,
category: 'tutorials',
withComments: true
)
@filamentBlogPost directive for individual posts.Comment System
comments() method in the plugin config:
'comments' => [
'enabled' => true,
'moderation' => true, // Require admin approval
]
Comment model to add custom fields (e.g., user_agent, ip_address).Newsletter Integration
post.published event to trigger newsletter emails:
event(new PostPublished($post));
Mail facade or a service like Mailchimp via the NewsletterService.Custom Fields
Add fields to the Post form via a service provider:
public function boot()
{
FilamentBlog::extendPostForm(function (Form $form) {
$form->fields([
TextInput::make('custom_field')
->columnSpanFull(),
]);
});
}
API Endpoints
Register routes in routes/api.php:
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('posts', \Firefly\FilamentBlog\Http\Controllers\Api\PostController::class);
});
Extend the controller to add custom logic (e.g., pagination, filtering).
Webhooks for Notifications
Use Laravel’s queue:work to process notifications asynchronously:
PostPublished::dispatch($post)
->delay(now()->addMinutes(5)) // Delay for testing
->onQueue('notifications');
Multi-Author Support
Override the author() relationship in the Post model:
public function author()
{
return $this->belongsTo(User::class, 'author_id');
}
Update the Filament form to include an AuthorSelect field.
Migration Conflicts
posts table, reset migrations before publishing:
php artisan migrate:fresh --env=testing
created_at, updated_at) in the package’s migrations.SEO Meta Tags Not Updating
metaTags():
php artisan cache:clear
php artisan view:clear
MetaTags service provider is registered in config/app.php.Comments Not Appearing
comments table exists and the commentable relationship is set up:
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
commentable_type and commentable_id columns in the comments table.Scheduled Posts Not Publishing
published_at column is nullable and indexed:
$table->timestamp('published_at')->nullable()->index();
php artisan schedule:run
now() instead of a future date.Frontend Styling Issues
resources/css/app.css:
@layer components {
.filament-blog-post {
@apply bg-white p-4 rounded-lg shadow;
}
}
Log Post Events
Add logging to the PostPublished event handler:
public function handle(PostPublished $event)
{
\Log::info('Post published', ['post_id' => $event->post->id]);
}
Check Queue Jobs
Monitor failed jobs in the failed_jobs table or via Tinker:
php artisan tinker
>>> \Illuminate\Support\Facades\Queue::failed();
Filament Plugin Isolation If the plugin conflicts with other Filament plugins, wrap its registration in a closure:
->plugins([
\Firefly\FilamentBlog\FilamentBlogPlugin::make()->configureUsing(function (FilamentBlogPlugin $plugin) {
$plugin->disableComments(); // Example: Conditional logic
}),
])
Custom Post Types
Extend the Post model to support different content types (e.g., VideoPost, Podcast):
class VideoPost extends Post
{
protected $table = 'video_posts';
public function video()
{
return $this->morphOne(Video::class, 'videoable');
}
}
Register a new Filament resource for the custom type.
Third-Party Integrations
comments() relationship and adding a disqus_id column.searchable scope to the Post model and index via Laravel Scout.Localization Publish and translate the language files:
php artisan vendor:publish --tag=filament-blog-translations
Update resources/lang/en/blog.php and add new locales.
Testing
Use the package’s test helpers in tests/Feature/BlogTest.php:
public function test_post_creation()
{
$post = FilamentBlog::createPost([
'title' => 'Test Post',
'content' => '<p>Hello, world!</p>',
]);
$this->assertDatabaseHas('posts', ['title' => 'Test Post']);
}
How can I help you explore Laravel packages today?