Extending Asset & Result Rendering with Render Hooks
The Render Hook system lets you inject custom content into asset and result components at specific locations—without overwriting Blade files. This is the recommended, future-proof way for any package to extend Capell Frontend UI.
How It Works
Section titled “How It Works”- Register extensions for named locations using the
RenderHookLocationenum (e.g.BeforeTitle,AfterTitle,Footer,BeforeResult,AfterResult,AssetTags, etc). - Each extension receives a
RenderHookContextDTO (withlocation,item, and extensible data) and returns HTML/Blade output. - Extensions can be:
- Closures
- Classes implementing
RenderHookExtensionInterface - Blade view/component names (as strings)
- All registered extensions for a location are rendered at the corresponding hook in the UI, sorted by priority (lower numbers first).
- Granular control: You can scope a hook registration to a specific scenario (e.g. only for assets, or only for a specific Blade file/component) using the
scenarioandtargetparameters.
Registering an Extension
Section titled “Registering an Extension”In your package’s service provider:
use Capell\Frontend\Data\RenderHookContext;use Capell\Frontend\Enums\RenderHookLocation;use Capell\Frontend\Support\Render\RenderHookRegistry;
// Register for all assetsapp(RenderHookRegistry::class)->register( RenderHookLocation::AfterTitle, function (RenderHookContext $context) { return view('your-package::partials.asset-badge', ['context' => $context])->render(); }, 10, // priority 'asset' // scenario);
// Register for a specific file/componentapp(RenderHookRegistry::class)->register( RenderHookLocation::AfterTitle, 'your-package::components.asset-badge', 10, // priority 'asset', // scenario 'asset/tile.blade.php' // target);When rendering, the scenario and target are passed automatically by the Blade component:
{!! app(RenderHookRegistry::class)->renderAll( RenderHookLocation::AssetTags, [ 'tags' => $tags, 'item' => $item ?? null, ], 'asset', 'asset/tile.blade.php', )!!}Where Hooks Render
Section titled “Where Hooks Render”Hooks are available in:
x-capell-frontend::asset.tile(BeforeTitle,AfterTitle,Footer,AssetTags)x-capell-frontend::asset.index(same)x-capell-frontend::page.results(BeforeResult,AfterResult)
Example: Adding a Badge
Section titled “Example: Adding a Badge”- Create a Blade partial or component in your package:
{{-- resources/views/components/asset-badge.blade.php --}}@if ($context->item['is_featured'] ?? false) <span class="badge badge-featured">Featured</span>@endif- Register the extension for the desired location and scenario (see above).
Extension Priority
Section titled “Extension Priority”- Lower priority numbers render first.
- Multiple packages can register for the same location—output is composable.
Context DTO
Section titled “Context DTO”- The
RenderHookContextDTO provides the hook location and the current item. - Extend this DTO if you need to pass more data in the future.
Contract
Section titled “Contract”- Implement
RenderHookExtensionInterfacefor reusable, testable extensions.
Testing
Section titled “Testing”- See
tests/Frontend/Unit/RenderHookExtensionRegistryTest.phpfor real-world examples, including scenario/target-specific hooks.
Best Practices & Notes
Section titled “Best Practices & Notes”- Extensions are rendered in the order of their priority for each location.
- You have full access to the current context object.
- This mechanism is additive and composable—multiple packages can contribute extensions at any hook.
- Prefer this system over Blade overrides for maintainability and upgrade safety.
- Use scenario/target scoping for granular control when needed.