How to customize Laravel filament login page
Tags: laravel, filamentphp, loginpage
Published: 2022-08-15 12:24:57

---
title: How to customize Laravel filament login page
published: true
date: 2022-07-06 00:00:00 UTC
tags: ['laravel','filamentphp','loginPage']
canonical_url: https://www.codef.site/blog/laravel/how-to-customize-laravel-filament-login-page
---

!["Laravel filament custom login page"](https://www.codef.site/img/laravel/laravel_filament_login_page.jpg)

[Laravel filament](https://filamentphp.com/) is a set of tools from which you can rapidly build <link-to-self hash="tall-stack" title="Tall"></link-to-self> stack application. Currently it has 3 tools, [Admin Panel](https://filamentphp.com/docs/2.x/admin/installation), [Form Builder](https://filamentphp.com/docs/2.x/forms/installation) and [Table Builder](https://filamentphp.com/docs/2.x/tables/installation). There are also [community plugin](https://filamentphp.com/plugins) to support Laravel filament.

## TALL stack

Tall stack is full stack framework for laravel. It stands for **T: Tailwindcss** , **A: Alpinejs** , **L: Laravel** and **L: Livewire**.

<my-icon name="logos:tailwindcss-icon"></my-icon><my-icon name="logos:alpinejs-icon"></my-icon><my-icon name="logos:laravel"></my-icon><my-icon name="simple-icons:livewire"></my-icon>

## Getting Started

I assume that you have already installed Laravel and Filament. If not than check [here](/blog/laravel/setup-laravel-admin-panel-in-few-minutes-with-laravel-filament) for setting up filament. First publish configuration and views of filament.

```bash
php artisan vendor:publish --tag=filament-config
```
```bash
php artisan vendor:publish --tag=filament-views
```

Generated Files:

```
/
|-- config/
| |-- filament.php
|-- resources/
| |-- views/
| |-- vendor/
| |-- filament/
| ...
| |-- login.blade.php
```

This will publish filament configuration and views.

## Vite setup for filament

The current default bundler for laravel is [vitejs](https://vitejs.dev/), so if you have created a new project then there is greater chance that it came with vite. If it is then we have to register render hook <code-inline>head.end</code-inline> in <code-inline>register</code-inline> method of **AppServiceProvider**. We need to add <code-inline>@vite</code-inline> directive in order to use the compiled css and js files for our admin panel.

```php
use Filament\Facades\Filament;

public function register()
{
    Filament::registerRenderHook(
        'head.end',
        fn (): string =&gt; Blade::render('@vite([\'resources/css/app.css\',\'resources/js/app.js\'])'),
    );
}
```

For the icons i am using [Iconify](https://iconify.design), so we need to register cdn script for iconify.

```php
public function boot()
{
    Filament::registerScripts([
        'https://code.iconify.design/2/2.2.1/iconify.min.js',
    ], true); // true means that this script will be load before filament core scripts.
}
```

We also need to use filament's tailwind configuration otherwise styling of the admin panel will not work. we can use tailwind's presets property to use preset configuration.

```js
module.exports = {
    ...
    presets: [require("./vendor/filament/filament/tailwind.config.js")],
}
```

## Change login class

Since filament uses livewire component to render inputs of login form, we need to create our own class components. Copy the code of <code-inline>vendor/filament/filament/src/Http/Livewire/Auth/Login.php</code-inline> file then create a new file <code-inline>app/Filament/Auth/Login.php</code-inline> and paste the code in it. Next change the namespace of the class to <code-inline>namespace App\Filament\Auth;</code-inline>. Then pass the class into filament config file under <code-inline>auth.pages.login</code-inline>.

```php
//app/Filament/Auth/Login.php
<?php

namespace App\Filament\Auth;

use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Filament\Facades\Filament;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
use Illuminate\Contracts\View\View;
use Livewire\Component;

/**
 * @property ComponentContainer $form
 */
class Login extends Component implements HasForms
{
    use InteractsWithForms;
    use WithRateLimiting;

    public $email = '';
    public $password = '';
    public $remember = false;

    public function mount(): void
    {
        if (Filament::auth()->check()) {
            redirect()->intended(Filament::getUrl());
        }

        $this->form->fill();

    }

    public function authenticate(): ?LoginResponse
    {
        try {
            $this->rateLimit(5);
        } catch (TooManyRequestsException $exception) {
            $this->addError('email', __('filament::login.messages.throttled', [
                'seconds' => $exception->secondsUntilAvailable,
                'minutes' => ceil($exception->secondsUntilAvailable / 60),
            ]));

            return null;
        }

        $data = $this->form->getState();

        if (!Filament::auth()->attempt([
            'email' => $data['email'],
            'password' => $data['password'],
        ], $data['remember'])) {
            $this->addError('email', __('filament::login.messages.failed'));

            return null;
        }

        return app(LoginResponse::class);
    }

    protected function getFormSchema(): array
    {
        return [
            TextInput::make('email')
                ->label(__('filament::login.fields.email.label'))
                ->email()
                ->required()
                ->autocomplete(),
            TextInput::make('password')
                ->label(__('filament::login.fields.password.label'))
                ->password()
                ->required(),
            Checkbox::make('remember')
                ->label(__('filament::login.fields.remember.label')),
        ];
    }

    public function render(): View
    {
        return view('filament::login')
            ->layout('filament::components.layouts.card', [
                'title' => __('filament::login.title'),
            ]);
    }
}
```
```php
use App\Filament\Auth\Login;

return [
    ...
    'auth' =&gt; [
        'pages' =&gt; [
            'login' =&gt; Login::class,
        ],
    ],
];

```

## Login page

Now lets customize our blade file. This is default blade file for login page.

```php
<form wire:submit.prevent="authenticate" class="space-y-8">
    {{ $this->form }}

    <x-filament::button type="submit" form="authenticate" class="w-full">
        {{ __('filament::login.buttons.submit.label') }}
    </x-filament::button>
</form>
```

![Login page before customization](https://www.codef.site/img/laravel/filament_login.png)

We will add icons for social logins for example facebook, google, etc.

```php
<form wire:submit.prevent="authenticate" class="space-y-8">
    {{ $this->form }}

    <x-filament::button type="submit" form="authenticate" class="w-full">
        {{ __('filament::login.buttons.submit.label') }}
    </x-filament::button>
    <div class="flex items-center space-x-4">
        <div class="border-t-2 border-slate-600 w-full h-1"></div>
        <h1>Or</h1>
        <div class="border-t-2 border-slate-600 w-full h-1"></div>
    </div>
    <div class="flex space-x-4 items-center justify-evenly">
        // icons from iconify
        <span class="iconify w-5 h-5" data-icon="flat-color-icons:google"></span>
        <span class="iconify w-5 h-5" data-icon="logos:github-icon"></span>
        <span class="iconify w-5 h-5" data-icon="logos:facebook"></span>
    </div>
</form>
```

![Login page after customization](https://www.codef.site/img/laravel/after_edit.png)

## Example

Lets make a simple example in which email and password will be auto filled when in local environment. This will help us quickly login in local environment. Open Login.php file and on mount method add the following code.

```php
public function mount(): void
{
    if(env('APP_ENV') === 'local'){
        // fill method is from HasForms interface 
        $this-&gt;form-&gt;fill([
            'email'=&gt; 'fazailalam898@gmail.com',
            'password'=&gt; '12345678',
        ]);
    }else{
        $this-&gt;form-&gt;fill();
    }
}
```

All right all done, now goto <code-inline>https://localhost:8000/admin/login</code-inline> and check for changes.