happytodev/blogr

Blogr is a FilamentPHP plugin that adds a powerful blog system to your Laravel application.

Fund package maintenance!
happytodev


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

alt text

Blogr is a FilamentPHP plugin that adds a powerful blog system to your Laravel application.

Features

Content management

  • Create, edit, and delete blog posts
  • Edit post in markdown
  • A post can have a TL;DR
  • The post's slug can be custom
  • Status : Draft, Scheduled, Published
  • Category (one per post)
  • Tags (multiple per post)
  • Posts by category page
  • Posts by tag page
  • Post reading time
  • Support code (currently very simple)

Medias

  • Main post image upload and editing
  • Drag & Drop image in the post content (see video demo below)

Table of contents

  • Table of contents is automatically generated
  • TOC could be deactivate for a post
  • User could define if TOC is activated by default or not for every post

SEO

  • Integrate meta fields
  • Content optimization for SEO

Settings

  • Many settings are available on an admin page or directly in config/blogr.php

Tutorial

  • Add default content to help user to start with Blogr

Widgets

  • Widgets available for the dashboard

Screenshots

Blog post view

Blog post view

Backend - List of posts

Backend - List of posts

Backend - Edit post

Backend - Edit post

Settings

Backend - Settings

Widgets

Backend - Widgets

Video demo

Drag & Drop image in the post content

alt text

Roadmap

Beta 2 (ETA 2025-09-15)

  • SEO fields (meta title, description, keywords) ✅ Completed
  • Scheduled publishing ✅ Completed
  • In the admin in the list of posts, display the toggle for is_published to quickly publish or unpublish ✅ Completed
  • Add a table of content for blog post ✅ Completed
  • When no post is published, display a message to user ✅ Completed
  • Add a reading time information for blog post ✅ Completed
  • Integrate meta fields ✅ Completed
  • Create widgets to display on dashboard ✅ Completed
  • Add a settings page to easily manage settings set in config/blogr.php ✅ Completed
  • TOC could be deactivate for a post ✅ Completed
  • User could define if TOC is activated by default or not for every post ✅ Completed
  • Add default content to help user to start with Blogr ✅ Completed

Beta 3 (ETA 2025-09-30)

  • Add a RSS feed for the blog posts
  • Collapsible TOC
  • Title of blog post in the widget 'recent blog posts' should be clickable
  • Define TOC style like in the eventuallycoding.com blog
  • More to come...

Requirements

  • Laravel 12.x
  • FilamentPHP v4.x
laravel new mycompanyblog

cd mycompanyblog

composer require filament/filament:"^4.0"

php artisan filament:install --panels

php artisan make:filament-user

You have to start with a fresh install of Laravel and Filament v4 or add this package on existing app with these requirements.

Installation

Install with blogr command

The easiest way to install Blogr is using the automated installation command. This command will guide you through the entire installation process and handle most configuration automatically.

  1. Install the package via Composer
composer require happytodev/blogr
  1. Run the automated installation
php artisan blogr:install

Available Options

The blogr:install command supports several options to customize your installation:

  • --skip-npm - Skip npm dependencies installation
  • --skip-tutorials - Skip tutorial content installation

Examples:

# Install everything (recommended for new installations)
php artisan blogr:install

# Skip npm installation (if you don't need typography plugin)
php artisan blogr:install --skip-npm

# Skip tutorial content
php artisan blogr:install --skip-tutorials

# Skip both npm and tutorials
php artisan blogr:install --skip-npm --skip-tutorials

What the command does

The automated installation performs the following steps:

  1. 📦 Publishes configuration and migration files

    • Publishes config/blogr.php
    • Publishes migration files
    • Publishes views and assets
  2. 🗄️ Runs database migrations

    • Creates necessary database tables
    • Handles migration conflicts gracefully
  3. 📚 Installs tutorial content (unless --skip-tutorials is used)

    • Creates 7 comprehensive tutorial posts
    • Includes welcome guide, installation help, and advanced features
    • Creates a dedicated "Blogr Tutorial" category
  4. 📊 Installs dashboard widgets

    • BlogStatsOverview - Blog statistics and metrics
    • RecentBlogPosts - Latest posts with quick actions
    • ScheduledPosts - Upcoming scheduled publications
    • BlogPostsChart - Publication trends over time
    • BlogReadingStats - Reading time analytics
  5. 📦 Handles npm dependencies (unless --skip-npm is used)

    • Installs @tailwindcss/typography if not present
    • Updates resources/css/app.css with typography plugin
  6. 🔧 Checks AdminPanelProvider configuration

    • Verifies BlogrPlugin is properly registered
    • Provides guidance if configuration is missing
  7. ⭐ Prompts for GitHub star

    • Asks if you'd like to support the project
    • Completely optional and non-intrusive

After installation

Once the command completes successfully, you can:

  • Access your admin panel at /admin
  • View tutorial posts (if installed) in the "Blogr Tutorial" category
  • Create your first blog post using the "Blog Posts" section
  • Configure settings in the "Blogr Settings" page
  • Explore dashboard widgets for blog analytics

Troubleshooting

If you encounter issues:

  • Clear caches: php artisan optimize:clear
  • Re-run migrations: php artisan migrate:fresh (⚠️ This will reset your database)
  • Check file permissions: Ensure web server can write to storage directories
  • Verify npm installation: Run npm install && npm run build if needed

Manual installation

If you prefer to install Blogr manually or need more control over the installation process, follow these steps:

  1. Install the package via Composer
composer require happytodev/blogr
  1. Publish configuration and migration files
php artisan vendor:publish --provider="Happytodev\Blogr\BlogrServiceProvider"
  1. Run the migrations
php artisan migrate
  1. Add the plugin in AdminPanelProvider class

Add this line in your file app\Providers\Filament\AdminPanelProvider.php

            ->plugin(BlogrPlugin::make())

Don't forget to import the class :

use Happytodev\Blogr\BlogrPlugin;
  1. Install typography plugin

Run npm install -D @tailwindcss/typography

  1. Add typography plugin in resources\css\app.css

In resources\css\app.css, change :

@import 'tailwindcss';
@import '../../vendor/livewire/flux/dist/flux.css';
...

by

@import 'tailwindcss';
@import '../../vendor/livewire/flux/dist/flux.css';
@plugin "@tailwindcss/typography";
...
  1. Access the blog in Filament

The plugin adds a Filament resource for managing blog posts.
Log in to your Filament admin panel and go to the “Blog Posts” section.

Configuration

You can customize the table prefix in the published config file:
config/blogr.php

Default Open Graph (OG) Image Configuration

To set a default Open Graph image that will be used when your blog posts don't have a specific image:

  1. Place your image in the public/images/ folder of your Laravel application
  2. Edit the file config/blogr.php:
'seo' => [
    // ... other SEO configurations ...
    
    'og' => [
        'type' => 'website',
        'image' => '/images/your-og-image.jpg', // Path to your OG image
        'image_width' => 1200, // Recommended width: 1200px
        'image_height' => 630, // Recommended height: 630px
    ],
    
    // ... other configurations ...
],

Recommendations for OG image:

  • Format: JPG, PNG or WebP
  • Dimensions: 1200x630 pixels (1.91:1 ratio)
  • Size: Less than 1 MB
  • Content: Your site logo or representative image

Logo Configuration for Structured Data

To set your organization's logo in the JSON-LD structured data:

  1. Place your logo in the public/images/ folder of your Laravel application
  2. Edit the file config/blogr.php:
'seo' => [
    // ... other SEO configurations ...
    
    'structured_data' => [
        'enabled' => true,
        'organization' => [
            'name' => env('APP_NAME', 'My Blog'),
            'url' => env('APP_URL', 'https://yourwebsite.com'),
            'logo' => env('APP_URL', 'https://yourwebsite.com') . '/images/your-logo.png',
        ],
    ],
    
    // ... other configurations ...
],

Recommendations for logo:

  • Format: PNG or SVG (transparent preferred)
  • Dimensions: Minimum 112x112 pixels
  • URL Format: Complete absolute URL (with https://)

Complete Configuration Example

'seo' => [
    'site_name' => 'My Awesome Blog',
    'default_title' => 'Blog',
    'default_description' => 'Discover our latest articles',
    'twitter_handle' => '@myblog',
    
    'og' => [
        'type' => 'website',
        'image' => '/images/og-default.jpg',
        'image_width' => 1200,
        'image_height' => 630,
    ],
    
    'structured_data' => [
        'enabled' => true,
        'organization' => [
            'name' => 'My Awesome Blog',
            'url' => 'https://myawesomeblog.com',
            'logo' => 'https://myawesomeblog.com/images/logo.png',
        ],
    ],
],

Reading Time Configuration

Configure the reading time display for your blog posts:

'reading_speed' => [
    'words_per_minute' => 200, // Average reading speed (150-300 recommended)
],

'reading_time' => [
    'enabled' => true, // Enable/disable reading time display
    'text_format' => 'Reading time: {time}', // Customize display text
],

Reading speed recommendations:

  • Slow readers: 150-200 words per minute
  • Average readers: 200-250 words per minute
  • Fast readers: 250-300 words per minute

Complete SEO Configuration

Configure all SEO settings for optimal search engine optimization:

'seo' => [
    'site_name' => env('APP_NAME', 'My Blog'), // Your site name
    'default_title' => 'Blog', // Default title for listing pages
    'default_description' => 'Discover our latest articles and insights', // Default meta description
    'default_keywords' => 'blog, articles, news, insights', // Default meta keywords
    'twitter_handle' => '@yourhandle', // Twitter handle for Twitter Cards
    'facebook_app_id' => '', // Facebook App ID for enhanced Open Graph
    
    'og' => [
        'type' => 'website',
        'image' => '/images/og-default.jpg',
        'image_width' => 1200,
        'image_height' => 630,
    ],
    
    'structured_data' => [
        'enabled' => true,
        'organization' => [
            'name' => env('APP_NAME', 'My Blog'),
            'url' => env('APP_URL', 'https://yourwebsite.com'),
            'logo' => env('APP_URL', 'https://yourwebsite.com') . '/images/logo.png',
        ],
    ],
],

Blog Appearance Configuration

Customize the visual appearance of your blog:

'blog_index' => [
    'cards' => [
        'colors' => [
            'background' => 'bg-green-50', // Background color of blog cards
            'top_border' => 'border-green-600', // Border color of blog cards
        ]
    ]
],

'colors' => [
    'primary' => '#FA2C36' // Primary color for the blog
],

Route Configuration

Configure the blog routes and middleware:

'route' => [
    'prefix' => 'blog', // URL prefix (leave empty for homepage)
    'middleware' => ['web'], // Middleware for blog routes
],

Posts Per Page

Control pagination settings:

'posts_per_page' => 10, // Number of posts displayed per page

Dashboard Widgets

Blogr provides powerful dashboard widgets to help you monitor and manage your blog content effectively. These widgets are automatically available in your Filament dashboard once the plugin is installed.

Available Widgets

📊 BlogStatsOverview

Displays comprehensive statistics about your blog:

  • Total number of posts
  • Published posts count
  • Draft posts count
  • Scheduled posts count
  • Total categories
  • Total tags

Each statistic is displayed with color-coded indicators and descriptive icons.

📝 RecentBlogPosts

Shows a table of the 10 most recent blog posts with:

  • Post title (with tooltip for long titles)
  • Category (with colored badges)
  • Author name
  • Publication status (with color coding: published=green, scheduled=yellow, draft=gray)

⏰ ScheduledPosts

Provides an overview of upcoming scheduled publications:

  • Posts scheduled for future publication
  • Publication dates
  • Quick status overview

📈 BlogPostsChart

Interactive chart showing blog post publication trends:

  • Monthly publication data for the last 12 months
  • Visual representation of content creation patterns
  • Helps identify peak publishing periods

📖 BlogReadingStats

Analytics focused on content engagement:

  • Reading time statistics
  • Average reading times across posts
  • Content performance insights

How to Add Widgets to Your Dashboard

Manual Registration

If you need to customize widget placement or behavior, you can manually register them in your AdminPanelProvider:

use Happytodev\Blogr\Filament\Widgets\BlogStatsOverview;
use Happytodev\Blogr\Filament\Widgets\RecentBlogPosts;
use Happytodev\Blogr\Filament\Widgets\ScheduledPosts;
use Happytodev\Blogr\Filament\Widgets\BlogPostsChart;
use Happytodev\Blogr\Filament\Widgets\BlogReadingStats;

public function panel(Panel $panel): Panel
{
    return $panel
        // ... other configurations ...
        ->widgets([
            BlogStatsOverview::class,
            RecentBlogPosts::class,
            ScheduledPosts::class,
            BlogPostsChart::class,
            BlogReadingStats::class,
        ])
        // ... other configurations ...
}

Widget Customization

Changing Widget Size

Widgets support different column spans:

class CustomBlogStatsOverview extends BlogStatsOverview
{
    protected int | string | array $columnSpan = 'full'; // or 1, 2, 3, etc.
}

Customizing Chart Data

The BlogPostsChart widget can be extended to show different time periods:

class CustomBlogPostsChart extends BlogPostsChart
{
    protected function getData(): array
    {
        // Custom data logic here
        return [
            'datasets' => [
                [
                    'label' => 'Posts per Month',
                    'data' => [10, 15, 8, 12, 20, 18], // Your custom data
                ],
            ],
            'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
        ];
    }
}

Widget Permissions

If you're using Filament's permission system, you can control widget visibility:

class BlogStatsOverview extends BaseWidget
{
    public static function canView(): bool
    {
        return auth()->user()->can('view blog stats');
    }
}

Support

For questions or bug reports, open an issue on GitHub or contact happytodev.

Sponsor

If you like this project, you can support me via GitHub Sponsors.

License

MIT

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.