Laravel 13 tutorial #4: the admin panel with Filament
verified on 7 September 2026 · 6 min
Laravel ships with no admin panel. This series now uses Filament: composer require filament/filament then php artisan filament:install --panels. Voyager, used in earlier versions, is marked abandoned on Packagist and no longer installs on Laravel 13.
Laravel ships with no admin panel. You have to pick one, and that choice commits the project for years. This chapter explains why this series changed package, then installs Filament.
Why this chapter changed
Earlier versions of this tutorial used Voyager. That is no longer tenable.
tcg/voyager is marked as abandoned on Packagist. Its latest release, 1.8.0, dates from September 2024 and declares compatibility up to Laravel 11 only. On a Laravel 13 project, Composer simply refuses to install it: it first stops on the security advisories that cover every version, and its Laravel 11 constraint would make dependency resolution fail anyway.
That is the useful lesson of the episode: a tutorial resting on a package maintained by a single team becomes wrong the day that team stops. So the replacement has to be weighed on the health of the project as much as on its features.
What was looked at
Four candidates, measured on 2 September 2026 against the public Packagist data:
| Package | Last release | Laravel 13 | Downloads / month |
|---|---|---|---|
tcg/voyager | 1.8.0 (Sept 2024) | no | 23,614, but abandoned |
ilsondev/voyager | 2.2.1 (July 2026) | yes | 1 |
orchid/platform | 14.53.0 (March 2026) | yes | 27,227 |
filament/filament | 5.7.8 (Aug 2026) | yes | 3,324,015 |
ilsondev/voyager is a fork that works: it was installed on a fresh Laravel 13.30.1 for this revision, and the dashboard, the BREAD tool, the media library, the menu builder and the settings all responded correctly. But it totals 12 downloads and one star, and every one of its releases was published across three days in July 2026. It also pulls in intervention/image version 2, whose branch is no longer the current one. Recommending this fork to a beginner would be repeating the exact mistake that broke this tutorial.
That said, if you maintain an existing Voyager application and your first concern is moving to Laravel 13 without rewriting everything, this fork is an honest stepping stone. Treat it as a stage, not as a destination.
The choice: Filament
Filament wins on three counts.
- It will not disappear tomorrow. 3.3 million downloads a month, a hundred times the audience of every alternative combined, and releases published every week.
- The admin panel is code. Voyager stored the screen configuration in the database, clicked together in an interface. With Filament, each screen is a PHP class versioned along with the rest of the project. It can be reread, diffed and deployed like any other file.
- It is a skill that pays off. Filament is now the default admin panel of the Laravel ecosystem. What you learn here will turn up again on a real project.
Two paid alternatives are worth knowing about, without being needed for this tutorial: Nova, the official solution from the Laravel team, and Backpack.
Installing Filament
The intl extension has to be there
Filament requires the PHP intl extension. Check for it before installing:
php -m | grep intlIf the command returns nothing, the installation fails on this message, which never mentions Filament and leaves you puzzled:
filament/support[...] require ext-intl * -> it is missing from your system.
Install or enable PHP's intl extension.The first chapter already advised checking it for that reason. On Debian or Ubuntu, sudo apt install php8.4-intl. On macOS with Homebrew, the extension is already there. On Windows with WampServer, untick then tick php_intl again in the PHP extensions menu. Restart your server afterwards.
The package and the panel
composer require filament/filament
php artisan filament:install --panelsThe second command creates app/Providers/Filament/AdminPanelProvider.php, publishes the panel’s CSS and JavaScript files into public, and clears the caches.
INFO Successfully published assets!
INFO Successfully upgraded!Creating an account
php artisan make:filament-userThe command asks for a name, an email address and a password, then confirms:
INFO Success! admin@gekkode.test may now log in at http://localhost:8000/admin/login.Head to http://127.0.0.1:8000/admin and log in. The dashboard is empty: that is expected, nothing has been handed to it yet. Chapter 6 will add posts, categories and tags to it.
Controlling who gets in
In a local environment, Filament lets any authenticated user in. Everywhere else, it turns everyone away with a 403 until the User model has said who is allowed in. It is a safe default, but it catches people out: the panel works on your machine and returns 403 the moment you go live.
The rule is declared by implementing the FilamentUser interface. Keep everything the shipped model already contains, the #[Fillable] and #[Hidden] attributes as well as the casts() method: only the interface and the canAccessPanel() method are added.
<?php
namespace App\Models;
use Database\Factories\UserFactory;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable implements FilamentUser
{
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
public function canAccessPanel(Panel $panel): bool
{
return str_ends_with($this->email, '@gekkode.test');
}
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}Replace the domain with your own. This rule is deliberately simplistic: it is enough for a learning project, not for a public site. A real project relies on an is_admin column or on a role system.
The behaviour is checked by two tests. The second one matters as much as the first: in the testing environment, Filament refuses everyone as long as the rule does not exist, so a test that only checks the refusal would pass even without it.
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class AdminTest extends TestCase
{
use RefreshDatabase;
public function test_un_email_hors_domaine_est_refuse(): void
{
$user = User::factory()->create(['email' => 'intrus@example.com']);
$this->actingAs($user)->get('/admin')->assertForbidden();
}
public function test_un_email_du_domaine_est_accepte(): void
{
$user = User::factory()->create(['email' => 'admin@gekkode.test']);
$this->actingAs($user)->get('/admin')->assertOk();
}
}Migrating from the Voyager version of this tutorial
If you followed this tutorial in its Voyager version, here is what changes.
- The Voyager tables go away. The installation created ten of them:
data_types,data_rows,menus,menu_items,settings,roles,permissions,permission_role,user_rolesandtranslations. None of them are of any use now. Your business tables,posts,categories,tags,post_tag,users, are kept exactly as they are: Filament plugs into them with no data migration. - The BREAD configuration is lost, and that is deliberate. What you had clicked together in Voyager gets rewritten in PHP, once, in the files of chapter 6. That is half an hour of work, after which the configuration is under version control.
- The
setting()function is gone. Voyager provided it to read the site title and description. Replacesetting('site.title')withconfig('app.name'), or with your own settings. - The
postsslug workaround becomes pointless. Voyager shipped its ownPostmodel, which forced you to rename the table slug toblog-postsand patch one of the package’s templates. Filament imposes no model, so the conflict disappears. - The admin address does not change. Filament installs on
/adminas well.
To take Voyager out of an existing project: composer remove tcg/voyager, then drop its tables and the resources/views/vendor/voyager folder if it is still there. Back up the database first.
What this chapter did not cover
Fine-grained roles and permissions, theming the panel and dashboard widgets are beyond the scope of this series. The Filament documentation covers them.
The next chapter builds the home page of the public site.