Setup

Plugin Registration

Register TagixoFilamentPlugin in your Filament panel provider and understand available options.

Plugin Registration

Registering in a PanelProvider

Add TagixoFilamentPlugin::make() to the plugins() array of your Filament PanelProvider:

<?php

namespace App\Providers\Filament;

use Ccast\TagixoFilament\TagixoFilamentPlugin;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->login()
            ->colors(['primary' => Color::Amber])
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
            ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
            ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([Authenticate::class])
            ->plugins([
                TagixoFilamentPlugin::make()
                    ->withPages()
                    ->withLayouts()
                    ->withMenus()
                    ->withGlobalVariables()
                    ->withForms()
                    ->withMediaGallery()
                    ->navigationGroup('Content'),
            ]);
    }
}

Fluent Configuration Methods

All feature toggles are chainable on the TagixoFilamentPlugin instance. Every method accepts an optional bool argument (default true) so you can conditionally disable a feature.

Method Default Effect
->withPages(bool $enabled = true) true Registers the Pages resource (list, create, edit, builder).
->withLayouts(bool $enabled = true) true Registers the Layouts resource.
->withMenus(bool $enabled = true) true Registers the Menus & Menu Items resources.
->withGlobalVariables(bool $enabled = true) true Registers the Global Variables resource.
->withForms(bool $enabled = true) true Registers the Forms resource (form schema editor).
->withMediaGallery(bool $enabled = true) true Registers the Media Gallery resource and file-picker Livewire component.
->usingLayout(string $view) built-in Overrides the default Filament layout blade view used by builder pages.
->navigationGroup(string $group) null Wraps all Tagixo nav items under this Filament navigation group label.

Example — disable forms and override the navigation group:

TagixoFilamentPlugin::make()
    ->withForms(false)
    ->navigationGroup('Website'),

What the Plugin Registers Automatically

When the plugin boots inside a panel, it automatically registers the following without any extra configuration:

Routes All builder API endpoints (page/layout/menu save, global variables, media endpoints) are registered under the panel's path prefix and protected by the panel's auth middleware stack. You do not need to add any routes manually.

Livewire Components Builder-related Livewire components (the visual editor mount component, the media picker, the form schema editor) are registered via Livewire::component() during the ServingFilament event so they are scoped to the panel request.

Render Hooks The plugin injects builder JavaScript and CSS into the Filament head via render hooks (FilamentView::renderHook). The assets are loaded only on pages that mount the builder, not on every admin page.

Livewire Morph Guard A render hook appends a wire:ignore wrapper around the #tagixo-vue mount point. This prevents Livewire's DOM-morph from destroying the Vue application during Livewire updates.


The Plugin Boot Sequence

Understanding the boot order prevents the most common integration mistakes:

  1. Service providers bootTagixoFilamentServiceProvider registers base bindings (models, config, migrations).
  2. ServingFilament event fires — Filament dispatches this once per HTTP request when a panel is being served. The plugin registers Livewire components and routes here.
  3. register() runs on PanelProvider — the plugins([...]) array is evaluated; TagixoFilamentPlugin::make() configures the plugin instance but does not yet boot it.
  4. boot() runs on PanelProvider — navigation items, render hooks, and asset injection are applied.
  5. Navigation is built — Filament assembles the sidebar; navigationGroup() takes effect here.

Gotcha: Do not call TagixoFilamentPlugin::get($panel) or reference the plugin instance before boot() completes. In particular, do not call it from a service provider's register() method — the panel will not yet have processed its plugins array.


Multi-Panel Setups

If your application has more than one Filament panel (e.g. an admin panel and a tenant panel), register the plugin independently in each panel's provider:

// AdminPanelProvider
->plugins([
    TagixoFilamentPlugin::make()
        ->withPages()
        ->withLayouts()
        ->navigationGroup('Content'),
])

// TenantPanelProvider
->plugins([
    TagixoFilamentPlugin::make()
        ->withPages(false)   // tenants cannot manage pages
        ->withForms()
        ->navigationGroup('Forms'),
])

Each panel gets its own route prefix (e.g. /admin/tagixo/... vs /tenant/tagixo/...), its own middleware stack, and its own set of registered resources. The plugin is designed to run safely in both panels simultaneously.

Warning: Do not share a single TagixoFilamentPlugin instance across two panels. Always call ::make() separately for each panel. A shared instance will have its configuration overwritten by whichever panel boots last.


Conditionally Enabling Features

Two common patterns for gating features behind config or feature flags:

Config-gated — read a value from your config/ at provider boot time:

TagixoFilamentPlugin::make()
    ->withForms(config('tagixo.features.forms', true))
    ->withMediaGallery(config('tagixo.features.media_gallery', true)),

Feature-flag-gated — integrate with a flag service:

TagixoFilamentPlugin::make()
    ->withMenus(Feature::active('advanced-menus')),

Octane / multi-tenant gotcha: Plugin registration happens once at boot, before any request context is available. If you are using Octane or a multi-tenant package that swaps tenants per request, feature flags that depend on the current tenant or session will not work here — they will be evaluated against the state at application boot. Gate features at the resource-policy or middleware level instead.


Custom Panel Layout Override

The builder pages use a custom Filament layout that mounts the Vue application. If you need to extend this layout (e.g. to inject a custom toolbar or change the sidebar), publish the views first:

php artisan vendor:publish --tag=tagixo-filament-views

This copies the layout stub to resources/views/vendor/tagixo-filament/. Then tell the plugin to use your overridden view:

TagixoFilamentPlugin::make()
    ->usingLayout('vendor.tagixo-filament.custom-builder-layout'),

Critical: Your custom layout must preserve the id="tagixo-vue" div and the id="vb-dynamic-styles" style tag. The Vue builder mounts onto #tagixo-vue and injects scoped CSS into #vb-dynamic-styles at runtime. Removing or renaming either element will silently break the builder with no console error — the div will simply remain empty.


Full PanelProvider Reference Example

A production-style provider with conditional plugin configuration:

<?php

namespace App\Providers\Filament;

use Ccast\TagixoFilament\TagixoFilamentPlugin;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->login()
            ->colors(['primary' => Color::Blue])
            ->brandName('My Site Admin')
            ->discoverResources(in: app_path('Primix/Resources'), for: 'App\\Primix\\Resources')
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([Authenticate::class])
            ->plugins([
                TagixoFilamentPlugin::make()
                    ->withPages()
                    ->withLayouts()
                    ->withMenus()
                    ->withGlobalVariables()
                    ->withForms(config('features.forms', true))
                    ->withMediaGallery(config('features.media_gallery', true))
                    ->navigationGroup('Content'),
            ]);
    }
}

Asset Publication Checklist

After installing or upgrading ccast/tagixo-filament, run these three commands:

# 1. Publish Filament SDK assets (JS/CSS for the builder UI inside the panel)
php artisan vendor:publish --tag=tagixo-filament-assets --force

# 2. Publish core Tagixo assets (frontend renderer JS/CSS served to public visitors)
#    Note: this tag comes from ccast/tagixo core, not the Filament SDK
php artisan vendor:publish --tag=tagixo-assets --force

# 3. Clear all caches so Octane picks up the new files
php artisan optimize:clear

Clarification: --tag=tagixo-assets is owned by the ccast/tagixo core package and publishes the public-facing builder renderer to public/vendor/tagixo/. The --tag=tagixo-filament-assets tag is owned by ccast/tagixo-filament and publishes the admin-panel-side JS/CSS. Both must be run after an upgrade — running only one will leave either the admin panel or the public renderer on the old version.