
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
express-inertia
Advanced tools
A lightweight Express.js middleware/adapter for Inertia.js that lets you build modern single-page applications with server-side rendering.
A lightweight Express.js middleware/adapter 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.
Check out a live demo of express-inertia in action: Pingcrm
The fastest way to get started is using our official templates:
# For React
npx degit mahendra7041/express-inertia/examples/react my-inertia-app
# For Vue
npx degit mahendra7041/express-inertia/examples/vue my-inertia-app
# For Svelte
npx degit mahendra7041/express-inertia/examples/svelte my-inertia-app
cd my-inertia-app
npm install
npm run dev
First, create a new project using Vite with your preferred framework:
# For React (used in this guide)
npm create vite@latest my-inertia-app -- --template react
# For Vue
npm create vite@latest my-inertia-app -- --template vue
# For Svelte
npm create vite@latest my-inertia-app -- --template svelte
cd my-inertia-app
Install the necessary dependencies for Express and Inertia:
# For React (used in this guide)
npm install express-inertia express express-session @inertiajs/react
# For Vue
npm install express-inertia express express-session @inertiajs/vue3
# For Svelte
npm install express-inertia express express-session @inertiajs/svelte
# Additional dev dependencies
npm install -D nodemon
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 # Express server
└── package.json
index.html)<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- @inertiaHead -->
</head>
<body
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"
>
<!-- @inertia -->
<script type="module" src="/src/main.Jsx"></script>
</body>
</html>
server.js)import express from "express";
import session from "express-session";
import inertia from "express-inertia";
async function bootstrap() {
const app = express();
const PORT = process.env.PORT || 3000;
// Serve static assets (only in production)
if (process.env.NODE_ENV === "production") {
app.use(express.static("build/client", { index: false }));
}
// Session middleware (required for flash messages)
app.use(
session({
secret: process.env.SESSION_SECRET || "secret",
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === "production",
},
})
);
// Inertia middleware setup
app.use(
await inertia({
rootElementId: "root", // DOM element ID for Inertia app (default: app)
assetsVersion: "v1", // change to bust client-side cache
ssrEnabled: true, // enable SSR
ssrEntrypoint: "src/ssr.jsx", // entry file for SSR in dev
ssrBuildEntrypoint: "build/ssr/ssr.js", // built SSR file for production
})
);
// Example route
app.get("/", (req, res) => {
res.inertia.render("home");
});
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});
}
bootstrap().catch(console.error);
{
"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"
}
}
Update your framework's main entry point accordingly. For more details, visit Inertia.js Client-Side Setup:
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(<App {...props} />);
},
});
Add Server-Side Rendering support for improved SEO and performance.
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 }) => <App {...props} />,
});
}
| 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 |
inertia(config?, vite?)Initializes and returns the Express middleware.
app.use(await inertia(config));
res.inertia.render(component, props?)Renders an Inertia page component.
app.get('/users', (req, res) => {
const users = await User.findAll();
res.inertia.render('user/index', {
users: users,
page: req.query.page || 1
});
});
res.inertia.share(data)Shares data with the current and subsequent requests.
app.use((req, res, next) => {
res.inertia.share({
auth: {
user: req.user,
permissions: req.user?.permissions,
},
});
next();
});
res.inertia.redirect(urlOrStatus, url?)Redirects the user to a different location while preserving Inertia’s client-side navigation.
app.get("/home", (req, res) => {
// Redirect with default status (302 Found)
res.inertia.redirect("/dashboard");
// Redirect with explicit status
res.inertia.redirect(301, "/new-home");
});
// Middleware to share data across all requests
app.use((req, res, next) => {
res.inertia.share({
auth: {
user: req.user,
isAdmin: req.user?.role === "admin",
},
});
next();
});
app.post("/contact", async (req, res) => {
try {
await Contact.create(req.body);
req.flash("success", "Message sent successfully!");
res.inertia.redirect("/contact");
} catch (error) {
req.flash("error", "Failed to send message");
res.inertia.redirect("/contact");
}
});
Here’s an updated Contributing section with a clear note about discussing breaking changes before implementation:
We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.
Fork the repository
Create your feature branch:
git checkout -b feat/amazing-feature
Commit your changes with a descriptive message:
git commit -m "feat: add amazing feature"
Push to your branch:
git push origin feat/amazing-feature
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:
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
A lightweight Express.js middleware/adapter for Inertia.js that lets you build modern single-page applications with server-side rendering.
The npm package express-inertia receives a total of 3 weekly downloads. As such, express-inertia popularity was classified as not popular.
We found that express-inertia demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.