russelcruz28/filament-demo-mode
A Filament plugin that adds a safe demo mode to your admin panel, letting you showcase apps without risking data changes by restricting destructive actions while keeping the interface fully explorable.
What this package is: A persistent, installation-wide SQLite sandbox for Laravel apps, with a user/role picker and Filament integration. In practice you use it to "become" a real user and exercise the real UI against a clone of your data, without writes ever reaching the production database. The 0.1.0 release is the first public cut, so treat the API as unstable.
Minimum steps to first value:
composer require <vendor>/<package> — then confirm the service provider is picked up. Laravel auto-discovery is enabled in 0.1.0, but the Filament plugin still needs explicit registration (see below).php artisan vendor:publish --tag="<package>-config"
The config is the real documentation for this package — model selection, adapter choice, restore policy, and the production guard all live there.php artisan <package>:install
php artisan <package>:doctor
The doctor command is your first stop for every problem. Run it after install, after every composer update, and after every migration.->plugin(\Vendor\Package\Filament\SandboxPlugin::make())
Where to look first, in order: the published config file → the doctor command output → the ApplicationAdapter contract (this is where the package hooks into your app's bootstrapping) → the published views if you want to change the picker.
The single-sandbox model is the core mental model. There is exactly one sandbox per installation, not one per developer and not one per user. Everything else follows from that: it is a shared, long-lived artifact, and your team workflow has to treat it like a shared staging database rather than a scratch file.
Persistent + indefinite restore — use it as a fixture, not a transaction. The intended flow is: sync the sandbox once, restore it as often as you like, and never worry about mutations. Wire the restore into your local workflow rather than doing it by hand:
// config/<package>.php or a service provider callback
'callbacks' => [
'after_restore' => fn () => Artisan::call('cache:clear'),
],
Model selection is where most of your setup time goes. You enumerate which Eloquent models get cloned. Get this right:
Custom application adapters are the extension point when the default "boot the app against SQLite" behaviour doesn't match your setup — multi-tenant resolution, custom connection routing, or a non-standard user model. Implement the adapter contract and point config at your class; don't fork the package for this.
Spatie integration is on by default. The role picker assumes Spatie's permission tables exist and are cloned. If you use a different authorisation package, this is the first thing to switch off/replace in config, otherwise the picker will render empty or error on boot.
Callbacks over subclassing. Before/after hooks (sandbox boot, impersonation start/stop, restore) let you add logging, notifications, or cache invalidation without touching package internals. Keep them idempotent and fast — they run inline in the request/boot path.
Filament registration is separate from Laravel auto-discovery. If the picker doesn't appear, it's almost always a missing ->plugin() call on the panel, not a discovery failure.
Testing pattern: lift the package's own standalone tests as a template for asserting your config is valid. Add a CI job that runs the doctor command against a clean checkout — it catches model-selection drift after schema changes far earlier than a manual smoke test.
git pull checklist. A doctor failure after a migration is usually exactly this.PRAGMA foreign_keys=ON in the boot callback and don't trust the sandbox for numeric/date edge cases.composer.json. Expect breaking changes to config keys and the adapter contract in any 0.x bump; re-read the config after upgrading rather than assuming published config files are merged.before_* callback looks like a sandbox failure, not a bug in your callback. Wrap them in try/catch with a log line if you add non-trivial logic.How can I help you explore Laravel packages today?