Search by

roundly-consulting / posts-for-laravel

mihaliak

A modern, multilingual, SEO-ready blog/posts engine for Laravel with translatable content, a publishing lifecycle, categories, and tags.

Package info

github.com/roundly-consulting/posts-for-laravel

pkg:composer/roundly-consulting/posts-for-laravel

Fund package maintenance!

Patreon

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-10-03 18:40 UTC

This package is auto-updated.

Last update: 2026-10-03 18:54:59 UTC


README

Posts for Laravel — Roundly open source

Latest release Tests Code style Donate Patreon Crypto

Posts for Laravel

A multilingual, SEO-ready blog engine for Laravel: translatable posts with a real publishing lifecycle (draft, scheduled, published, archived), nested categories and tags, per-locale slugs, SEO meta and schema.org structured data, and a polymorphic author of any key type. Featured images, likes and reports come built in through our own media, likes and reports packages.

Installation

Requires PHP 8.4 and Laravel 12 or 13.

composer require roundly-consulting/posts-for-laravel
php artisan vendor:publish --tag="posts-migrations"
php artisan vendor:publish --tag="media-migrations"
php artisan vendor:publish --tag="likes-migrations"
php artisan vendor:publish --tag="reports-migrations"
php artisan vendor:publish --tag="approvals-migrations"
php artisan migrate

If your author models are UUID/ULID-keyed, set POSTS_KEY_TYPE (and POSTS_PRIMARY_KEY_TYPE for the posts' own ids) before migrating. Scheduled posts go live through Schedule::command('posts:publish-scheduled')->everyMinute();.

Usage

Write a post in two languages and publish it (or ->save() a draft, ->schedule($at) it):

use RoundlyConsulting\Posts\DataTransferObjects\SeoData;
use RoundlyConsulting\Posts\Facades\Posts;

$post = Posts::draft()
    ->title('en', 'Hello world')->title('sk', 'Ahoj svet')
    ->perex('en', 'A short intro')
    ->content('en', '<p>…</p>')
    ->by($user)                                   // any author model, bigint/uuid/ulid keyed
    ->tags(['laravel', 'php'])                    // found or created by name
    ->seo(new SeoData(canonical: 'https://example.test/hello-world'))
    ->publish();

$post->getTranslation('title', 'sk');             // 'Ahoj svet'

Read it back — slugs are generated per locale, and {post} route parameters bind by them:

use RoundlyConsulting\Posts\Models\Post;

Posts::findBySlug('hello-world');                 // current locale → fallback → any locale
Posts::published()->latest('published_at')->paginate();
Posts::archive($post);                            // or unpublish() back to draft

Route::get('/posts/{post}', fn (Post $post) => view('posts.show', compact('post')))->name('posts.show');

And render it with its SEO tags and JSON-LD:

{!! $post->renderMetaTags() !!}   {{-- <title>, description, canonical, og:*, twitter:*, robots --}}
{!! $post->renderJsonLd() !!}     {{-- schema.org BlogPosting --}}

<h1>{{ $post->title }}</h1>        {{-- current locale, with fallback --}}
{!! $post->renderContent() !!}    {{-- raw HTML: trusted or sanitized content only --}}

Documentation

The full documentation — configuration, every feature and its API, and testing — lives on our website: roundly-consulting.com/open-source/docs/posts-for-laravel

Release notes are in CHANGELOG.md. To contribute, see the contributing guide.

Support our work

This package is free and open source, built and maintained by Roundly Consulting. If it saves you time, please consider supporting our open-source work — a one-time donation, a monthly pledge on Patreon or a crypto donation helps fund maintenance, new features and new packages.

Donate to Roundly open source Become a patron on Patreon Donate crypto: BTC, ETH, BNB or SOL

License

The MIT License (MIT). See LICENSE.md.