ibexa/twig-components
Twig Components for Ibexa DXP provides reusable Twig-based UI components and related integration for building and rendering component-driven interfaces within Ibexa projects.
First, the reality check. ibexa/twig-components is not a standalone Composer package you can require into a Laravel app. The README is explicit: "To use this package, install Ibexa DXP." It is a Symfony bundle that ships as part of the Ibexa DXP metapackage, and its license is Ibexa BUL/TTL (subscription or trial) — not MIT. If your project is a plain Laravel app, stop here and treat this as a source of patterns rather than a dependency. If you are on Ibexa DXP, continue.
Prerequisites
Minimal steps (Ibexa DXP project)
composer show ibexa/twig-components. In a modern DXP install it is pulled in transitively — you rarely require it by name.config/bundles.php; if the package was added manually you may need to enable it there.php bin/console cache:clear.vendor/ibexa/twig-components/src/ — bundle class, DI extension, renderer/registry services.vendor/ibexa/twig-components/src/Resources/config/ — service definitions and any Twig path/namespace registration.vendor/ibexa/twig-components/src/Resources/views/ — the actual component templates.vendor/ibexa/twig-components/tests/ — the real documentation; the README contains none.php bin/console debug:twig | grep -i twig-components (or grep for the bundle's Twig path in the service config). That tells you the @Namespace/... prefix to use from your own templates.First use case
Start by consuming an existing component rather than building one. As of v5.0.7 the bundle ships ibexa.Table (added in PR #28). Find its template under Resources/views/, read what context variables it expects, then render it from one of your own Ibexa templates instead of hand-writing <table> markup. That single exercise teaches you the render mechanism, the context contract, and the escaping rules in one pass.
Two distinct roles — pick one deliberately
ibexa/twig-components or another Ibexa bundle.Most application teams only ever need the consumer role. Producing components is worth it only once you have three or more places repeating the same markup.
Discover the registration mechanism from the source, not from blogs
Read the DI extension and the renderer/registry service class first. The general shape in Ibexa is: services tagged or configured with a component name, resolved by a renderer that hands a context array to a Twig template. Once you know the tag name, bin/console debug:container --tag=<tag> lists everything registered — that is your live component catalogue.
Composition pattern
Prefer composing components inside Twig (include/embed of the component's template, or the package's render function if one is exposed) over calling back into PHP. Keeping the tree entirely in Twig preserves the "no controller round-trip" benefit and keeps caching predictable.
Data passing pattern
Keep contexts as plain arrays or scalar/simple objects built in the view layer. Ibexa's own ContentView / ViewBuilder is where content-aware data should be assembled; components should receive already-resolved data and stay presentation-only. If a component needs to query the repository, that logic belongs in a view builder or a dedicated Twig function, not in the template.
Integration tips
templates/bundles/<BundleName>/<path>.html.twig in your project so your copy wins without forking the vendor package. This is the safest customisation path and survives patch releases.ibexa/twig-components follows the DXP branch (4.6.x vs 5.0.x); letting Composer float these independently is how you get a template expecting a context key your code no longer supplies.ibexa.Table (vendor-prefixed names). It makes it obvious in a stack trace which bundle owns a template.symfony/ux-twig-component or a small Blade component set. Do not attempt to bridge this bundle into Laravel — see Gotchas.The Laravel mismatch is fundamental, not cosmetic. Several third-party write-ups claim this "plays well with Laravel's service container", offers "pagination, sorting, and dynamic content binding", or can be embedded in Blade via a Twig bridge. None of that is evidenced by the package's own documentation or release notes. The releases mention exactly two functional changes across the whole visible history: the ibexa.Table component (v5.0.7) and nullable parameter type declarations (v4.6.25 / v5.0.3). Everything else is "no significant changes". Treat enthusiastic capability claims as unverified until you have read the templates yourself.
Licensing is a hard gate, not a formality. NOASSERTION on the license field means Composer cannot tell you your obligations. You need a subscription or trial grant with repository credentials configured. There is no community edition of this package.
Branch/version alignment. 4.6.x and 5.0.x are separate maintenance branches with separate release streams. Running a v5 component template on a v4.6 DXP (or vice versa) is the most likely cause of a blank render or a missing-variable Twig error. Check composer show ibexa/twig-components against composer show ibexa/dxp before debugging anything else.
Caching will waste your afternoon. Twig caches compiled templates and Symfony caches the container. After any template or service-tag change, run php bin/console cache:clear and check var/cache/<env>/twig/. In prod the Twig cache does not self-invalidate for overridden templates placed in unusual paths.
Escaping. Component templates typically emit markup, so the render call's output must be printed unescaped (|raw or the renderer already returns Twig\Markup). Verify which — if you double-escape you get visible HTML entities; if user-supplied context reaches a |raw path you have XSS. Grep the component template for |raw before passing any CMS-editable content into it.
Debugging toolkit
php bin/console debug:twig — confirm the namespace and that the template is resolvable.php bin/console debug:container --tag=<component-tag> — confirm your component is registered.php bin/console lint:twig <path> — catch syntax errors without a browser.php bin/console debug:router / profiler — when a component renders empty, check whether the context array arrived at all before blaming the template.{% dump %} with the profiler enabled to see the actual context keys.Extension points worth knowing. Template overrides (project-level templates/bundles/...), additional Twig extensions registered in your own bundle, and service tags for registering new components. If you need behaviour the component doesn't offer, add a Twig function that pre-formats the data rather than pushing conditionals into the shared template — you will be sharing that template with the rest of the DXP.
Patch releases are cheap to take. The 4.6.21 → 4.6.30 and 5.0.0 → 5.0.8 ranges are almost entirely no-op or type-safety changes. Stay current on patches; the only behavioural change to plan around in this window is the arrival of ibexa.Table.
How can I help you explore Laravel packages today?