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

Fragment Kit Bundle Laravel Package

nowo-tech/fragment-kit-bundle

Symfony bundle that packages a reusable kit of front-end fragments for building web interfaces. Install it with Composer, register the bundle, and compose the supplied fragments into your own templates. Bundle configuration lets you tailor the kit to fit each project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the contract before writing templates.

composer require nowo-tech/fragment-kit-bundle

Flex registers the bundle automatically; otherwise add it to config/bundles.php. Then, before touching any Twig file, spend five minutes reading the actual surface area — this is a small bundle, so the whole contract is in three places:

  • src/DependencyInjection/Configuration.php — the config tree, i.e. the only source of truth for option names.
  • src/Twig/ — the extension/runtime that exposes the Twig function and how it resolves templates.
  • src/Resources/config/ — service IDs you may want to decorate or override (these are public extension points; the project's BC rules forbid renaming them without warning).

Dump the reference rather than guessing at keys:

php bin/console config:dump-reference fragment_kit   # confirm the actual alias
php bin/console debug:twig | grep -i fragment        # confirm the function name

First use case: wrap the one widget that actually fails.

The bundle exists for "third-party / expensive / flaky fragment, render something sane instead of a 500". Do not adopt it as a general try/catch around Twig. The canonical shape is: a fragile include + a deliberately boring fallback template.

{# templates/page/home.html.twig #}
{# confirm the function name via debug:twig; shape is render-with-fallback #}
{{ fragment_kit_render('recommendations/recommendations.html.twig', {
    userId: app.user ? app.user.id : null,
}, {
    fallback: 'recommendations/_unavailable.html.twig',
}) }}
{# templates/recommendations/_unavailable.html.twig #}
{# static, dependency-free, always renderable #}
<div class="recommendations recommendations--empty" aria-hidden="true"></div>

Pick your first target deliberately: a homepage carousel or ad slot where a failure is cosmetic, so you can ship it and observe Sentry volume for a week before applying it to anything revenue-bearing.

Implementation Patterns

1. Template-first, service-second. Most day-to-day use is the Twig call above. Reach for the renderer service only where Twig isn't in play — queued jobs, mailers, PDF generation — and inject it by its documented service ID rather than by class name, so a future decoration doesn't break you.

2. Fallback template tiers. Decide per fragment which fallback class you want, and encode it as a convention so reviewers can spot violations:

  • Empty shell — static markup, zero Twig logic, zero variables. Default choice.
  • Cached last-good — serve the previously rendered HTML from cache. Tempting, but the fallback now has a cache dependency that can also fail; treat it as a separate, separately-tested path.
  • Degraded variant — a cheaper query/reduced payload. Highest quality, highest maintenance cost.

3. Scope the blast radius at the boundary that matters. Resilience is per-fragment, not per-page. Do not wrap a whole layout: if the layout's fallback renders, you've masked a real regression and the user gets a blank page with a 200 status, which is worse than a 500 for observability.

4. Treat Sentry reporting as production-only, sampled, and tagged. Put the whole config under when@prod so local exceptions stay loud in the profiler (see Gotchas), and set an event rate limit or sample rate per fragment. Tag events with the fragment key so you can build one alert per fragile widget instead of one noisy alert for the whole app.

# config/packages/fragment_kit.yaml
fragment_kit:
  # ...options from config:dump-reference...
  sentry:
    enabled: true
    # tag events so alerting can be per-fragment
# config/packages/fragment_kit.yaml
when@test:
  fragment_kit:
    sentry:
      enabled: false   # keep test output clean; assert on fallback HTML instead

when@prod:
  fragment_kit:
    sentry:
      enabled: true

5. Test the failure path, not the happy path. The happy path is already covered by the fact the fragment renders normally. The valuable test forces the inner template or its controller to throw and asserts the fallback HTML and a 200:

public function testFragmentFallsBackWhenRendererThrows(): void
{
    $this->client->request('GET', '/');
    $this->assertResponseIsSuccessful();
    $this->assertSelectorExists('.recommendations--empty');
}

Pair it with a controller route that throws only when a query flag is set, so you don't need to mock the renderer.

6. Compose with fragment/HTTP caching carefully. If a page is cached, the fragment's failure gets frozen into HTML until the cache entry expires. Prefer rendering fragile fragments with a short TTL, or render them outside the cached shell (ESI) so a single bad render doesn't poison a long-lived entry.

7. Migrate incrementally. Apply to one fragment, watch Sentry for a week, then expand. A bundle with zero dependents and a 0.x-ish adoption footprint means you are the primary source of field reports — start where a bug report already exists.

Gotchas and Tips

Swallowed exceptions are invisible in the profiler. Because the bundle catches and returns a fallback, dev may look healthy while a fragment is silently broken. Keep reporting on in dev during rollout, or at minimum ensure the failure is logged at warning with the fragment key. If you add when@test: enabled: false, don't copy that block into dev.

The fallback must not share dependencies with the failing fragment. If the fallback uses the same service, client, or DB table that just failed, the "resilient" render becomes a second exception — and this one isn't caught, so you get a genuine 500. Keep fallbacks to static markup and literal strings.

Nested fragments multiply latency and hiding. A guarded fragment containing another guarded fragment means an inner failure can be indistinguishable from an outer one in logs. Flatten before adopting, or ensure the fragment key differs at each level so Sentry grouping stays useful.

Don't over-report expected failures. A third-party 503 that you already handle gracefully is not a bug; it's the feature working. Configure ignored exception types/status codes for upstream client errors, otherwise Sentry volume drowns the signal and the team mutes the project.

Exception construction is not free. On a hot path with a fragment that fails often (e.g. under sustained upstream outage), you're building and catching exceptions per request. If this shows up in profiles, cache a short-lived "fragment down" flag (or rely on the fragment cache) rather than retrying-and-failing every request.

Config quirks to check first when behaviour surprises you:

  • DSN/enablement leaking from env vars — verify with bin/console debug:container --env-vars | grep -i sentry.
  • strict_variables is irrelevant inside the bundle's catch, but a missing variable in the fallback is a hard error; fallbacks should reference no variables.
  • Twig template resolution uses the bundle's namespace/paths — a fallback defined only in an app bundle may not be found if the resolver is scoped. Confirm with bin/console debug:twig --filter=<fallback path>.

Extension points, in order of safety: a custom fallback template (zero risk) → an event listener/subscriber if the bundle dispatches one for render failures (log enrichment, metrics) → decorating the renderer service by its documented ID (safe, but respect the public-ID BC promise) → forking the resolver (last resort).

Debugging recipe when a fragment "randomly" falls back: search logs for the fragment key, not the exception class — the catch point is where the key is logged. Then reproduce by calling the inner template directly with {% include %} in a scratch template; if it renders there but falls back in place, the difference is context (missing variables, locale, request scope), not the bundle.

Version discipline. With ^7.4 || ^8.0 Symfony constraints and PHP >=8.2, pin the bundle minor in composer.json if you depend on specific fallback/Sentry option semantics; there is no large install base to surface regressions for you.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager