Filament Laravel

Filament Laravel

This filament is something to be recon, got used to Voyager but this is the next level.

Filament Admin Panel
How to build a Laravel Admin Panel. Built with Laravel 9, Filament, Spatie’s Laravel-Permissions, Jetstream, Livewire, and Tailwind CSS. Project name will be...

This playlist is pretty straightforward, understood every bit of it.

laravel new project --jet
# update env for database
composer require filament/filament
php artisan migrate
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\\Permission\\PermissionServiceProvider"
php artisan make:migration add_is_admin_users

Schema::table('users', function(Blueprint $table) {
use Spatie\\Permission\\Traits\\HasRoles;

class User extends Authenticatable {
	use HasRoles;
	protected $fillable = [
php artisan make:seeder RolesAndPermissionSeeder

# get this to rolesAndPermissionSeeder
php artisan make:filament-resource Permission --simple


use Spatie\Permission\Models\Permission;

protected static ?string $navigationGroup = 'Admin Management';

public static function form(Form $form): Form
        return $form
                            ->unique(ignoreRecord: true)

public static function table(Table $table): Table
        return $table
protected function getRedirectUrl(): string
    return $this->getResource()::getUrl('index');
php artisan make:filament-relation-manager RoleResource permissions name

User Resource w/ soft delete

composer require doctrine/dbal --dev
php artisan make:filament-resource User --generate

// to make list of checkbox relationship
  ->relationship('roles', 'name')
  ->helperText('Only Choose One!')

// password changing
        static fn(null|string $state):
            null|string => filled($state) ? Hash::make($state) : null,
        static fn(Page $livewire): 
            string => $livewire instanceOf CreateUser,
        static fn(null|string $state): 
            bool => filled($state),
        static fn(Page $livewire): 
            string => $livewire instanceOf EditUser ? 'New Password' : "Password"

Customizing user menu

php artisan make:provider FilamentServiceProvider

#add to config app.php

Filament::serving(function() {
  if (!empty(auth()->user()) && auth()->user()->is_admin == 1 && auth()->user()->hasAnyRole('super-admin', 'admin', 'moderator')) {
              ->label('Manage Users')
              ->label('Manage Roles')
              ->label('Manage Permission')

// to hide menu sidebar UserResource.php
protected static bool $shouldRegisterNavigation = false;

Authorization with policies

# User.php add

implements FilamentUser

public function canAccessFilament(): bool
    return $this->is_admin;

php artisan make:policy PermissionPolicy --model=Permission

public function viewAny(User $user)
    return $user->hasAnyRole(['super-admin', 'admin', 'moderator']);

# app/Providers/AuthServiceProvider.php
use App\\Policies\\PermissionPolicy;
protected $policies = [
    \\Spatie\\Permission\\Models\\Permission::class => PermissionPolicy::class,


php artisan make:filament-widget StatsOverview --stats-overview

protected function getCards(): array
        return [
            Card::make('Unique views', '192.1k'),
            Card::make('Bounce rate', '21%'),
            Card::make('Average time on page', '3:12'),

php artisan make:filament-widget BlogPostsChart --chart

protected function getData(): array
        $users = User::select('created_at')->get()->groupBy(function($users) {
            return Carbon::parse($users->created_at)->format('F');
        $quantities = [];
        foreach ($users as $user => $value) {
            array_push($quantities, $value->count());
        return [
            'datasets' => [
                    'label' => 'Users Joined',
                    'data' => $quantities,
                    'backgroundColor' => [
            'labels' => $users->keys(),

Custom theme

npm install tippy.js --save-dev

const colors = require('tailwindcss/colors')
colors: { 
    danger: colors.rose,
    warning: colors.yellow,


#create new file in resources/css/filament.css
@import '../../vendor/filament/filament/resources/css/app.css';

# open filamentServiceProvider in serving function

Make only admin accessible


I saw a few tricks to get this done but this is my way, it's simpler.

Users - Admin Panel - Filament
Schema::table('users', function (Blueprint $table) {

// then in user model

use Filament\Models\Contracts\FilamentUser;
... implements FilamentUser

public function canAccessFilament(): bool
	return $this->is_admin;


namespace App\Models;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements FilamentUser
    // ...
    public function canAccessPanel(Panel $panel): bool
        return str_ends_with($this->email, '') && $this->hasVerifiedEmail();

Import data

I have tried with some plugins but with a new project, the package doesn't work, here's another approach.

First get the package first

composer require maatwebsite/excel

Create the import

php artisan make:import ImportCampaign --model=Campaign


namespace App\Imports;

use App\Models\Campaign;
use Maatwebsite\Excel\Concerns\ToModel;

class ImportCampaign implements ToModel
    * @param array $row
    * @return \Illuminate\Database\Eloquent\Model|null
    public function model(array $row)
        return new Campaign([
            'client_id' => $row[0] ?? '',
            'date' => $row[1] ?? '',
            'name' => $row[2] ?? '',

Add this to Page/List{model} if User ListUser

    // Pages/List{model}
    public function getHeader(): ?View {
        $data = Actions\CreateAction::make();
        return view('filament.custom.upload-file', compact('data'));

    public function save() {
        if ($this->file != '') {
            Excel::import(new ImportCampaign, $this->file);

Look at the get header it return a view, make like this below where wire:submit="save" (on top save())

    <x-filament::breadcrumbs :breadcrumbs="[
        '/admin/campaigns' => 'Campaign',
        '' => 'List',
    ]" />
    <div class="flex justify-between mt-1">
        <h1 class="font-bold text-3xl">Campaign</h1>
        <div>{{ $data }}</div>

    <form wire:submit="save" class="w-full max-w-sm flex mt-2">
        <div class="mb-4">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="fileInput">
                Upload File
            <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="fileInput" type="file" wire:model='file'>
        <div class="item-center justify-between mt-3 pl-5">
            <button class="text-black font-bold border rounded px-6 py-2" type="submit">



GitHub - reworck/filament-settings: Easy setting management for filament
Easy setting management for filament. Contribute to reworck/filament-settings development by creating an account on GitHub.
composer require reworck/filament-settings

# appServiceProvider - add more in values in here

# in User.php add function below, create permission and add to user if have any
public function canManageSettings(): bool
    return $this->can('manage.settings');

Subscribe to You Live What You Learn

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]