A lightweight Fastify plugin for Inertia.js that lets you build modern single-page applications with server-side rendering.
npm install alex-fastify-inertiajs

A lightweight Fastify plugin for Inertia.js that lets you build modern single-page applications with server-side rendering. It allows seamless integration of React, Vue, or Svelte components while preserving the simplicity of classic apps.
- Server-Side Rendering (SSR) support for improved SEO and performance
- Vite integration for fast development and optimized builds
- Framework agnostic - works with React, Vue, or Svelte
- Lightweight Fastify plugin with minimal configuration
- TypeScript support with full type definitions
The fastest way to get started is using our official templates:
``bashFor React
npx degit mahendra7041/fastify-inertia/examples/react my-inertia-app
cd my-inertia-app
npm install
npm run dev
`
- Node.js 18 or higher
- Fastify
- Vite
First, create a new project using Vite with your preferred framework:
`bashFor React (used in this guide)
npm create vite@latest my-inertia-app -- --template react
cd my-inertia-app
`
Install the necessary dependencies for Fastify and Inertia:
`bashFor React (used in this guide)
npm install fastify-inertiajs @fastify/cookie @fastify/static @inertiajs/react
$3
Set up your project structure as follows:
`
my-inertia-app/
├── build/ # Generated build artifacts
├── public/ # Static assets
├── src/
│ ├── pages/ # Inertia page components
│ ├── assets/ # Styles, images, etc.
│ ├── main.jsx # Client entry point (or .js/.vue/.svelte)
│ └── ssr.jsx # SSR entry point (optional)
├── index.html # HTML template
├── vite.config.js # Vite configuration
├── server.js # Fastify server
└── package.json
`$3
`html
class="bg-neutral-50 text-black selection:bg-teal-300 dark:bg-neutral-900 dark:text-white dark:selection:bg-pink-500 dark:selection:text-white"$3
`javascript
import fastify from "fastify";
import fastifyStatic from "@fastify/static";
import fastifyCookie from "@fastify/cookie";
import inertia from "fastify-inertiajs";
import path from "path";
import { fileURLToPath } from "url";const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function bootstrap() {
const app = fastify();
const PORT = process.env.PORT || 5000;
// Serve static files in production
if (process.env.NODE_ENV === "production") {
await app.register(fastifyStatic, {
root: path.join(__dirname, "build/client"),
prefix: "/",
decorateReply: false,
});
}
await app.register(fastifyCookie);
await app.register(inertia, {
rootElementId: "root",
assetsVersion: "v1",
ssrEnabled: true,
ssrEntrypoint: "src/ssr.jsx",
ssrBuildEntrypoint: "build/ssr/ssr.js",
});
app.get("/", (req, reply) => {
reply.inertia.render("home");
});
try {
await app.listen({ port: PORT });
console.log(
Server is running at http://localhost:${PORT});
} catch (err) {
console.error(err);
process.exit(1);
}
}bootstrap().catch(console.error);
`$3
`json
{
"scripts": {
"dev": "nodemon server.js",
"start": "cross-env NODE_ENV=production node server.js",
"build": "npm run build:ssr && npm run build:client",
"build:client": "vite build --outDir build/client",
"build:ssr": "vite build --outDir build/ssr --ssr src/ssr.jsx"
}
}
`$3
Update your framework's main entry point accordingly. For more details, visit Inertia.js Client-Side Setup:
`javascript
import { createInertiaApp } from "@inertiajs/react";
import { createRoot } from "react-dom/client";createInertiaApp({
id: "root",
resolve: (name) => {
const pages = import.meta.glob("./pages/*/.jsx", { eager: true });
return pages[
./pages/${name}.jsx];
},
setup({ el, App, props }) {
createRoot(el).render( );
},
});
`$3
Add Server-Side Rendering support for improved SEO and performance.
`javascript
import ReactDOMServer from "react-dom/server";
import { createInertiaApp } from "@inertiajs/react";export default function render(page) {
return createInertiaApp({
id: "root",
page,
render: ReactDOMServer.renderToString,
resolve: (name) => {
const pages = import.meta.glob("./pages/*/.jsx", { eager: true });
return pages[
./pages/${name}.jsx];
},
setup: ({ App, props }) => ,
});
}
`Configuration
$3
| Option | Type | Default | Description |
| ---------------------- | -------------------- | --------------------------------------------------------- | ------------------------------------------------------------- |
|
rootElementId | string? | "app" | DOM element ID where the Inertia app mounts |
| assetsVersion | string? | "v1" | Version string used for inertia |
| encryptHistory | boolean? | true | Encrypts the Inertia history state for security |
| indexEntrypoint | string? | "index.html" | Path to your base HTML template (used in dev mode) |
| indexBuildEntrypoint | string? | "build/client/index.html" | Path to the built client HTML entrypoint (used in production) |
| ssrEnabled | boolean? | false | Enables/disables server-side rendering (SSR) |
| ssrEntrypoint | string? | Required if ssrEnabled: true | Path to your SSR entry file (used in development) |
| ssrBuildEntrypoint | string? | Required if ssrEnabled: true | Path to the built SSR bundle (used in production) |
| vite | ViteResolveConfig? | { server: { middlewareMode: true }, appType: "custom" } | Passes custom options to the Vite dev server |API Reference
$3
Initializes and returns the Fastify middleware.
`javascript
await fastify.register(inertia, inertiaConfig);
`$3
Renders an Inertia page component.
`javascript
fastify.get('/users', (request, reply) => {
const users = await User.findAll(); reply.inertia.render('user/index', {
users: users,
page: req.query.page || 1
});
});
`$3
Shares data with the current and subsequent requests.
`javascript
reply.inertia.share({
auth: {
user: req.user,
permissions: req.user?.permissions,
},
});
`$3
Redirects the user to a different location while preserving Inertia’s client-side navigation.
`javascript
fastify.get("/home", (req, reply) => {
// Redirect with default status (302 Found)
reply.inertia.redirect("/dashboard"); // Redirect with explicit status
reply.inertia.redirect(301, "/new-home");
});
`Contributing
We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.
$3
1. Fork the repository
2. Create your feature branch:
`bash
git checkout -b feat/amazing-feature
`3. Commit your changes with a descriptive message:
`bash
git commit -m "feat: add amazing feature"
`4. Push to your branch:
`bash
git push origin feat/amazing-feature
``5. Open a Pull Request
If your contribution introduces a breaking change (e.g. changes to configuration options, API methods, or default behavior), please open an issue or discussion first before submitting a PR. This ensures we can:
- Discuss the impact on existing users
- Decide if a major version bump is required
- Provide a clear migration path in the documentation
This project is licensed under the MIT License - see the LICENSE file for details.
- Inertiajs Documentation
- Reactjs Documentation
- Fastify Documentation
- Vite Documentation