Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Cms Laravel Package

tomatophp/filament-cms

Full CMS builder for Filament: manage posts, categories, and content with built-in comments and ratings, multi-meta and SEO fields, plus import/export of integrations. Install with Composer, run filament-cms:install, then register the FilamentCMSPlugin in your admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

Requirements first. Pick the package branch that matches your Filament major: v1–v3 for Filament v3-era apps, v4 for Filament v4, and v5 (released 2026-10-13) for Filament v5 + Laravel 12/13 on PHP 8.2+. The README's caution is serious: jumping v1 → v4 loses features that were split out into "integrated packages," so a legacy install should be treated as a migration project, not a composer update.

composer require tomatophp/filament-cms
php artisan filament-cms:install

The installer wires up config and the Spatie settings/translatable dependencies the package leans on (spatie/laravel-settings, lara-zeus/spatie-translatable in v5). Before you trust it, publish and inspect what it wrote:

php artisan vendor:publish --tag="filament-cms-config"
php artisan vendor:publish --tag="filament-cms-migrations"
php artisan migrate

Register the plugin in your panel provider — this is where day-to-day behaviour is decided, since Post and Category resources only appear if you ask for them:

->plugin(
    \TomatoPHP\FilamentCms\FilamentCMSPlugin::make()
        ->useCategory()
        ->usePost()
        ->allowExport()
        ->allowImport()
)

Drop useCategory() if you're managing taxonomy elsewhere; drop allowImport()/allowExport() if content editors shouldn't move data around.

Where to look first. Open the Post resource in the panel and create one post end-to-end — title, body, SEO tab, category, author. That single pass shows you the shape of the data model (posts with multi-meta, categories, comments/ratings) and tells you quickly whether the default form matches your content model. If your content isn't a "post," don't fight the form — register a custom type in AppServiceProvider::boot():

use TomatoPHP\FilamentCms\Facades\FilamentCMS;
use TomatoPHP\FilamentCms\Services\Contracts\CmsType;

FilamentCMS::types()->register([
    CmsType::make('building')
        ->label('Buildings')
        ->icon('heroicon-o-home')
        ->color('danger'),
]);

That's the first real use case: one CMS install, several editorial content types, each with its own label/icon/badge in the admin.

Frontend is yours. This is an admin-side CMS. There's no documented public routing or Blade rendering in the README, so plan on your own controller/route/resource layer (or a headless JSON endpoint) reading the Post model. Budget for that; don't assume the package ships a blog.

Implementation Patterns

Model your authors before you seed content. The default author binding is the auth user model, but registration makes it explicit and multi-source:

use TomatoPHP\FilamentCms\Services\Contracts\CmsAuthor;

FilamentCMS::authors()->register([
    CmsAuthor::make('Admin')->model(\App\Models\User::class),
]);

This is the pattern to copy whenever the package offers a register()/types() style registry: resolve it once in boot(), keep it declarative, and let the package own the wiring.

Extend resources through the registries rather than forking. Post and Category expose six extension points each — form, table columns, row actions, bulk actions, filters, infolist entries. A typical client request ("add a custom_field, show it in the table and the view page, filter on it") becomes three small registrations in one provider, no vendor edits:

PostForm::register([TextInput::make('custom_field')->label('Custom Field')->required()]);
PostTable::register([TextColumn::make('custom_field')->label('Custom Field')->sortable()->searchable()]);
PostInfoList::register([TextEntry::make('custom_field')->label('Custom Field')]);
PostFilters::register([
    Filter::make('custom_field')
        ->form([TextInput::make('custom_field')])
        ->query(fn ($query, array $data) => $query->when(
            $data['custom_field'],
            fn ($q, $v) => $q->where('custom_field', 'like', "%{$v}%")
        )),
]);

For anything reused across panels or packages, wrap it in a class extending Component / Column / Entry and register CustomFieldComponent::make(). That keeps the provider short and makes the component testable in isolation.

Keep side effects in the events, not in the form. PostCreated, PostUpdated, PostDeleted are the sanctioned hook for notifications, search indexing, cache busting, webhooks. Register listeners the normal Laravel way; pass $event->post (verify the property name against the source) into a queued job so editorial saves stay fast.

Import/export as an integration surface. allowImport()/allowExport() gives you the built-in content transfer, and FilamentCMS::registerImportAction(Action::make('import')) lets you bolt on your own source (a legacy WordPress dump, a partner feed, an internal API). Realistic workflow: export a CSV/JSON snapshot from staging, transform it offline, then import into production with your custom action so the mapping logic lives in your codebase rather than in someone's spreadsheet.

Comments and ratings are the "community" half of the feature list. Treat them as an admin moderation queue: filter by unapproved, bulk-action to approve/spam, and only then expose them publicly from your own controller.

Gotchas and Tips

  • The README has namespace typos. You'll see both TomatoPHP\FilamentCms\Facades\FilamentCMS and TomatoPHP\FilamentCms\Facade\FilamentCMS (singular, in the import-action snippet). The plural Facades is correct — the singular one will throw a class-not-found if you copy it verbatim. Grep the installed package's src/Facades directory to confirm.
  • Filament action namespaces shifted across majors. The README mixes Filament\Tables\Actions\Action with Filament\Actions\Action, and mentions Filament\Schemas\Components\Component (v4+) alongside Filament\Forms\Components\Field. Resolve imports against your installed Filament version before blaming the package.
  • v1.0.7 existed solely to fix Spatie\LaravelSettings\Migrations\SettingsMigration not found. If your install fails at migrate time, that's the settings package not being pulled in or its migrations not published — fix the dependency, don't hand-write the table.
  • Order matters on fresh installs: filament-cms:install → publish config/migrations → migrate → then open the panel. Opening the panel first on an unmigrated database gives confusing resource errors.
  • Register in boot(), and be aware of panel scope. FilamentCMS::types() and friends are global; FilamentCMSPlugin flags are per-panel. If you register types inside a panel provider's register(), they may not be available when the resource schema is built.
  • Translatable posts need Spatie set up. v5 pulls lara-zeus/spatie-translatable, which assumes spatie/laravel-translatable conventions on the model, the *_translations columns, and a locale list. If your app has a custom locale switcher, verify it agrees with Filament's.
  • author select and filter use the configured auth user model (v5 changelog) — if you've pointed CmsAuthor at a non-default model, re-check the author filter after upgrading; earlier versions hardcoded the assumption.
  • Tiny ecosystem, so pin versions. 126 stars and zero dependents means you are effectively the QA team. Commit composer.lock, read src/ when behaviour surprises you (the code is the documentation here), and avoid ^ ranges on the CMS package across Filament majors.
  • Version upgrades are content migrations. Soft deletes were added to the categories migration in v1.0.8, and v5 changed class-name casing on case-sensitive filesystems. Run php artisan migrate and check git diff on published migrations after every bump; a category that "disappeared" is usually a deleted_at column that arrived late.
  • Use the shipped factories for tests. v5 added Post/Category factories plus install/plugin tests — lean on them in your own Pest suite rather than hand-building fixtures, and mirror the package's composer test / composer analyse setup so extension code stays green.
  • Debugging resource extension: if a registered component doesn't render, temporarily dump the registry (or breakpoint the static register()/get() on PostForm) to confirm your provider ran after the package's. Panel providers and AppServiceProvider ordering is the usual culprit.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table