ojessecruz/simple-blog
A ready-to-use Laravel blog package: a clean, reading-focused public listing plus Livewire admin CRUD, Markdown with HTML escaping, and draft previews in a new tab. Auth is left to your own middleware. Install with one command; bring Tailwind.
Architecture fit
Post, PostCategory), a handful of routes, Blade views, and three Livewire admin components. It does not own users, auth, media, or search — which is why it fits cleanly inside a Laravel monolith and awkwardly anywhere else.admin_middleware is host-supplied. This is architecturally correct (no duplicate identity system, no opinion on guard/Gate/role package) but it converts a security control into a configuration step that can be silently skipped.@livewireStyles/@livewireScripts, and a Livewire dependency solely for a blog admin.Integration feasibility
composer require → simple-blog:install → protect admin routes → implement the Author contract on User → npm run build. A competent Laravel developer completes this in well under a day, most of it in layout reconciliation.Author contract (getBlogAuthorName, getBlogAuthorInitials, getBlogAuthorAvatarUrl) and the layout bridge. Both are documented with copy-paste examples, which materially lowers the cost.@yield-based and the admin side is slot-based ({{ $slot }}), so apps with an existing <x-app-layout> need a three-line wrapper for public and can point admin straight at the slot layout. Cheap, but it is bespoke glue that must be maintained.simple-blog:install command edits resources/css/app.css in the host repo. Idempotency is claimed; it must still be reviewed as a source change in the PR, and it is a no-op-with-instructions when that file is absent (e.g., apps not using Vite, or using Sass).Technical risk
admin_route_prefix return 302/403.Post::published() used #[Scope], which only exists in Laravel 12+, breaking the advertised Laravel 11 support with an ArgumentCountError; and blog::admin.* component names broke under Livewire 4 because :: is reserved for namespace resolution. Both are fixed and CI was widened — but this is direct evidence that the README's version range has historically run ahead of reality. Treat the matrix as a claim to verify, not a guarantee.simple-blog-views-public, -admin, -layouts) — adopt a policy of publishing only the slice you actually need to restyle.@push('head'); a custom layout missing @stack('head') produces a correctly rendering blog with no metadata and no error. Add to the acceptance checklist.Key questions
admin_middleware — is it ['web'] (open by default) or something fail-closed? This determines whether the top risk is "documentation discipline" or "an insecure default."@source) both covered?published_at / slug / category_id indexed in the published migrations?published_at scope (no scheduler required), and how are timezones handled?LIKE scans, and is there any caching layer, or is that entirely the host's responsibility?blog.index, blog.show), and is there guidance for prefix collisions?Stack fit
vendor/ paths imported into app.css; or the app uses a component library with conflicting base styles.Migration path
posts table), plan a one-off import into Post/PostCategory, preserve slugs and published_at verbatim, and generate 301s for any URL shape change. Do not let the package's slug generation rewrite historical URLs.composer remove, drop posts/post_categories, delete published views/config, revert the app.css import. Half a day, no data loss beyond the blog content itself.Compatibility
composer.json (e.g. 0.7.*) rather than a caret range, given pre-1.0 status. Let Renovate/Dependabot open PRs and gate them on the full test suite plus the admin-authorization and SEO smoke tests.scopePublished() fix is in the version you install (0.5.0+); if you are on Livewire 4, confirm 0.5.0+ for the dotted component names.@import of resources/css/simple-blog.css) versus v3 (content array entry) explicitly, and set 'assets' => [] if your layout already loads CSS through @vite to avoid double-loading.blog. before merging.Sequencing
Author contract, point layouts at a wrapper, build, and eyeball both surfaces. This surfaces every real integration cost, in practice mostly Tailwind and layout.admin_middleware with the app's real guard/Gate; add automated tests for unauthenticated and unauthorized access to every admin route including preview and categories. Merge only with these green.@stack('head') is present in the public layout and that a published post emits <title>, OG tags, and JSON-LD. Confirm public_back_url/admin_back_url are set or deliberately null.cta_view if a conversion surface is wanted.Maintenance
published_at-scoped reads, verify no scheduler is required). The operational envelope is "one more set of routes and two tables in the app you already run."Support
Scaling
published_at, slug, and category_id are indexed; a published() + latest('published_at') listing without those indexes degrades predictably.LIKE-based; acceptable for a small editorial team, not for a large content operation.Failure modes
admin_middleware exposes write access at a guessable URL. Detect with automated 403/302 assertions; this is the one failure worth blocking a release on.@source/@import missing, or v3 content array not updated). Renders semantically correct, visually broken. Detect in the deploy smoke test / visual check.@stack('head'); page renders fine, head is empty. Detect by asserting on rendered HTML in a test.author_model not implementing Author, or getBlogAuthorAvatarUrl() returning something unexpected; surfaces as a render-time error on the public show page.blog.* names; link generation silently targets the wrong route.::-namespace class of failure. Detect by running the integration suite on every dependency bump, not just on release.Ramp-up
How can I help you explore Laravel packages today?