jh3ady/inertia-bundle
Inertia bundle for Symfony
A small, server-side adapter for the Inertia.js v3 protocol. It lets your Symfony controllers return Inertia responses (a page component plus props) instead of Twig templates, while your frontend stays a single-page app built with React, Vue or Svelte.
It is deliberately minimal and bundler-agnostic: it does not bundle Vite, Webpack Encore or AssetMapper. You bring your own asset pipeline; this bundle only handles the protocol and a single Twig helper.
Requirements
- PHP 8.2+
- Symfony 6.4, 7.x or 8.x
- Twig
Installation
composer require jh3ady/inertia-bundle
If you do not use Symfony Flex, enable the bundle manually:
// config/bundles.php
return [
// ...
Jh3ady\InertiaBundle\InertiaBundle::class => ['all' => true],
];
Configuration
All keys are optional and shown with their defaults:
# config/packages/inertia.yaml
inertia:
root_view: 'app.html.twig' # template rendered on the initial load
root_id: 'app' # mount element id; must match createInertiaApp({ id })
version: ~ # asset version used to invalidate stale visits
Usage
Controller
Inject the Inertia service and return render(component, props):
use Jh3ady\InertiaBundle\Inertia;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class DashboardController
{
public function __construct(private readonly Inertia $inertia)
{
}
#[Route('/', name: 'dashboard')]
public function index(): Response
{
return $this->inertia->render('Dashboard', [
'message' => 'Hello from Symfony',
]);
}
}
Root template
Drop {{ inertia() }} into your root template. It emits the mount element and
the page object as a JSON script tag, exactly the way the Inertia v3 client
reads it. The output is safe by design: the page is hex-escaped so a prop value
can never break out of the script tag, so you never write |raw yourself.
{# templates/app.html.twig #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{# load your JS/CSS with your own bundler (Vite, Encore, AssetMapper) #}
</head>
<body>
{{ inertia() }}
</body>
</html>
Pass an id to override the configured root_id for a specific template:
{{ inertia('root') }}.
Frontend
Set up the Inertia client for your framework as described in the
official documentation. The id
passed to createInertiaApp must match the bundle's root_id.
Shared props
Props that every page should receive (the authenticated user, flash messages, the locale) can be shared once, typically from an event listener:
$this->inertia->share('locale', $request->getLocale());
License
MIT © Jean-Denis VIDOT