a2insights/filament-saas
Filament SaaS provides scaffolding for building SaaS admin panels with Filament, including publishable migrations, config, and views to get subscription and team management wired into your app quickly. Install via Composer, publish assets, migrate, and extend from there.
This package is not a typical drop-in library — it is a Filament SaaS starter codebase shipped as a Composer package. The README is still the unedited Spatie skeleton (Usage: TODO), so expect to learn the API by reading src/, database/migrations, resources/views and config/ directly rather than from docs.
Prerequisites and install:
# Filament 4 is required from v1.15.0 onward; earlier tags are Filament 3
composer require a2insights/filament-saas:"^1.19@beta"
php artisan vendor:publish --tag="filament-saas-migrations"
php artisan vendor:publish --tag="filament-saas-config"
php artisan vendor:publish --tag="filament-saas-views" # optional
php artisan migrate
Because every release so far is -beta, you will need @beta (or minimum-stability: beta) in composer.json, otherwise Composer silently resolves nothing installable.
Where to look first, in order:
composer.json of the package — it is the real feature list. The dependency graph tells you what ships in the box: bezhansalleh/filament-shield (roles/permissions), pxlrbt/filament-spotlight (command palette), bezhansalleh/filament-exceptions, z3d0x/filament-logger, kenepa/banner, icetalker/filament-picker, malzariey/filament-daterangepicker-filter, ysfkaya/filament-phone-input, amidesfahani/filament-tinyeditor, openai-php/laravel, spatie/laravel-data, blade-ui-kit.database/migrations — reveals the tenancy model (teams/organisations), settings and feature-flag tables introduced in the v1.11 "Settings and Features" epic.config/filament-saas.php — currently an empty array, so there is little to tune; most behaviour is wired through panel/resource classes.First use case: stand up a tenant-aware admin panel in a fresh Laravel + Filament 4 app. Register the package's panel plugins (Shield, Spotlight, exceptions, logger, banner, picker) inside your AdminPanelProvider, enable Filament tenancy against the published tenant model, then log in and generate Shield permissions. A realistic second use case is using the repo as the skeleton for a new SaaS product rather than as a dependency — clone, rename the namespace, and own the code.
Fork-first for greenfield, package-install for existing apps. With 19 stars and 0 dependents there is no ecosystem to lean on, and the history shows repeated namespace renames (the changelog references a2insights/octo-core in v1.7 and two namespace changes in v1.9/v1.10). For a new product, copying the source into your app namespace gives you full control and avoids being blocked by beta churn. Install it as a package only if you genuinely want to track upstream and re-publish on upgrade.
Treat published files as your code, and version them. Publish migrations, config and views once, commit them, and after each package upgrade run a diff against vendor/a2insights/filament-saas to see what changed upstream. Never let vendor:publish --force run blind in CI — it will overwrite your customised views and panel layouts.
Register the plugin stack in your panel provider. Rather than discovering each bundled plugin ad hoc, wire them explicitly in AdminPanelProvider::panel(): ->plugin(ShieldPlugin::make()), Spotlight, exceptions, logger, banner, picker. This makes the dependency set visible to your team and lets you drop plugins you don't want (e.g. openai-php if no AI features are used).
Multi-tenancy pattern. Filament 4 tenancy wants a tenant() model, a ownershipRelationship, and a tenantMiddleware. Map the package's tenant/organisation table to those hooks, and confirm tenant scoping in your own resources by toggling between two tenants in the UI — global-scope leaks in Filament usually show up as cross-tenant record visibility in tables.
Roles and permissions via Shield. Create your own resources, then re-run Shield's permission generation (php artisan shield:generate), otherwise new policies never appear and every action 403s. Seed roles per tenant, not globally, if tenancy is enabled.
Settings and feature flags. The v1.11 epic added settings pages and a features layer. Use these as the home for per-tenant toggles (billing plan gating, widget visibility) rather than inventing a parallel config system; read the settings migration before adding your own columns so you extend the existing table rather than duplicating it.
Localisation. Translations arrived in v1.10. Publish the lang files, set app.locale, and check that the package's resource labels resolve — untranslated keys appear as raw filament-saas::... strings in the UI, which is the fastest way to spot a missing publish.
Testing. composer test runs the package suite; for your own app use Pest/Livewire tests around your overridden resources. spatie/laravel-data DTOs are in play, so test form-to-DTO mapping separately from persistence.
composer require a2insights/filament-saas without a stability flag fails or resolves to an old tag. Pin an exact beta (1.19.0-beta) in production and upgrade deliberately.config('filament-saas.*') keys exist; grep the source before writing conditionals around config. Extension is via published views and class overrides, not config.dd() through vendor/a2insights/filament-saas/src. Use the Filament debug bar plus php artisan about to confirm the panel and plugins loaded; a silently missing plugin is almost always an unregistered provider or a cached panel.ysfkaya/filament-phone-input, giggsey/libphonenumber-for-php, malzariey/filament-daterangepicker-filter, bezhansalleh/filament-shield, etc.). Expect conflicts with plugins already in your app; resolve by aligning on the same major versions the latest tag requires, and upgrade the whole Filament cluster together.app/Filament, Filament render hooks and macros for injecting UI, and the Shield/permission layer for gating your own additions. There is no event bus or contract layer to hook into, so do not design around one.^ range so your team is all debugging the same code.How can I help you explore Laravel packages today?