Two small, framework-agnostic Hotwire Turbo helpers.
A TypeScript lifecycle orchestrator for the browser and a Symfony-components frame-redirect listener for the server — each usable on its own.
The two halves solve different problems and only meet on redirect following (the server escalates a frame redirect to a
Turbo-Location header, the browser handler follows it):
@silarhi/turbo(JS/TS): aTurboHandlerthat runs a single pair ofonMount/onUnmountcallbacks across every Turbo Drive, Frame and Stream render.silarhi/turbo-bundle(PHP): a listener that turns a redirect issued inside a Turbo Frame into a full Drive visit, plus theturbo_frameTwig filter. Symfony components only, nosymfony/framework-bundlerequired.
- One lifecycle hook pair:
onMount/onUnmountrun on Drive renders, frame loads and Stream mutations alike - Morph-aware: Stream renders are diffed per node; Drive and Frame morphs can opt into per-element refresh
- Frame-redirect following: a redirect inside a Turbo Frame becomes a full Drive visit,
DELETEredirects too turbo_frameTwig filter: extend a lean frame template only when the request targets a matching frame- Framework-optional: the bundle gives zero-config wiring; the classes also work standalone
- PHP 8.2+ and Symfony components 6.4, 7.x or 8.x
@hotwired/turbo7.1+ or 8.x for@silarhi/turbo(followingDELETEredirects outside a frame needs Turbo 8)
composer require silarhi/turbo-bundle # PHP half
pnpm add @silarhi/turbo # JS half// config/bundles.php
return [
// ...
Silarhi\TurboBundle\SilarhiTurboBundle::class => ['all' => true],
];import { TurboHandler } from '@silarhi/turbo'
new TurboHandler({
onMount: (container) => app.mount(container),
onUnmount: (container) => app.unmount(container),
}).start()Your widgets now mount and unmount on every Turbo render, and a redirect answered to a frame request becomes a full
page visit. Render a lean layout inside frames with {% extends 'base.html.twig'|turbo_frame('main') %}, after
creating that layout in templates/base-frame.html.twig (see the
quick start).
Everything else is on turbo-bundle.silarhi.dev:
- Installation and quick start
- JavaScript:
TurboHandler, stream mutations, morph mutations, frame responses without a matching frame, keeping a redirect in its frame - PHP: frame-redirect following, the
turbo_frameTwig filter, without the framework - Reference: configuration,
TurboHandleroptions, PHP API, HTTP headers
See CONTRIBUTING.md. Release notes are in CHANGELOG.md.
Released under the MIT License.