Home PHP Laravel Filament: Rapid Admin Panel Development Guide
Intermediate 4 min · July 13, 2026

Laravel Filament: Rapid Admin Panel Development Guide

Learn to build production-ready admin panels with Laravel Filament.

N
Naren Founder & Principal Engineer

20+ years shipping production PHP systems at scale. Written from production experience, not tutorials.

Follow
Production
production tested
July 13, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 20-30 min read
  • Basic knowledge of Laravel (models, migrations, routing).
  • PHP 8.0+ and Laravel 8+ installed.
  • Familiarity with Composer and npm.
  • Understanding of MVC pattern and Eloquent ORM.
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Filament is a Laravel package for building admin panels with minimal code.
  • It provides pre-built UI components like forms, tables, and widgets.
  • Resources map to Eloquent models for CRUD operations.
  • Custom pages and actions extend functionality.
  • Includes built-in authentication and authorization.
✦ Definition~90s read
What is Laravel Filament?

Laravel Filament is a rapid development toolkit for building beautiful, production-ready admin panels using Laravel and Livewire.

Think of Filament as a set of pre-fabricated building blocks for an admin dashboard.
Plain-English First

Think of Filament as a set of pre-fabricated building blocks for an admin dashboard. Instead of writing every line of HTML and CSS from scratch, you snap together ready-made pieces like forms, tables, and buttons. It's like using LEGO to build a house instead of carving each brick from stone.

Building an admin panel from scratch is tedious and error-prone. You need to handle authentication, CRUD operations, form validation, data tables, and more. Laravel Filament simplifies this by providing a rapid development toolkit that generates beautiful, responsive admin interfaces with minimal code.

Filament is built on top of Laravel and uses Livewire for dynamic interactions. It offers a rich set of components: resources (for CRUD), forms, tables, widgets, notifications, and custom pages. With Filament, you can create a fully functional admin panel in hours instead of days.

In this tutorial, you'll learn how to install Filament, create resources for your models, customize forms and tables, add custom pages, and implement security best practices. We'll also cover real-world scenarios like handling file uploads, using relationships, and optimizing performance.

By the end, you'll be able to build production-ready admin panels that are both developer-friendly and user-friendly.

Installing Filament

To get started, you need a Laravel application (version 8 or higher). Install Filament via Composer:

``bash composer require filament/filament ``

``bash php artisan filament:install --panels ``

This command creates a panel provider (e.g., app/Providers/Filament/AdminPanelProvider.php) and publishes the configuration file. You can customize the panel's path, middleware, and other settings in this file.

Next, create a user with admin privileges. Filament uses Laravel's authentication, so you can use the default User model. Run migrations and create a user:

``bash php artisan migrate php artisan tinker > \App\Models\User::create(['name' => 'Admin', 'email' => 'admin@example.com', 'password' => bcrypt('password')]); ``

Now, access your admin panel at /admin. Log in with the credentials you created. You should see the default Filament dashboard.

Key Takeaway: Filament installation is straightforward. The panel provider is the central configuration point for your admin panel.

AdminPanelProvider.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php

namespace App\Providers\Filament;

use Filament\Panel;
use Filament\PanelProvider;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->login()
            ->colors([
                'primary' => '#6366f1',
            ])
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
            ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
            ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
            ->middleware([
                'web',
                Authenticate::class,
            ]);
    }
}
💡Use the Default Panel
📊 Production Insight
In production, ensure you set the APP_URL in your .env file to avoid asset loading issues. Also, use HTTPS for secure communication.
🎯 Key Takeaway
Installation is quick: require the package, run the install command, and configure the panel provider.

Creating Your First Resource

Resources are the core of Filament. They map to Eloquent models and provide CRUD interfaces. Let's create a resource for a Post model.

``bash php artisan make:model Post -m ``

``php Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('content'); $table->boolean('is_published')->default(false); $table->timestamps(); }); ``

``bash php artisan migrate ``

``bash php artisan make:filament-resource Post ``

This generates a resource class at app/Filament/Resources/PostResource.php. Open it and define the form and table schemas.

Form Schema:

``php public static function form(Form $form): Form { return $form ->schema([ TextInput::make('title')->required()->maxLength(255), RichEditor::make('content')->required(), Toggle::make('is_published'), ]); } ``

Table Schema:

``php public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('title')->searchable(), IconColumn::make('is_published')->boolean(), TextColumn::make('created_at')->dateTime(), ]) ->filters([ Filter::make('is_published'), ]) ->actions([ EditAction::make(), DeleteAction::make(), ]) ->bulkActions([ BulkActionGroup::make([ DeleteBulkAction::make(), ]), ]); } ``

Now, navigate to /admin/posts in your browser. You'll see a fully functional CRUD interface with forms, tables, and actions.

Key Takeaway: Resources auto-generate CRUD interfaces. Customize forms and tables using Filament's rich component library.

PostResource.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

namespace App\Filament\Resources;

use App\Filament\Resources\PostResource\Pages;
use App\Models\Post;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;

class PostResource extends Resource
{
    protected static ?string $model = Post::class;

    protected static ?string $navigationIcon = 'heroicon-o-document-text';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('title')
                    ->required()
                    ->maxLength(255),
                Forms\Components\RichEditor::make('content')
                    ->required(),
                Forms\Components\Toggle::make('is_published'),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('title')->searchable(),
                Tables\Columns\IconColumn::make('is_published')->boolean(),
                Tables\Columns\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                Tables\Filters\Filter::make('is_published'),
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
                Tables\Actions\DeleteAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListPosts::route('/'),
            'create' => Pages\CreatePost::route('/create'),
            'edit' => Pages\EditPost::route('/{record}/edit'),
        ];
    }
}
🔥Resource Discovery
📊 Production Insight
Use ->searchable() on columns to enable search. For large datasets, consider using ->sortable() and pagination.
🎯 Key Takeaway
Resources provide a complete CRUD interface with minimal code. Customize forms and tables to fit your needs.

Customizing Forms with Validation and Relationships

Filament forms are highly customizable. You can add validation rules, handle relationships, and use advanced components.

Validation: Add rules using methods like ->required(), ->email(), ->unique(), etc. For custom rules, use ->rule(new CustomRule).

Relationships: Use Select or CheckboxList for belongs-to or many-to-many relationships. For example, if a post belongs to a category:

``php Select::make('category_id') ->relationship('category', 'name') ->required(), ``

File Uploads: Use FileUpload component:

``php FileUpload::make('featured_image') ->image() ->directory('posts') ->visibility('public'), ``

Repeater for nested forms: Use Repeater for dynamic rows:

``php Repeater::make('tags') ->relationship('tags') ->schema([ TextInput::make('name')->required(), ]), ``

Conditional fields: Use hidden() or visible() based on other field values:

``php TextInput::make('discount') ->visible(fn (Get $get) => $get('has_discount')), ``

Key Takeaway: Filament forms support validation, relationships, file uploads, and dynamic fields. Use the Get and Set utilities for conditional logic.

PostResource.php (form method)PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static function form(Form $form): Form
{
    return $form
        ->schema([
            TextInput::make('title')
                ->required()
                ->maxLength(255)
                ->unique(ignoreRecord: true),
            Select::make('category_id')
                ->relationship('category', 'name')
                ->required(),
            RichEditor::make('content')->required(),
            FileUpload::make('featured_image')
                ->image()
                ->directory('posts')
                ->visibility('public'),
            Toggle::make('is_published'),
            Repeater::make('tags')
                ->relationship('tags')
                ->schema([
                    TextInput::make('name')->required(),
                ]),
        ]);
}
⚠ File Upload Security
📊 Production Insight
For large file uploads, consider using queue jobs to process them asynchronously. Also, set up a storage disk for public files.
🎯 Key Takeaway
Forms can handle complex scenarios like relationships, file uploads, and dynamic fields with ease.

Building Custom Pages and Widgets

Beyond resources, Filament allows you to create custom pages and widgets for dashboards or specialized views.

Custom Pages: Create a page with:

``bash php artisan make:filament-page Settings ``

This generates a page class. You can add forms, tables, or any Livewire component. For example, a settings page with a form:

```php use Filament\Pages\Page;

class Settings extends Page { protected static ?string $navigationIcon = 'heroicon-o-cog';

protected static string $view = 'filament.pages.settings';

public $name; public $email;

public function mount(): void { $this->form->fill([ 'name' => auth()->user()->name, 'email' => auth()->user()->email, ]); }

public function submit(): void { $this->validate(); auth()->user()->update($this->form->getState()); Notification::make()->success()->title('Settings saved.')->send(); }

protected function getFormSchema(): array { return [ TextInput::make('name')->required(), TextInput::make('email')->email()->required(), ]; } } ```

Widgets: Create a widget for the dashboard:

``bash php artisan make:filament-widget StatsOverview ``

```php use Filament\Widgets\StatsOverviewWidget as BaseWidget; use Filament\Widgets\StatsOverviewWidget\Stat;

class StatsOverview extends BaseWidget { protected function getStats(): array { return [ Stat::make('Total Posts', Post::count()), Stat::make('Published Posts', Post::where('is_published', true)->count()), Stat::make('Users', User::count()), ]; } } ```

Key Takeaway: Custom pages and widgets extend Filament beyond CRUD. Use them for settings, reports, or any custom functionality.

Settings.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

namespace App\Filament\Pages;

use Filament\Pages\Page;
use Filament\Forms;
use Filament\Notifications\Notification;

class Settings extends Page
{
    protected static ?string $navigationIcon = 'heroicon-o-cog';

    protected static string $view = 'filament.pages.settings';

    public $name;
    public $email;

    public function mount(): void
    {
        $this->form->fill([
            'name' => auth()->user()->name,
            'email' => auth()->user()->email,
        ]);
    }

    public function submit(): void
    {
        $this->validate();
        auth()->user()->update($this->form->getState());
        Notification::make()->success()->title('Settings saved.')->send();
    }

    protected function getFormSchema(): array
    {
        return [
            Forms\Components\TextInput::make('name')->required(),
            Forms\Components\TextInput::make('email')->email()->required(),
        ];
    }
}
💡Widget Caching
📊 Production Insight
Use Filament's built-in notification system for user feedback. Avoid redirects; instead, use Livewire's reactivity.
🎯 Key Takeaway
Custom pages and widgets allow you to build any admin functionality beyond CRUD.

Implementing Authorization and Roles

Filament integrates with Laravel's authorization system. You can define policies and gates to control access.

Policies: Create a policy for a model:

``bash php artisan make:policy PostPolicy --model=Post ``

Define methods like viewAny, view, create, update, delete. Then register the policy in AuthServiceProvider.

Filament Integration: Filament automatically checks policies for resources. For example, if a user cannot view a post, the edit button will be hidden.

Roles and Permissions: Use a package like spatie/laravel-permission for role-based access. Install it:

``bash composer require spatie/laravel-permission php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" php artisan migrate ``

Create roles and assign permissions. Then, in Filament, you can check permissions in the panel provider:

``php public function panel(Panel $panel): Panel { return $panel ->authMiddleware([ Authenticate::class, 'role:admin', // custom middleware ]); } ``

``php public static function canViewAny(): bool { return auth()->user()->can('viewAny', static::getModel()); } ``

Key Takeaway: Use Laravel policies and Spatie permissions for fine-grained access control. Filament respects these automatically.

PostPolicy.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    public function viewAny(User $user): bool
    {
        return $user->hasPermissionTo('view posts');
    }

    public function view(User $user, Post $post): bool
    {
        return $user->hasPermissionTo('view posts');
    }

    public function create(User $user): bool
    {
        return $user->hasPermissionTo('create posts');
    }

    public function update(User $user, Post $post): bool
    {
        return $user->hasPermissionTo('edit posts');
    }

    public function delete(User $user, Post $post): bool
    {
        return $user->hasPermissionTo('delete posts');
    }
}
⚠ Don't Forget to Register Policies
📊 Production Insight
Always test authorization with different user roles. Use Filament's can() methods to conditionally show actions.
🎯 Key Takeaway
Authorization in Filament leverages Laravel's policies and can be extended with role-based packages.

Performance Optimization and Production Deployment

When deploying Filament to production, consider these optimizations:

Caching: Run php artisan optimize to cache configurations, routes, and views. For Filament, also cache the Livewire components:

``bash php artisan livewire:discover php artisan filament:cache ``

Asset Bundling: Filament uses Vite for asset compilation. In production, ensure you run npm run build to compile assets.

Database Queries: Use eager loading to avoid N+1 queries. In table columns, use ->with(['relation']) to load relationships.

Lazy Loading: For large datasets, use lazy loading or pagination. Filament's table supports pagination out of the box.

Queue Jobs: Offload heavy tasks like file processing or email sending to queues.

Security: Ensure your .env file has APP_DEBUG=false in production. Use HTTPS and set secure cookies.

Monitoring: Use Laravel's logging and monitoring tools like Telescope or Laravel Pulse.

Key Takeaway: Optimize Filament for production by caching, using eager loading, and offloading heavy tasks.

deploy.shPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# Production deployment script for Laravel Filament

php artisan down --retry=60

git pull origin main

composer install --no-dev --optimize-autoloader

php artisan migrate --force

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan filament:cache

npm ci --production
npm run build

php artisan up
🔥Use a CDN for Assets
📊 Production Insight
Always test the deployment in a staging environment. Use Laravel Horizon for queue monitoring.
🎯 Key Takeaway
Production deployment requires caching, asset compilation, and database optimization.
● Production incidentPOST-MORTEMseverity: high

The Case of the Missing Admin Panel: A Filament Deployment Nightmare

Symptom
After deployment, any visitor could browse the admin panel at /admin without logging in.
Assumption
The developer assumed that Filament's default middleware would automatically protect all admin routes.
Root cause
The developer had overridden the default Filament panel configuration and forgot to include the 'auth' middleware in the panel's middleware stack.
Fix
Added the 'auth' middleware to the panel configuration in config/filament.php and cleared the config cache.
Key lesson
  • Always verify that authentication middleware is applied to admin routes.
  • Use Filament's built-in authentication features instead of custom middleware unless necessary.
  • Test authentication in a staging environment before deploying to production.
  • Review the panel configuration file after any customization.
  • Implement role-based access control for sensitive actions.
Production debug guideSymptom to Action5 entries
Symptom · 01
Admin panel shows 404 error
Fix
Check if Filament routes are registered. Run php artisan route:list | grep filament to verify.
Symptom · 02
Forms not submitting
Fix
Check Laravel logs for validation errors. Ensure CSRF token is present in the form.
Symptom · 03
Slow table loading
Fix
Enable query logging with DB::enableQueryLog(). Check for N+1 queries and add eager loading.
Symptom · 04
File uploads failing
Fix
Verify storage link exists: php artisan storage:link. Check file size limits in php.ini and Filament config.
Symptom · 05
Users cannot access admin
Fix
Check if user has the correct role/permission. Verify middleware configuration in panel provider.
★ Quick Debug Cheat SheetCommon Filament issues and immediate fixes.
Admin panel not loading
Immediate action
Check that Filament is installed and configured.
Commands
php artisan vendor:publish --tag=filament-config
php artisan config:clear
Fix now
Ensure the panel provider is registered in config/app.php.
Resource not showing+
Immediate action
Verify the resource class exists and is registered.
Commands
php artisan make:filament-resource ModelName
php artisan optimize
Fix now
Check the resource's model and ensure the table exists.
Form validation errors+
Immediate action
Check the form rules in the resource.
Commands
php artisan make:filament-form
php artisan cache:clear
Fix now
Add validation rules to the form schema.
Table columns not displaying+
Immediate action
Check the table columns definition.
Commands
php artisan make:filament-table
php artisan view:clear
Fix now
Ensure columns are defined in the table() method.
FeatureFilamentNovaCustom Admin
Setup TimeMinutesMinutesHours/Days
CostFreePaid ($199/site)Developer time
CustomizationHighMediumFull
Livewire IntegrationNativeNoneManual
Community SupportActiveOfficialVaries
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
AdminPanelProvider.phpnamespace App\Providers\Filament;Installing Filament
PostResource.phpnamespace App\Filament\Resources;Creating Your First Resource
PostResource.php (form method)public static function form(Form $form): FormCustomizing Forms with Validation and Relationships
Settings.phpnamespace App\Filament\Pages;Building Custom Pages and Widgets
PostPolicy.phpnamespace App\Policies;Implementing Authorization and Roles
deploy.shphp artisan down --retry=60Performance Optimization and Production Deployment

Key takeaways

1
Filament accelerates admin panel development with pre-built components.
2
Resources map to Eloquent models and provide full CRUD interfaces.
3
Custom pages and widgets extend functionality beyond CRUD.
4
Authorization integrates with Laravel policies and role packages.
5
Performance optimization includes caching, eager loading, and queue jobs.

Common mistakes to avoid

3 patterns
×

Not running `php artisan filament:install` after installation

×

Forgetting to register policies in AuthServiceProvider

×

Using `all()` on large datasets in table columns

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is Filament and how does it integrate with Laravel?
Q02SENIOR
How do you create a custom page in Filament?
Q03SENIOR
Explain how Filament handles authorization.
Q01 of 03JUNIOR

What is Filament and how does it integrate with Laravel?

ANSWER
Filament is a set of tools for building admin panels in Laravel. It uses Livewire for dynamic UI and provides resources, forms, tables, and widgets. It integrates via Composer and panel providers.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I use Filament with an existing Laravel application?
02
How do I customize the admin panel's theme?
03
Does Filament support multi-tenancy?
04
Can I use Filament with non-Eloquent data sources?
05
How do I add custom JavaScript or CSS to Filament?
N
Naren Founder & Principal Engineer

20+ years shipping production PHP systems at scale. Written from production experience, not tutorials.

Follow
Verified
production tested
July 13, 2026
last updated
2,073
articles · all by Naren
🔥

That's Laravel. Mark it forged?

4 min read · try the examples if you haven't

Previous
Laravel Horizon and Telescope: Queue Monitoring and Debugging
21 / 24 · Laravel
Next
Laravel Breeze and Starter Kits