Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twigx Bundle Laravel Package

lmc/twigx-bundle

LMC TwigX Bundle integrates TwigX with Symfony to extend Twig templating capabilities, adding convenient template helpers and configuration for Symfony applications. Install via Composer and enable the bundle to build expressive, reusable views more easily.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first. lmc/twigx-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no Blade compiler, no config/twigx.php. It wires the alma/twigx Twig extension (JSX-like component tags such as <Button label="Save" />) into Symfony's Twig service definition. In a Blade-first Laravel app you have two honest options: (a) add Twig via a bridge and register the extension manually, or (b) don't — use Blade components and keep the DX you already have. Treat this as a spike until it proves itself on one screen.

Minimal path — Laravel + Twig bridge

composer require lmc/twigx-bundle
# and a Twig bridge, e.g.
composer require rcrowe/twigbridge
  1. php artisan vendor:publish the Twigbridge config so Laravel knows where your .twig views live (usually resources/views).
  2. Do not register Lmc\TwigXBundle\TwigXBundle — there is no Laravel bundle registry. You need to reach into the bundle's Twig extension class and register it on the Twig\Environment the bridge builds.
  3. Component templates go in a directory the extension's loader can resolve (conventionally templates/components/ or resources/views/components/ in a Laravel layout). Point the loader there.
  4. Clear both Laravel's view cache and Twig's compiled cache (storage/framework/views) after config changes.

Where to look in the repo (in this order)

  • DependencyInjection/ — the extension's config tree tells you exactly which options exist (component path, tag prefix, whether the Symfony container is required for resolution). This is the pivotal question: if component resolution injects ContainerInterface, standalone registration is painful and you should stop.
  • Resources/config/services.yaml (or services.php) — shows which arguments the Twig extension takes. Anything that's a plain array/string is easy to port to Laravel; anything that's a service is a wiring problem.
  • The Twig extension class itself — confirm it implements Twig\Extension\ExtensionInterface and registers node visitors only (no container lookups at render time).
  • README / tests — check for a standalone (non-Symfony) example or test. If tests boot the kernel, assume you're on your own.

First use case to spike

One self-contained, low-blast-radius surface: a card or button component with a couple of props and a children/slot block, rendered inside a Twig view that Laravel serves for a single route. That single test decides everything — if it renders, you have a template-by-template migration path; if resolution needs the Symfony container, you drop it and move on. Budget half a day, not a sprint.

{# resources/views/components/card.twig #}
<div class="card">
  <h2>{{ title }}</h2>
  {{ children }}
</div>
{# resources/views/pages/dashboard.twig #}
<Card title="Revenue">
  <p>Up 12% week over week.</p>
</Card>

If that doesn't render without kernel boot, the adoption question is already answered.

Implementation Patterns

Component boundaries, not page templates. Adopt per-template. Twig and Blade can coexist on the same route table as long as view resolution is unambiguous — so migrate one feature area at a time. Keep Twigx components in exactly one namespace and one directory; everything else stays Blade. This is what makes rollback a config change instead of a rewrite.

Abstract the engine behind one service. Whatever renders Twigx pages, funnel it through a single application service (e.g. TwigViewRenderer) that takes a view name and data. Call sites never touch Twig\Environment directly. When the package stalls or you drop it, you swap the implementation of one class.

Props over context soup. The reason to use this at all is explicit contracts. Pass props through the tag, resolve them inside the component template, and keep them typed-by-convention (document expected types in a comment above the component). Don't reach for {{ global_var }} inside components — that recreates the include-with-context problem you're trying to solve, and it makes components untestable in isolation.

Slots / children pattern. Use the children block for structural composition and props for data. A component that takes both children and arbitrary named props should be the exception, not the default — that's the shape that becomes unreadable at review time.

Registration pattern (Laravel side). A small service provider that resolves the Twig environment, instantiates the Twigx extension with the arguments you traced from the bundle's service definition, and calls addExtensions(). Register Twig_Extension/ExtensionInterface once. If the extension ships node visitors, they get registered via the extension itself — don't add them twice or Twig will complain about duplicate node classes.

// app/Providers/TwigxServiceProvider.php (sketch)
$this->app->resolved('twig', function ($twig) {
    $twig->addExtension(new \Alma\Twigx\Extension\TwigxExtension(
        componentsPath: resource_path('views/components'),
        // only arguments that are NOT service references
    ));
});

Confirm the constructor signature against the bundle source before writing this — the bundle may add Symfony-specific arguments you need to null out or replace with plain objects.

Config pattern. Every knob the bundle exposes (component path, tag prefix, any escaping toggles) should live in config/twig.php (or a dedicated config/twigx.php if you publish one yourself), not sprinkled through providers. Pin the package version in composer.json — "lmc/twigx-bundle": "1.*" is too loose for a package with zero dependents.

Integration with Laravel tooling. Register a Blade-less lint step for .twig files in CI (twig/twig's LintCommand or a small custom command), otherwise broken templates hit production. Add .twig to your editor's file associations for Twig syntax highlighting; the JSX-like tags will not be highlighted and will be flagged by some Twig linters. Expect that and don't fight it.

Test pattern. Render every component in isolation in a test and assert on escaped output — not just "it renders", but "a <script> in a prop is escaped". This is the cheapest way to catch the escaping-divergence risk that reviewers will miss by eye.

Gotchas and Tips

It's a Symfony bundle; assume the container. The bundle's service definition likely passes the Symfony ContainerInterface or a service-locator to the extension for component resolution. If so, standalone Twig registration needs you to supply a substitute that resolves components by path. Read DependencyInjection/ before writing a single line of glue. If you can't substitute it cleanly, that's your stop signal.

No Laravel service provider, ever — and don't fake one. Registering Lmc\TwigXBundle\TwigXBundle in config/app.php will do nothing at best and fatal at worst. The package relies on the Symfony HttpKernel/DI lifecycle; Laravel's container is a different contract.

Custom syntax breaks your entire tooling chain. TwigX's tags aren't standard Twig. That means no IDE completion, no working twigcs/linter rules out of the box, no static analysis, and reviewers who don't know the syntax will approve broken templates. Budget for this as a permanent, per-hire cost — not a one-time setup cost.

Escaping semantics are the security unknown. Confirm that interpolation inside component tags uses Twig's auto-escaping defaults. The custom parser may generate code that bypasses Twig\Environment's escaping. Write the isolation test above and make it part of CI before any component touches production.

Parse errors surface against compiled PHP. Twig compiles to PHP in storage/framework/views. When a TwigX template fails to parse, the stack trace points at generated code, not your .twig file. To debug: clear the compiled view cache (php artisan view:clear), re-render, and read the first Twig exception — the underlying Twig\Error\SyntaxError names the line. Keep a clean-cache step in your deploy script or you'll chase ghosts.

Two view engines, two caches, two lifespans. Blade and Twig compile independently. A deploy that clears one and not the other serves stale markup. Ensure view:clear (Laravel) and the Twig cache directory are both invalidated, and both directories are writable by the web user. On multi-server setups, warm both caches in the deploy pipeline, not at first request.

View resolution order is a live footgun. dashboard.blade.php and dashboard.twig in the same folder is asking for trouble. Namespace Twig views (resources/views/twig/… or a dedicated resources/twig/) so route → template resolution can't be ambiguous, and document the rule in your repo.

Pin and vendor. With 11 stars and zero dependents, treat this as internal code from day one. Fork under a private namespace, pin the version, and keep a changelog. Twig major releases will force you to patch the parser yourself — assume no upstream fix will arrive.

Extension points to use instead of editing the package: the Twig loader (point it wherever you like), the Twig extension registration (wrap the extension in your own decorator if you need extra props/logic), and the renderer service abstraction. Don't patch vendor files — fork and commit if you need real changes.

When to abandon. If the spike shows (a) container coupling you can't substitute, (b) escaping behavior you can't verify, or (c) a linter/IDE story your team refuses to live with — stop. symfony/ux-twig-component has the same conceptual model with first-party backing, and Blade components already solve most of it in a Laravel shop without a second engine.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect