Frontend
laravel-filament
Builds Filament admin panels with resources, pages, widgets
Overview
The laravel-filament agent creates admin panel components using Filament. It generates resources for CRUD interfaces, custom pages, dashboard widgets, and handles form/table builders with proper validation and relationships.
Responsibilities
- Resources - CRUD interfaces with forms, tables, and relation managers
- Form Builder - Complex forms with sections, tabs, and conditional fields
- Table Builder - Searchable, sortable tables with filters and bulk actions
- Custom Pages - Dashboard pages, settings pages, reports
- Widgets - Stats, charts, and custom dashboard widgets
- Relation Managers - Nested resource management
What It Creates
| Component | Location | Purpose |
|---|---|---|
| Resource | app/Filament/Resources/ |
CRUD interface for a model |
| Pages | app/Filament/Pages/ |
Custom admin pages |
| Widgets | app/Filament/Widgets/ |
Dashboard components |
| Relation Managers | app/Filament/Resources/*/RelationManagers/ |
Nested CRUD for relationships |
Generated Resource Example
<?php
namespace App\Filament\Resources;
use App\Models\Product;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
class ProductResource extends Resource
{
protected static ?string $model = Product::class;
protected static ?string $navigationIcon = 'heroicon-o-shopping-bag';
protected static ?string $navigationGroup = 'Shop';
public static function form(Form $form): Form
{
return $form->schema([
Forms\Components\Section::make('Product Details')
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255)
->live(onBlur: true)
->afterStateUpdated(fn ($state, $set) =>
$set('slug', str($state)->slug())),
Forms\Components\TextInput::make('slug')
->required()
->unique(ignoreRecord: true),
Forms\Components\RichEditor::make('description')
->columnSpanFull(),
Forms\Components\TextInput::make('price')
->required()
->numeric()
->prefix('$'),
Forms\Components\Select::make('category_id')
->relationship('category', 'name')
->searchable()
->preload()
->createOptionForm([
Forms\Components\TextInput::make('name')->required(),
]),
Forms\Components\FileUpload::make('image')
->image()
->directory('products'),
])->columns(2),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\ImageColumn::make('image'),
Tables\Columns\TextColumn::make('name')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('category.name')
->sortable(),
Tables\Columns\TextColumn::make('price')
->money()
->sortable(),
Tables\Columns\IconColumn::make('is_active')
->boolean(),
])
->filters([
Tables\Filters\SelectFilter::make('category')
->relationship('category', 'name'),
Tables\Filters\TernaryFilter::make('is_active'),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
RelationManagers\ReviewsRelationManager::class,
];
}
}
Stats Widget Example
<?php
namespace App\Filament\Widgets;
use App\Models\Order;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
class OrderStats extends StatsOverviewWidget
{
protected function getStats(): array
{
return [
Stat::make('Total Orders', Order::count())
->description('All time orders')
->descriptionIcon('heroicon-m-arrow-trending-up')
->color('success'),
Stat::make('Revenue', '$' . number_format(Order::sum('total'), 2))
->description('Total revenue')
->chart([7, 3, 4, 5, 6, 3, 5, 8])
->color('primary'),
Stat::make('Pending', Order::where('status', 'pending')->count())
->description('Awaiting processing')
->color('warning'),
];
}
}
Custom Action Example
// In table actions
Tables\Actions\Action::make('approve')
->action(fn (Product $record) => $record->approve())
->requiresConfirmation()
->modalHeading('Approve Product')
->modalDescription('Are you sure you want to approve this product?')
->color('success')
->icon('heroicon-o-check'),
// Bulk action
Tables\Actions\BulkAction::make('export')
->action(function (Collection $records) {
return Excel::download(
new ProductsExport($records),
'products.xlsx'
);
})
->icon('heroicon-o-arrow-down-tray')
Invoked By Commands
- /laravel-agent:filament:make - Create Filament resources
Called By
- laravel-architect - When building admin interfaces
Best Practices
- Use Sections - Organize forms with sections and tabs
- Add searchable - Enable search on Select fields
- Relation managers - Use for nested CRUD operations
- Global search - Configure $recordTitleAttribute
Guardrails
The Filament agent follows strict rules:
- ALWAYS set navigationIcon for resources
- ALWAYS implement proper authorization
- ALWAYS add soft deletes with restore action
- NEVER exceed 15 fields per form section
- NEVER skip relationship configuration on Select fields
See Also
- laravel-filament skill - Auto-invoked Filament expertise
- laravel-livewire - Livewire components (Filament is built on Livewire)