Skip to content

Inertia.js integration

Inertia.js doesn’t require any integration configuration out of the box, however there are a few things to keep in mind.

Redirects across domains (often using e.g. tenancy()->impersonate()) require that you use Inertia::location(). That way, a “regular” window.location = ... redirect is performed, rather than a fetch() that may get blocked (you’d see CORS errors in the dev console in such a case).

// Instead of:
redirect(tenant_route('foo.acme.com', 'home'));
// Use:
Inertia::location(tenant_route('foo.acme.com', 'home'));

Depending on your frontend setup, you may be using Ziggy or Wayfinder to generate routes. These should generally work out of the box in a multi-database setup. In a setup with path identification, i.e. where routes have {tenant} parameters, you may need to ensure the parameter is being passed to the routes.

The basic approach is to simply do this manually — share the tenant ID (or preferably a slug so you don’t needlessly expose the tenant ID to the frontend) — with the frontend, as a global JavaScript variable in a Blade template, and then simply reference that variable when generating routes.

If you set URL::defaults(), Ziggy will generally respect that and you will not need to do the above.

You can either do that manually:

URL::defaults(['tenant' => tenant()->id]);
// or if you use {tenant:slug} parameters:
URL::defaults(['tenant:slug' => tenant()->slug]);

or use the UrlGeneratorBootstrapper which automatically sets URL defaults (and optionally other things — see the relevant documentation and class docblocks).

One additional use of the UrlGeneratorBootstrapper is that it can prefix route names (rather than just setting parameters) depending on the current context. This can be useful if you’re integrating with packages or starter kits specifically with route cloning. In other words, you have duplicated versions of, at least some, routes as in:

  • home
  • tenant.home
  • posts.index
  • tenant.posts.index

In such cases, if views or controllers are being shared, it would be impractical to have to modify each route() call to be conditional like this:

tenant() ? route('tenant.foo', tenant()) : route('foo');

The URL generator can prefix route names for you automatically if you’re in the tenant context.

This however only applies to routes generated server-side, not in JavaScript using tools like Ziggy.

Instead, you’d need to use an override like this:

resources/views/app.blade.php
@routes
<script>
window.tenancyInitialized = {{ tenant() ? 1 : 0 }}
if (window.tenancyInitialized) {
const oldRoute = window.route
window.route = function (name, params, absolute, config) {
if (name && ! name.startsWith('tenant.')) {
name = 'tenant.' + name
}
return oldRoute(name, params, absolute, config)
}
}
</script>
@vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"])

That change will affect window.route() calls, i.e. route() calls in general JavaScript context.

In Vue.js, you may also need to use an additional override like this:

resources/js/app.js
import { createApp, h } from 'vue';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
// ...
const ZiggyVue = {
install(app, options) {
const r = (name, params, absolute, config = options) => {
if (window.tenancyInitialized && (name && ! name.startsWith('tenant.'))) {
name = 'tenant.' + name
}
return route(name, params, absolute, config);
};
if (parseInt(app.version) > 2) {
app.config.globalProperties.route = r;
app.provide('route', r);
} else {
app.mixin({
methods: {
route: r,
},
});
}
}
};
createInertiaApp({