Skip to content

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.


  • Register extensions for named locations using the RenderHookLocation enum (e.g. BeforeTitle, AfterTitle, Footer, BeforeResult, AfterResult, AssetTags, etc).
  • Each extension receives a RenderHookContext DTO (with location, 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 scenario and target parameters.

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 assets
app(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/component
app(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',
)
!!}

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)

  1. 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
  1. Register the extension for the desired location and scenario (see above).

  • Lower priority numbers render first.
  • Multiple packages can register for the same location—output is composable.

  • The RenderHookContext DTO provides the hook location and the current item.
  • Extend this DTO if you need to pass more data in the future.

  • Implement RenderHookExtensionInterface for reusable, testable extensions.

  • See tests/Frontend/Unit/RenderHookExtensionRegistryTest.php for real-world examples, including scenario/target-specific hooks.

  • 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.