jh3ady/inertia-bundle

Inertia.js v3 server-side adapter for Symfony.

Maintainers

Package info

github.com/jh3ady/inertia-bundle

Type:symfony-bundle

pkg:composer/jh3ady/inertia-bundle

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-06-26 19:31 UTC

This package is auto-updated.

Last update: 2026-06-26 19:42:34 UTC


README

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