Your application might require adding Filament and your existing Laravel Breeze (or any other stack) application. In this example, we will show you how it's done and how you can have a single login page for all of them.
Let's start with the Filament Admin panel:
app/Providers/Filament/AdminPanelProvider.php
class AdminPanelProvider extends PanelProvider{ public function panel(Panel $panel): Panel { return $panel ->default() ->id('admin') ->path('admin') // ... }}
In this panel, we will have 2 CRUDs:
app/Filament/Resources/Users/UserResource.php
class UserResource extends Resource{ protected static ?string $model = User::class; protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-users'; protected static ?int $navigationSort = 1; protected static ?string $recordTitleAttribute = 'name'; public static function form(Schema $schema): Schema { return UserForm::configure($schema); } public static function infolist(Schema $schema): Schema { return UserInfolist::configure($schema); } public static function table(Table $table): Table { return UsersTable::configure($table); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => ListUsers::route('/'), 'create' => CreateUser::route('/create'), 'view' => ViewUser::route('/{record}'), 'edit' => EditUser::route('/{record}/edit'), ]; } public static function getGloballySearchableAttributes(): array { return ['name', 'email']; } public static function getGlobalSearchResultDetails(Model $record): array { return [ 'Email' => $record->email, 'Role' => $record->role?->name, ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery()->with(['role', 'driver']); }}
As you can see, we have not defined our Form or Table yet. In Filament v4, we define them as a separate file:
app/Filament/Resources/Users/Schemas/UserForm.php
class UserForm{ public static function configure(Schema $schema): Schema { return $schema ->components([ Section::make('User Information') ->schema([ TextInput::make('name') ->required() ->maxLength(255), TextInput::make('email') ->email() ->required() ->unique(ignoreRecord: true) ->maxLength(255), // ...}
Next, we will create: