Branding in Filament multi-tenant: Customize logo & colors
yebor974

yebor974 @yebor974

About: Freelance - French IT Engineer passionate about Laravel and Filament PHP, creating innovative solutions to simplify web development. Founder of Filament Mastery.

Location:
Reunion Island, France
Joined:
May 5, 2025

Branding in Filament multi-tenant: Customize logo & colors

Publish Date: May 16
5 0

Filament allows extensive customization of its panels, including branding elements like the logo and colors. In a multi-tenant application, such as a white-label app, you may want to display different logos depending on the active tenant. This article will guide you through dynamically setting the logo and branding for a Member panel based on the connected tenant.

To manage a multi-tenant panel, you can follow this article. This guide builds upon that configuration.

Storing Tenant-Specific Branding

In your Entity model (which represents a tenant for this article), define methods to retrieve the logo and colors dynamically (To simplify, we define only the primary color instead of a full color set):

class Entity extends Model
{
    protected $fillable = [
        //....
        'logo',
        'config',
    ];

    protected $casts = [
        'config' => 'json',
    ];

    public function getBrandLogo()
    {
        if ($this->logo) {
            return asset('private/' . $this->logo);
        }
        return asset('images/logo.svg'); // Default logo if none is set
    }

    public function getPrimaryColorCode()
    {
        return Arr::get($this->config, 'colors.primary', '#0099a8'); // Default primary color
    }

    //...
}

Enter fullscreen mode Exit fullscreen mode

Here, we assume that:

  • The logo attribute stores the tenant’s custom logo.
  • The config attribute (stored as JSON in the database) contains branding configurations, including colors.

You can manage these attributes on your EditEntityProfile page with a FileUpload and a ColorPicker like this :

FileUpload::make('logo')
    ->image()
    ->imageEditor()
    ->disk('private')
    ->directory('logos')
    ->visibility('private'),
ColorPicker::make('config.colors.primary')
    ->nullable()
    ->hexColor(),

Enter fullscreen mode Exit fullscreen mode

Setting a default logo in the Panel Provider

By default, Filament allows you to define a static logo in your PanelProvider. In our example, this can be set in MemberPanelProvider.php:

use App\Models\Entity;
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        ->default()
        ->id('member')
        ->tenant(Entity::class)
        ->brandLogo(asset('images/logo.svg')) // Default logo
        ->brandLogoHeight('7rem') // Logo height
        //...
}

Enter fullscreen mode Exit fullscreen mode

This ensures that if no tenant-specific logo is defined or if there is no active tenant (e.g., on the login page), the default logo will be used.

Adjusting the logo and colors dynamically

To modify the logo dynamically, we need to hook into Filament’s Tenancy middleware system. You can create a middleware, e.g., ApplyFilamentTenantThemeMiddleware.php, and modify the logo and colors based on the active tenant.

Creating a middleware

You need this middleware to dynamically apply branding settings based on the active tenant, ensuring that each user sees the appropriate logo and colors without requiring manual configuration.

php artisan make:middleware Filament\\ApplyFilamentTenantThemeMiddleware

Enter fullscreen mode Exit fullscreen mode

This command creates the middleware on App\Http\Middleware\Filament\.

Changing the logo and colors based on Tenant

To change the logo and color scheme per tenant, first register the middleware on the MemberPanelProvider:

use App\Models\Entity;
use Filament\Panel;
use App\Http\Middleware\Filament\ApplyFilamentTenantThemeMiddleware;

public function panel(Panel $panel): Panel
{
    return $panel
        ->default()
        ->id('member')
        ->tenant(Entity::class)
        ->brandLogo(asset('images/logo.svg')) // Default logo
        ->brandLogoHeight('7rem') // Logo height
        ->tenantMiddleware([
            ApplyFilamentTenantThemeMiddleware::class, //Registering tenant middleware
        ])
        //...
}

Enter fullscreen mode Exit fullscreen mode

Then, update the handle method in your middleware to apply the logo and colors dynamically:

use Closure;
use Filament\Facades\Filament;
use Filament\Support\Facades\FilamentColor;
use Illuminate\Http\Request;

class ApplyFilamentTenantThemeMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $tenant = filament()->getTenant();

        if (!$tenant) {
            return $next($request);
        }

        // Set the tenant-specific logo
        Filament::getCurrentPanel()->brandLogo($tenant->getBrandLogo());
        Filament::getCurrentPanel()->brandLogoHeight('3.5rem');

        // Set the tenant-specific primary color
        if ($colors = Arr::get($tenant->config, 'colors')) {
            FilamentColor::register([
                'primary' => $tenant->getPrimaryColorCode()
            ]);
        }

        return $next($request);
    }
}

Enter fullscreen mode Exit fullscreen mode
  • Default logo and primary color on Login page: Filament Mastery Login Page

  • Custom logo and primary color on panel: Filament Mastery Tenant Panel Dashboard

Conclusion

By leveraging Filament’s middleware and panel customization features, you can create a fully dynamic branding system that adapts to each tenant. This approach guarantees that each tenant in your multi-tenant Filament application enjoys a unique and fully customized user experience.

Support my Work ☕

Writing in-depth tutorials like this takes time and effort. If you found this article helpful and want to support my work, consider buying me a coffee or sponsoring me on GitHub! Your support helps me keep creating valuable content for the community.

☕ Buy me a coffee | 💖 Sponsor me on GitHub

Thanks for reading and happy coding! 🚀

Comments 0 total

    Add comment