serhii-f8/filament-studio
Filament Studio is a page builder and lightweight CMS for Laravel Filament. Build dynamic website pages with reusable content blocks, manage content, menus, media, and SEO from a clean Filament admin panel—no separate frontend tooling required.
Prerequisites (verify before installing). You need an existing Laravel app with a working Filament panel. The package's compatibility matrix is the single highest-risk item: check the composer.json require block in the repo for the exact filament/filament, laravel/framework, and php constraints, and confirm the Filament major version matches your panel. Filament has breaking changes across majors, and this package owns Filament resource definitions, so a mismatch is the most likely cause of a failed first install.
Minimal install path
composer require serhii-f8/filament-studio
# inspect what gets published before running it
php artisan vendor:publish --provider="SerhiiF8\FilamentStudio\FilamentStudioServiceProvider"
Then, in order:
config/studio.php (or similarly named config) end to end. Note table prefixes, tenancy switches, and any field-type registry.database/migrations with a timestamp you control, and add a table prefix or at minimum document the table names. Do not depend on vendor migrations running unmodified in production.php artisan migrate against your production database driver, not SQLite.PanelProvider:public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(\SerhiiF8\FilamentStudio\FilamentStudioPlugin::make());
}
Verify the exact plugin class name from the repo's src/ directory — the published material does not include the install snippet.
Where to look first
src/ — the plugin class, the EAV models (collection, field, value/record), and the field-type registry. These tell you the storage shape and whether there is a usable Eloquent surface.database/migrations/ — the actual storage shape. Typed columns vs. a single value column vs. JSON. This determines everything about query performance and indexing.config/ — tenancy and field-type extension points.tests/ — if present, how they assert tenant isolation and schema mutation. If absent, that is a finding.First use case. Do not start with a core domain entity. Pick one bounded, low-blast-radius need: tenant-defined attributes on an existing relational record (e.g. a customer_note-style collection, or a small "asset register" with 3–5 fields including one date, one select, one free-text). This exercises the field types, list-table filtering, and tenancy without putting product-critical data behind an unproven EAV layer.
Sidecar, not system-of-record. Keep the relational core where it is and use Studio only for the sparse, user-defined extension. The reliable pattern is a relational table plus an EAV extension keyed back to it. Store the core record's identifier in a field (or, if the package supports it, a polymorphic/foreign association), and treat the EAV side as derived data you can drop and rebuild. Never migrate existing relational data into the EAV store; that is a one-way door with poor query characteristics on the other side.
Collection-per-domain-object with stable field keys. One collection per concept ("Vendor", "Inspection", "Intake Form"). Use snake_case field keys and treat them as permanent identifiers. Schema edits against live data are the classic EAV failure mode — a rename or type change can orphan values — so establish the naming convention before the first record exists.
Choose field types by query pattern, not by UI richness. The package advertises a large field-type catalog; use it deliberately. Free-text, number, date, and select are the ones you can filter and sort on list tables. Rich/heavy types are fine for detail views but should stay out of the columns you sort and aggregate on.
Wrap it behind your own boundary. Do not let vendor model classes leak into controllers, jobs, or API resources. Create a thin repository/service in your app that exposes findExtension($recordId), saveValues(...), listCollections(). That single seam is what makes a fork or an exit to flat tables a refactor instead of a rewrite.
Seed schemas for environment parity. Define your collections and fields in a seeder or an artisan command rather than clicking them into existence in staging. Otherwise dev, staging, and prod drift and your tests can't assert against a known schema. Re-run it idempotently in CI.
Tenancy: prove isolation at the query layer. If you already use Filament's native multi-tenancy (HasTenants, tenant-scoped panels), check whether Studio participates in that lifecycle or implements a parallel one. Two tenancy mechanisms in one app is a defect generator. Whatever the answer, write a test that authenticates as tenant A and asserts tenant B's records are invisible to every Studio resource — not just the list page.
Versioning: decide what it means before you promise it. "Versioning" here can mean per-record audit history, per-schema versioning, or both. Confirm which is implemented, whether you can diff and restore, and whether history rows survive a field deletion. Use it for audit-style "who changed what" if it holds up; do not assume it satisfies a compliance requirement without verification.
Dashboards and reporting. The dashboard surface is a good fit for operational counts and recent activity. For anything that touches many records — totals, trends, exports — build a read model (a scheduled job writing to a flat aggregate table) instead of aggregating across the EAV value store at request time.
Programmatic access. Imports, background jobs, and any headless consumer need a path that isn't the Filament UI. Confirm whether the package exposes models, a query builder, and events. If not, you are writing raw queries against value tables — workable, but flag it as a maintenance liability and keep it inside the repository boundary.
Authorization. Filament hides what the policy denies, but check that enforcement is server-side and that your policies cover the Studio resources, not just your own. Add a test that a role without the permission gets a 403 on the resource route.
Pin exact versions and treat Filament + Studio upgrades as one change unit. Because the package defines Filament resources, it is tightly coupled to Filament internals. Lock the Filament major in composer.json, run a joint regression suite on upgrade, and review upstream commits rather than trusting semver — the v1.8.0 release notes are only a changelog link, so the notes are not a usable risk record.
Schema mutation is the sharpest edge. Before letting anyone edit a live collection's fields, snapshot the affected value rows. Prefer additive changes (new field) over destructive ones (rename, type change, delete). Test each mutation against a collection that already has records, and check whether it is transactional and whether there is a dry-run.
Filtering and sorting live in the value store. Expect N+1 unless you eager-load, and expect unindexed filtered columns to degrade as rows grow. Inspect the generated query (DB::listen or Telescope) on a list table with a filter and a sort applied — that is the measurement that decides whether the pattern is viable for your volume.
Verify the database driver, not the test suite's driver. EAV implementations frequently lean on JSON columns and driver-specific indexing. SQLite passing the vendor tests is not evidence for MySQL or PostgreSQL.
Watch for a UI-only surface. If there is no first-class query API, every consumer of this data has to go through Filament or raw SQL. That constrains exports, API endpoints, and analytics. Decide that constraint is acceptable before adoption, not after.
Publishing conflicts. If the package ships views or assets, confirm Livewire/Alpine/Tailwind build compatibility. Check php artisan vendor:publish --tag=... output against your existing asset pipeline.
Debugging checklist when a resource 404s or the plugin seems absent:
php artisan optimize:clear # config/route/view caches mask plugin registration
php artisan filament:optimize-clear
php artisan about # confirm the service provider is discovered
php artisan route:list | grep studio
Then check plugin registration order in the PanelProvider, and storage/logs/laravel.log for migration or policy exceptions.
Migrations are supply-chain. Keep your own copies under version control with a documented table prefix, so you can relocate or drop the EAV tables cleanly. A vendor migration you don't control is a rollback hazard.
Maintenance expectation. MIT, single-maintainer namespace, and effectively no dependents means you absorb defect cost. Budget an internal owner and decide in advance whether you are willing to carry a local patch or fork — if not, keep the pilot behind a feature flag with an export-to-flat-tables exit path documented. Extension points to check for: a field-type registry in config (for custom field types), config-driven model swapping (so you can subclass the vendor models), and Filament policies for the generated resources.
How can I help you explore Laravel packages today?