Plugin Registration
This document covers how to register TagixoPrimixPlugin inside a Primix panel provider, what is auto-registered on your behalf, and how to configure optional features.
Registering the Plugin
Add TagixoPrimixPlugin::make() to the plugins() call inside your AdminPanelProvider:
use Ccast\TagixoPrimix\TagixoPrimixPlugin;
use Primix\Primix\PrimixPanelProvider;
class AdminPanelProvider extends PrimixPanelProvider
{
public function panel(Panel $panel): Panel
{
return parent::panel($panel)
->id('admin')
->path('admin')
->plugins([
TagixoPrimixPlugin::make(),
]);
}
}
Important — provider base class Your provider must extend
Primix\Primix\PrimixPanelProvider, notFilament\PanelProvider. Using the Filament base class skips Primix boot hooks and will cause the plugin to partially or silently fail.
What Auto-Registers
When TagixoPrimixPlugin::make() is present in the panel, the following are registered automatically without any additional configuration:
| What | Details |
|---|---|
| Builder routes | /tagixo/builder/* endpoints mounted under the panel path — page save, asset serving, global variables, font preview, form submission proxy |
| LiVue asset hooks | <link> and <script> tags for the LiVue runtime injected via Primix render hooks |
enableAppForms |
Registers Tagixo form schema support globally (see section below) |
| Notifications bridge | Primix flash notifications wired to the Tagixo frontend notification bus |
| Admin resources | Pages, Layouts, Menus, Global Variables, and Forms Primix resources auto-registered in the panel |
You do not need to register routes, call Route::tagixo(), or manually boot the builder.
enableAppForms
The plugin calls Tagixo::enableAppForms() during its boot phase. This call:
- Registers the
tgx_formstable as a global form schema source available to all pages and modules - Is idempotent — calling it more than once has no effect
- Is global in scope — not tied to a panel; it affects the full application
Do not call enableAppForms() again in your own service provider. The plugin already handles it. If you call it before the plugin boots, it is safe (idempotent), but the call is redundant.
Fluent Options
withMediaGallery()
TagixoPrimixPlugin::make()
->withMediaGallery(),
Adds a Media Gallery resource to the panel (upload, organize, and reuse images and files across pages). When enabled:
- A
Medianav item appears in the admin sidebar - The media picker field becomes available inside PropType definitions
- Uploaded files are stored in the
publicdisk undermedia/
Without withMediaGallery(): The media picker field falls back to a plain URL text input. No upload or library UI is available.
Boot Sequence
The following ASCII tree shows where the plugin boots relative to the Laravel kernel and Primix panel boot. Understanding this order matters if you add custom service providers or listen to boot events.
Laravel kernel boot
└── AppServiceProvider::boot()
└── TagixoServiceProvider::boot() ← plugin core (routes, models, migrations)
└── TagixoPrimixServiceProvider::boot() ← Primix integration layer registered
└── PrimixPanelProvider::boot()
└── TagixoPrimixPlugin::boot() ← your plugin call runs here
├── enableAppForms()
├── register builder routes
├── register LiVue hooks
└── register admin resources
Octane note: Under Laravel Octane (Swoole), the boot sequence runs once per worker process, not per request. State set during plugin boot (registered routes, resolved bindings) persists across requests on the same worker. Avoid storing per-request state in the plugin's boot() callback or in service provider properties.
Multi-Panel Setups
If your application has two panels (for example, an admin panel and a vendor panel), register TagixoPrimixPlugin only in the panel where the builder should appear:
// AdminPanelProvider.php — builder panel
class AdminPanelProvider extends PrimixPanelProvider
{
public function panel(Panel $panel): Panel
{
return parent::panel($panel)
->id('admin')
->path('admin')
->plugins([
TagixoPrimixPlugin::make()->withMediaGallery(),
]);
}
}
// VendorPanelProvider.php — separate panel, no builder
class VendorPanelProvider extends PrimixPanelProvider
{
public function panel(Panel $panel): Panel
{
return parent::panel($panel)
->id('vendor')
->path('vendor')
->plugins([
// TagixoPrimixPlugin not included here
]);
}
}
Route scoping: Builder routes (/tagixo/builder/*) are scoped to the panel that registered the plugin. The vendor panel above will not expose builder endpoints.
enableAppForms is intentionally global. Even though the plugin is registered in only one panel, form schema support is available application-wide. This allows public-facing form submissions (POST /forms/{formKey}/submit) to resolve form definitions regardless of which panel registered the plugin.
Conditional Features
Use ->when() to enable optional plugin features based on config values or authorization checks:
// Config-gated — feature flag in config/tagixo.php
TagixoPrimixPlugin::make()
->when(config('tagixo.media_gallery_enabled'), fn ($plugin) => $plugin->withMediaGallery()),
// Permission-gated — only enable media gallery if the current user can manage media
TagixoPrimixPlugin::make()
->when(
fn () => auth()->user()?->can('manage media'),
fn ($plugin) => $plugin->withMediaGallery(),
),
Timing caveat: The closure passed as the first argument to
->when()runs during panel boot, not during the request. At that point the auth guard may not yet have resolved the current user. For permission-based gating, prefer config flags or defer the check to a middleware/policy rather than readingauth()->user()inside a panel boot closure.
Custom Layout Override
To override the Tagixo admin layout Blade view, publish the vendor views:
php artisan vendor:publish --tag=tagixo-primix-views
This copies views to resources/views/vendor/tagixo-primix/. Edit the layout file there.
What not to remove from the published layout:
@stack('tagixo-scripts')— required for builder JS assets@livewireStyles/@livewireScripts— required for Primix/Livewire components- The Primix asset
@yielddirectives — removing these breaks panel navigation
CSS-only overrides (recommended alternative): If you only need to restyle the admin chrome (fonts, colours, spacing), use a Primix render hook instead of publishing the layout:
// In your AppServiceProvider::boot()
use Primix\Primix\Facades\Primix;
use Primix\Primix\View\PrimixRenderHook;
Primix::registerRenderHook(
PrimixRenderHook::HEAD_END,
fn () => '<link rel="stylesheet" href="' . asset('css/admin-overrides.css') . '">',
);
This is safer than a full layout override and will not break when the plugin updates its layout.
Full AdminPanelProvider Example
Complete provider with every documented option shown. Commented-out alternatives are included for reference.
<?php
namespace App\Providers;
use Ccast\TagixoPrimix\TagixoPrimixPlugin;
use Primix\Primix\PrimixPanelProvider;
use Filament\Panel;
class AdminPanelProvider extends PrimixPanelProvider
{
public function panel(Panel $panel): Panel
{
return parent::panel($panel)
->id('admin')
->path('admin')
// Authentication
->login()
// ->authMiddleware([Authenticate::class])
// Navigation
->brandName('Tagixo')
// ->brandLogo(asset('images/logo.svg'))
// ->favicon(asset('images/favicon.png'))
// Colors (Primix / Tailwind CSS variables)
// ->colors(['primary' => Color::Indigo])
// Plugin registration
->plugins([
TagixoPrimixPlugin::make()
// Optional: media gallery resource + picker field
->withMediaGallery(),
// Optional: conditional feature based on config
// ->when(config('tagixo.media_gallery_enabled'), fn ($p) => $p->withMediaGallery()),
]);
}
}
Asset Publication
Builder JS/CSS assets live in public/vendor/tagixo/ and are served directly by the web server. They are not processed by Vite.
Publish (or re-publish) assets after updating the ccast/tagixo package:
php artisan vendor:publish --tag=tagixo-assets --force
The --force flag is required on subsequent publishes — without it, existing files are not overwritten.
Commit the published assets. The production Docker image is built with composer install --no-scripts, which skips post-install-cmd hooks. Assets must already be present in the repository so the Dockerfile COPY step picks them up. If you skip committing assets, the production build will serve stale JS/CSS.
Vite is not involved in serving these assets. Running
npm run builddoes not updatepublic/vendor/tagixo/. Asset updates come exclusively fromvendor:publish.