websanova/larapost
Larapost is a Laravel package for quickly adding post and article management to your application, handling common backend pieces so you can focus on building and customizing the frontend. A simple starting point for blogs and content-driven sites.
Larapost is a small, opinionated blog package: it ships models, migrations, admin CRUD screens, and front-end routes for posts (and usually categories/tags/comments). Treat it as a lightweight CMS you can stand up in an afternoon, then customize through published views and model subclassing rather than editing vendor/.
First, check compatibility before installing:
composer show websanova/larapost --all
Look at its composer.json constraints for laravel/framework and php. This package predates Laravel's package auto-discovery era, so assume you must register the service provider manually unless your installed version says otherwise.
Install and publish:
composer require websanova/larapost
# Laravel 5.4 and below: config/app.php
# Websanova\Larapost\LarapostServiceProvider::class
php artisan vendor:publish --provider="Websanova\Larapost\LarapostServiceProvider"
php artisan migrate
If vendor:publish prompts for tags, publish config, migrations, views, and assets separately:
php artisan vendor:publish --provider="Websanova\Larapost\LarapostServiceProvider" --tag=config
php artisan vendor:publish --provider="Websanova\Larapost\LarapostServiceProvider" --tag=views
php artisan vendor:publish --provider="Websanova\Larapost\LarapostServiceProvider" --tag=assets
Then discover the actual URLs:
php artisan route:list | grep -i -E 'blog|post|larapost'
Where to look first:
vendor/websanova/larapost/src/LarapostServiceProvider.php — what gets registered: routes, views, migrations, config, middleware.src/Http/routes.php (or equivalent) — route prefixes, names, and middleware. This tells you whether the package exposes /blog, /admin/blog, or something else.config/larapost.php — route prefix, middleware, model mappings, upload paths, pagination.src/Models/ — Post, Category, Tag, Comment and their relationships/scopes.resources/views/ — the Blade templates you will likely override.database/migrations/ — table names and columns before you run them against an existing schema.First use case: open the admin route, create a category, create a post with a title, slug, body, and published state, then view it on the front-end route. If the admin UI is not what you need, create content programmatically:
use Websanova\Larapost\Models\Post;
use Websanova\Larapost\Models\Category;
$category = Category::firstOrCreate(['name' => 'News']);
$post = Post::create([
'title' => 'Hello World',
'slug' => 'hello-world',
'content' => '<p>First post.</p>',
'category_id' => $category->id,
'user_id' => auth()->id(),
'published_at' => now(),
]);
Confirm the actual fillable fields in the model before copying that snippet — older packages often use published booleans rather than published_at timestamps.
Use the package as an admin CMS, not as your application architecture. Let authors create posts in Larapost's admin, but render them through your own controllers and views when you need control over layout, SEO, caching, or JSON APIs. The package models are ordinary Eloquent models, so you can query them anywhere:
$posts = Post::with(['category', 'tags', 'author'])
->where('published_at', '<=', now())
->latest('published_at')
->paginate(12);
Override views, don't edit vendor files. Publish views into resources/views/vendor/larapost/ and change the layout, pagination partial, or post card markup there. If the published views extend a package layout, point them at your application layout instead.
Extend models through subclassing when you need custom behavior. If the config exposes a model map, point it at your subclass; otherwise use your own model and query the same tables:
namespace App\Models;
use Websanova\Larapost\Models\Post as BasePost;
class Post extends BasePost
{
protected $fillable = [
'title', 'slug', 'content', 'category_id',
'user_id', 'published_at', 'featured',
];
public function scopePublished($query)
{
return $query->where('published_at', '<=', now());
}
public function getRouteKeyName()
{
return 'slug';
}
}
If config/larapost.php supports a models array, wire it up:
'models' => [
'post' => App\Models\Post::class,
],
Add custom fields with a normal migration. Add columns to the package's posts table, extend $fillable, then override the admin form view to expose the field. This is usually cleaner than forking the package.
Protect the admin routes explicitly. The package may only apply the web middleware group. Wrap its admin prefix with auth and an authorization gate:
// AppServiceProvider or a dedicated middleware
Gate::define('manage-blog', function ($user) {
return $user->is_admin;
});
Then either configure the package's middleware in config/larapost.php or define your own route group that reuses the package controllers.
Disable or bypass front-end routes when integrating into an existing site. If the package's /blog routes conflict with your app, change the route prefix in config, or register your own routes and call the package models directly. Use php artisan route:list to see exactly what is registered before deciding.
Use Eloquent events for cross-cutting behavior. Slugs, excerpts, reading time, cache invalidation, and search indexing can be handled with saving/saved observers on the package models rather than editing vendor code.
For comments, build moderation into your workflow. If the package includes comments, expose only approved comments on the front-end, add spam protection (honeypot or reCAPTCHA), and consider closing comments entirely if the package's moderation tooling is thin.
Seed and import through models. For migrations from another blog, write an artisan command that maps old records to Post::create() calls. Use firstOrCreate on slugs to make imports idempotent.
composer why-not websanova/larapost before assuming it will install. If you are on a modern Laravel version, plan to fork it into packages/larapost or reimplement the schema/models rather than fight Composer constraints.config/app.php (or auto-discovery is not supported).php artisan config:clear, route:clear, and view:clear solve most "my changes aren't showing" problems.posts, categories, and tags. If your app already has a posts table, rename the package tables in the published migration or run it against a separate schema.auth plus a gate; do not rely on obscure URLs for security.{!! $post->content !!}). If non-trusted users can author posts, sanitize with HTMLPurifier or an equivalent before storage or output.Str::slug() and enforce a unique index. Append -2, -3 suffixes on conflict, and exclude the current record when validating uniqueness.public/uploads or a public disk. Run php artisan storage:link if the package uses storage/app/public, and verify the path in config/larapost.php and the published views. Broken images are almost always a path or symlink issue.auth()->user() or use the default web guard. If your app uses a custom guard or multi-auth setup, override the relevant controller/model behavior or set the guard in config.->paginate() yourself in your own views.category, tags, and author relationships when listing posts.getRouteKeyName() in your subclass if you want /blog/hello-world URLs.config/larapost.php do nothing in production, run php artisan config:clear and redeploy.RefreshDatabase and the package migrations so tests cover the real schema.src/ and migrations into your app or a local path repository is often faster and safer than waiting for upstream compatibility. Once forked, you control the routes, middleware, and model behavior.How can I help you explore Laravel packages today?