relaticle / ink
Filament-native content publishing for blog, docs, and AI-citable articles. Headless by default, with opt-in public routes.
Requires
- php: ^8.4
- filament/filament: ^5.0
- illuminate/contracts: ^12.0|^13.0
- ralphjsmit/laravel-filament-seo: ^2.0
- ralphjsmit/laravel-seo: ^1.7
- spatie/laravel-markdown: ^2.7
- spatie/laravel-package-tools: ^1.15
- spatie/laravel-sitemap: ^7.0 || ^8.0
- spatie/laravel-sluggable: ^3.0
Requires (Dev)
- laravel/mcp: ^0.5
- laravel/pint: ^1.14
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
This package is auto-updated.
Last update: 2026-05-13 21:27:51 UTC
README
Filament-native content publishing for blog, docs, and AI-citable articles. Ships Eloquent models, a full Filament admin, MCP tools for AI agents, SEO components, publishable Blade UI components, and an opt-in public-routes mode for hosts that want a working blog without writing controllers.
Features
- Filament Admin — PostResource and CategoryResource with markdown editor, draft/published/scheduled UX, SEO fields, featured images, and bulk publish/unpublish/schedule actions
- SEO Components — Meta tags, Open Graph, Twitter Cards, RSS feed, per-page canonicals on paginated listings
- JSON-LD Schema —
BlogPosting+BreadcrumbListon post pages,FAQPageandHowToauto-detected from content (opt-in),Blog+CollectionPageon listings - Search — Portable
Post::search()scope (LIKE by default, override for FTS / Scout), drop-inBlogSearchLivewire component with?q=URL sync - 13 MCP Tools — Full CRUD for posts and categories via Model Context Protocol, with markdown sanitization (HTML stripped, unsafe links blocked)
- Publishable UI Components — Post card, header, body, related posts, category badge, preview banner — all with dark mode
- Two install modes
- Headless (default) — define your own routes/controllers, use the Blade components
- Public-routes mode (opt-in) — flip a config flag, get
/blog,/blog/{slug},/blog/category/{slug}, signed/blog/preview/{post}, and optional/blog/feed
- Tags taxonomy (opt-in via
features.tags) — many-to-manyblog_post_tagtable,TagResourceadmin UI, public archive at/blog/tag/{slug} - MediaLibrary integration (opt-in via
features.media_library) — when both the flag is on ANDspatie/laravel-medialibraryis installed, the featured-image upload usesSpatieMediaLibraryFileUploadinstead of the plainFileUpload. Falls back gracefully if MediaLibrary isn't installed. - Sitemap Generator — Route-aware sitemap integration via spatie/laravel-sitemap
- Reading-time + related-posts helpers on the Post model
Requirements
- PHP 8.4+
- Laravel 12+ or 13
- Filament 5.x
Installation
composer require relaticle/ink
Register the plugin and run migrations:
// AppPanelProvider.php ->plugin(\Relaticle\Ink\InkPlugin::make())
php artisan migrate
Public-routes mode (opt-in)
By default this package is fully headless: no routes, no controllers, no forced views. Your app owns all rendering.
To get a working blog at /blog without writing any controllers, flip the feature flag:
// config/ink.php 'features' => [ 'public_routes' => true, // /blog, /blog/{slug}, /blog/category/{slug}, /blog/preview/{post} 'feed' => true, // adds /blog/feed (RSS 2.0) 'tags' => true, // /blog/tag/{slug}, TagResource in admin 'media_library' => true, // SpatieMediaLibraryFileUpload (requires spatie/laravel-medialibrary) ], 'layout' => 'layouts.app', // your host layout to extend
Routes register at the service-provider level — no Filament panel boot is required, so the public site keeps working for guests who never touch the admin.
Publish the views if you want to customize them:
php artisan vendor:publish --tag=ink-views
Documentation
Quick Example (headless)
{{-- In your blog show page --}} <x-your-layout> @push('head') <x-ink::meta-tags :post="$post" /> <x-ink::feed-link /> @endpush <x-ink::structured-data :post="$post" /> <x-ink::post-header :post="$post" /> <x-ink::post-body :post="$post" /> <x-ink::related-posts :post="$post" /> </x-your-layout>
License
MIT