pvtl/voyager-blog
A Laravel Voyager package that adds blog management to the admin panel, providing CRUD for posts, categories, and tags plus frontend-ready models and routes for publishing and displaying articles in your application.
Acknowledge the archive status before anything else. This package is archived and has not tracked Voyager or Laravel releases since. Before installing, check composer.json in the repo for its Laravel/Voyager constraints and confirm they intersect with your app. On a modern Laravel (10+) you will almost certainly need to fork it, bump constraints, and fix type/return declarations yourself. Treat installation as "vendor and own it," not "composer require and forget."
Minimal path:
the-control-group/voyager admin panel) must already be installed, migrated, and have an admin user. This package is a module on top of Voyager's BREAD system, not a standalone blog.php artisan vendor:publish --provider="Pvtl\VoyagerBlog\VoyagerBlogServiceProvider" — to get migrations, seeders, config, and views into your app.database/migrations/ (table names and columns — you will extend them), src/Models/ (relationships and any scopes), the seeder (which BREAD rows and menu items get created), and resources/views/ (whether any frontend templates actually ship, which is often not the case)./admin, open the new Blog menu, create a Category, then a Post with a title, slug, body, and category. Then wire a trivial frontend route in your app (Route::get('/blog', ...)) that queries the Post model and renders the results. The package gives you content modeling and admin CRUD; the public-facing routing and controllers are yours to write.Let BREAD do the schema work, not migrations. The idiomatic Voyager workflow is: add columns via a normal migration, then use the Voyager BREAD editor (or data_rows inserts) to expose them as form fields. Fight the urge to hardcode admin forms — the whole point of this package is that editors manage posts through Voyager's UI.
Relationships are configured in two places. Post→Category (belongsTo) and Post↔Tag (belongsToMany) need both the Eloquent methods on the models and the relationship declared in the BREAD "Relationships" tab so Voyager renders the correct select/multi-select and persists pivot rows. If tags silently don't save, this is the first thing to check.
Frontend integration pattern. Build a thin BlogController with index/show (and optionally category/tag filtered variants), use route model binding on slug, and add query scopes for published state (whereNotNull('published_at')->where('published_at', '<=', now())). Keep the scopes on the model so admin previews and frontend listings share one definition of "published."
Media handling. Featured images normally go through Voyager's media manager, which stores a path string for single-image fields or JSON for multi-image fields. Normalize on read (helper/accessor) so your Blade templates don't care which shape the field returns.
Caching and sidebars. Blog indexes and "recent posts"/category sidebars are read-heavy and rarely change minute-to-minute. Cache rendered fragments keyed by page/category, and clear on Post save via a model observer. A view composer is a clean place to inject categories/tags into layouts.
Extending without forking. Publish the views and override them in resources/views/vendor/.... If you need behavior changes, prefer model observers, extra BREAD fields, and subclassing over editing package source — this keeps your fork delta small, which matters for a package nobody is maintaining.
bread/data_rows/menu_items rows first or write guarded inserts.posts, categories, or tags tables, the package migrations will conflict. Rename or prefix before migrating — retrofitting after data exists is painful.saving hook to slugify from the title when empty and enforce uniqueness, or you will get 404s and duplicate-slug route-binding surprises.published_at null case. A common bug is where('published_at', '<=', now()) excluding drafts correctly but also excluding posts where the field is stored as 0000-00-00 by older MySQL modes. Standardize on NULL for drafts.browse/read/edit/add/delete permissions granted. New admin users seeing an empty blog menu is a permissions issue, not a broken install.php artisan config:clear && php artisan view:clear && php artisan cache:clear after any vendor:publish — stale compiled views are the most common "my changes aren't showing" cause with Voyager modules.bread and data_rows tables directly. Field-name mismatches between data_rows.field and the actual column are the usual culprit when form saves appear to succeed but nothing persists./blog out of the box. Budget time for frontend controllers, views, pagination, and SEO metadata — the package's value is admin CRUD and content modeling, not a finished blog.How can I help you explore Laravel packages today?