Skip to content

Admin Tool Registry

Who is this for? Package developers adding custom quick-action items to the Capell admin header toolbar.

TL;DR: The AdminToolRegistry reads tagged tool classes from the container and renders them into the admin header dropdown. Register a tool by implementing AdminToolItem and tagging it with AdminToolItem::TAG in your service provider.


The Admin Tool Registry is for adding custom dropdown items to the admin header’s tools menu (wrench icon, top-right). Use it when you want to:

  • Add a quick-action button (e.g., “Flush cache”, “Open dashboard”)
  • Contribute a custom tool alongside core actions (rebuild site, upgrade, etc.)
  • Keep the tool accessible without requiring a full Filament resource or page

Contrast with Filament resources or dashboard widgets, which have their own registration mechanisms and are discovery-friendly on their own.

  1. Container tagging: Tools are tagged into Laravel’s service container with the key AdminToolItem::TAG ('capell-admin:admin-tool-items')
  2. Registry lookup: The AdminToolRegistry singleton resolves all tagged tools via app()->tagged(AdminToolItem::TAG)
  3. Render hook: CapellAdminPlugin injects the tools Livewire component into Filament’s topbar via PanelsRenderHook::GLOBAL_SEARCH_AFTER
  4. Livewire component: The AdminTools Livewire component calls AdminToolRegistry::all() to fetch tools
  5. Blade rendering: The template iterates tools and calls $tool->render() to output each one

Key files:

  • Registry: packages/admin/src/Support/AdminTools/AdminToolRegistry.php
  • Contract: packages/admin/src/Contracts/AdminTools/AdminToolItem.php
  • Topbar hook: packages/admin/src/Filament/Plugin/CapellAdminPlugin.php
  • Livewire component: packages/admin/src/Livewire/Header/AdminTools.php
  • View: packages/admin/resources/views/livewire/header/admin-tools.blade.php (lines 97–99 loop over tools)
namespace Capell\Admin\Contracts\AdminTools;
interface AdminToolItem
{
/** @var string */
public const TAG = 'capell-admin:admin-tool-items';
/**
* Render the tool as an HTML snippet (typically a button).
* Called from the Blade template; output is unescaped via {!! $tool->render() !!}.
*/
public function render(): string;
}

Your tool class must implement this interface with a render() method that returns HTML. The output is injected directly into the dropdown, so you can include a button, link, or any other Filament component.

MethodReturnsPurpose
all()iterable<AdminToolItem>Fetch all tagged tools from the container

The registry has a single public method: all() returns an iterable of all tools tagged with AdminToolItem::TAG. It is typically resolved via the service container and called from the AdminTools Livewire component.

<?php
declare(strict_types=1);
namespace App\Admin\Tools;
use Capell\Admin\Contracts\AdminTools\AdminToolItem;
final class FlushCacheTool implements AdminToolItem
{
public function render(): string
{
return <<<'HTML'
<button
class="fi-dropdown-list-item fi-dropdown-list-item-color-gray flex w-full items-center gap-2 whitespace-nowrap rounded-md p-2 text-sm outline-none transition-colors duration-75 hover:bg-gray-50 focus:bg-gray-50 dark:hover:bg-white/5 dark:focus:bg-white/5"
type="button"
wire:click="flushApplicationCache"
>
{{-- Icon SVG or Filament icon component --}}
<span>Flush Cache</span>
</button>
HTML;
}
private function flushApplicationCache(): void
{
// Logic here (called via Livewire if you add a public method)
}
}
<?php
declare(strict_types=1);
namespace App\Providers;
use App\Admin\Tools\FlushCacheTool;
use Capell\Admin\Contracts\AdminTools\AdminToolItem;
use Illuminate\Support\ServiceProvider;
final class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// Tag the tool during registration, before admin boot
$this->app->tag(
[FlushCacheTool::class],
AdminToolItem::TAG
);
}
}

When the admin panel loads, your tool will appear in the dropdown between the built-in actions. The render() method is called once per page load (in the Livewire view render lifecycle) and rendered unescaped into the dropdown.

  • Register in register(), not boot(): The admin panel boots early and resolves tagged services during its own setup. Tagging in register() ensures the tool is available when the container builds. If you tag in boot(), the tool may be missed.
  • Render must return a string: The Blade template uses {!! $tool->render() !!}, so render() must return a complete HTML string. Fragments are fine as long as they’re valid in a dropdown context.
  • Styling: To match Capell’s admin UI, use the fi-dropdown-list-item classes shown in the example. See admin-tools.blade.php for the exact class structure.
  • Interactivity: For Livewire actions (e.g., wire:click), route them through the AdminTools Livewire component. Custom tools cannot directly define their own Livewire methods — they must delegate to the parent component or use plain JavaScript.