Framework Defaults
The starter configures several opinionated behaviors across its service providers and bootstrap that differ from stock Laravel. These are active, running defaults that affect how you write code in this application. Understanding them helps avoid surprises.
Eloquent Behavior
Section titled “Eloquent Behavior”Configured in EloquentServiceProvider. These affect every model in the application.
Mass Assignment Unguarded
Section titled “Mass Assignment Unguarded”Model::unguard();Laravel default: Models are guarded, you must declare $fillable or $guarded to allow mass assignment.
Starter behavior: All mass assignment is allowed on all models. $fillable and $guarded are ignored.
Rationale: User input MUST pass through Laravel’s form request validation before reaching models. The validator only returns known validated fields, solving the problem $fillable was designed for, without the maintenance burden of keeping arrays in sync with your schema.
Lazy Loading Prevention
Section titled “Lazy Loading Prevention”Model::preventLazyLoading(! App::isProduction());Laravel default: Lazy loading is allowed everywhere, silently introducing N+1 query problems.
Starter behavior: A two-tier approach:
| Environment | Behavior |
|---|---|
| Local with debug mode | Throws an exception, you see the N+1 immediately |
| Non-production without debug | Throws an exception, caught during testing and CI |
| Production | Silently reports to your exception handler, never breaks for users |
If a lazy loading violation reaches production, it’s reported to Sentry/logs rather than showing an error page.
Missing Attribute Access Prevention
Section titled “Missing Attribute Access Prevention”Model::preventAccessingMissingAttributes(! App::isProduction());Laravel default: Accessing a non-existent attribute silently returns null.
Starter behavior: Throws in non-production, falls back to null in production.
This catches typos during development (e.g., $user->frist_name instead of $user->first_name) that would otherwise silently produce null.
Morph Map Convention
Section titled “Morph Map Convention”Relation::morphMap(array_merge( // Model::MORPH_TYPE => Model::class,));Laravel default: Polymorphic relationships store fully-qualified class names in *_type database columns.
Starter behavior: The morph map is scaffolded but empty. When you add polymorphic relationships, register aliases here so the database stores stable strings (e.g., user) instead of class paths like App\Domains\User\Models\User.
This prevents renaming/moving a model from breaking existing polymorphic references, and keeps implementation details out of the database. The recommended pattern is to define a MORPH_TYPE_MAP constant on each model’s base class and merge it here.
Authentication
Section titled “Authentication”Configured in AppServiceProvider and EagerLoadEloquentUserProvider.
Eager-Loaded Auth User
Section titled “Eager-Loaded Auth User”$this->withQuery(function (Builder $query) { $query->with(['roles.role_type', 'roles.permissions']);});A custom auth user provider (EagerLoadEloquentUserProvider) replaces Laravel’s default EloquentUserProvider. It eager-loads the roles, roles.role_type, and roles.permissions relationships on every authenticated request, preventing N+1 queries when checking authorization.
If you need additional relationships available on the authenticated user, add them to the withQuery callback in this class.
Super Admin Gate Bypass
Section titled “Super Admin Gate Bypass”Gate::before(static function (User $user): ?true { return $user->hasPermissionTo(SystemPermission::ManageAll) ? true : null;});Users with the ManageAll permission bypass all Gate and Policy checks. Every $this->authorize(), @can, and Gate::allows() call returns true for them. This is the mechanism behind super admin access.
HTTP & Security
Section titled “HTTP & Security”Configured in AppServiceProvider and bootstrap/app.php.
Forced HTTPS
Section titled “Forced HTTPS”if (! App::environment(['ci', 'testing'])) { URL::forceScheme('https');}All generated URLs use HTTPS. CI and testing environments are excluded so tests don’t require SSL certificates.
Destructive Command Prohibition
Section titled “Destructive Command Prohibition”DB::prohibitDestructiveCommands(App::isProduction());Commands like migrate:fresh, migrate:refresh, db:wipe, and db:seed --force are blocked in production. This prevents accidentally destroying a production database.
Stray HTTP Request Prevention
Section titled “Stray HTTP Request Prevention”if (App::environment(['ci', 'testing'])) { Http::preventStrayRequests();}In CI and testing environments, any outbound HTTP request made via Laravel’s Http client that hasn’t been explicitly faked will throw an exception. This ensures your test suite doesn’t accidentally make real HTTP calls to external services, verifying that all network dependencies are properly mocked. If you see a stray request error, you need to add Http::fake() for that endpoint.
Untruncated Request Exceptions
Section titled “Untruncated Request Exceptions”if (App::environment(['local', 'ci', 'testing'])) { RequestException::dontTruncate();}In local, CI, and testing environments, HTTP client exceptions include the full response body instead of truncating it. This makes debugging failed API calls significantly easier.
Bootstrap 5 Pagination
Section titled “Bootstrap 5 Pagination”Paginator::useBootstrapFive();Laravel’s paginator renders Bootstrap 5 markup instead of the default Tailwind CSS. This applies to non-Filament views that use {{ $items->links() }}.
Filament Defaults
Section titled “Filament Defaults”Configured in FilamentServiceProvider. These affect the entire admin panel.
User Timezone on All Datetimes
Section titled “User Timezone on All Datetimes”All DateTimePicker, TextColumn, and TextEntry components that display datetime values automatically use the authenticated user’s timezone. This means timestamps are displayed in each user’s local time throughout the admin panel. No manual ->timezone() calls are needed.
Table Defaults
Section titled “Table Defaults”| Setting | Value |
|---|---|
| Default pagination | 25 per page |
| Pagination options | 10, 25, 50, 100 |
| Deferred filters | Disabled (filters apply immediately) |
| DateTime format | From config('platform.datetime_display_format') |
Non-Native Selects
Section titled “Non-Native Selects”All Select and SelectFilter components render as Filament’s custom searchable select instead of the browser’s native <select> element. This provides a consistent, searchable dropdown experience across the admin panel.
Export Defaults
Section titled “Export Defaults”All Filament export actions default to CSV format and write to the s3 disk.
Impersonation Banner
Section titled “Impersonation Banner”An impersonation warning banner is injected at the top of the page body when a user is being impersonated, ensuring administrators always know when they’re acting as another user.
Error Handling
Section titled “Error Handling”Configured in bootstrap/app.php.
RFC 9457 Problem Details for API
Section titled “RFC 9457 Problem Details for API”API routes return errors as structured RFC 9457 Problem Details JSON instead of Laravel’s default error format. This is handled by ProblemDetailsRenderer and applies to all api/* routes and requests that send Accept: application/json.
Database Timeout Handling
Section titled “Database Timeout Handling”When a database connection times out (common with scale-to-zero RDS in non-production), the application renders a custom “database paused” error page instead of a generic 500. In non-production environments, these timeout errors are also suppressed from error reporting to reduce noise during RDS wake-up periods.
Event Auto-Discovery
Section titled “Event Auto-Discovery”->withEvents(discover: [ __DIR__ . '/../app/Domains/*/Listeners',])Laravel’s event auto-discovery is scoped to app/Domains/*/Listeners. Listener classes in these directories are automatically registered without needing an EventServiceProvider. The framework infers the event from the handle() method’s type-hint.