How to Use Inertia.js in a Laravel Project: A Simple Guide for Beginners
Single-page applications (SPAs) are getting popular these days as they are faster and give an experience like a mobile app. Traditionally, developers had to build a separate API backend and a frontend framework such as React or Vue to achieve this. However, Inertia.js provides a better solution.
Inertia.js acts as a bridge between Laravel and modern frontend frameworks, allowing developers to build SPA-like applications without creating a separate API. Instead of managing two different applications, you can use Laravel for routing and backend logic while rendering pages with React, Vue, or Svelte components.
In this blog we will cover about Inertia.js, including installation, configuration, creating pages, passing data between Laravel and React, and building a modern full-stack application.

What is Inertia.js?
Inertia.js is a library that is used for creating single-page applications (SPAs) where we use backends like Laravel, Rails, Django, Phoenix and for the frontend we use React, Vue, or Svelte without creating an API. All the routes are defined on the backend side, so for React we do not need React Router.
It works like a bridge between the backend and frontend, where all the routes and logic are defined on the backend side and frontend components are rendered dynamically using frameworks like React or Vue.
Why Should You Use Inertia.js?
Here are the awesome benefits of using Inertia.js:
✅ No API Needed
You don't have to create RESTful or GraphQL APIs. Inertia handles communication for you!
⚡ Super Fast
Pages load instantly because only the data changes, not the whole page.
🔒 One Authentication System
Use Laravel's built-in authentication. No need to duplicate login logic in React.
📱 SPA Feel
Your website feels like a mobile app with smooth page transitions.
What You Need Before Starting
Before we begin, make sure you have these installed on your computer:
- PHP 8.2+ (Laravel's language)
- Composer (PHP package manager - like a app store for PHP tools)
- Node.js & NPM (JavaScript package manager - for React/Vue)
- MySQL or any database (if you want to store your data)
Step 1: Create a New Laravel Project
First, let's create a fresh Laravel project.Naviaget to the location where you want to create your projet. Open your terminal (command prompt) and type this command:
composer create-project laravel/laravel inertia-appThis creates a folder called inertia-app with all Laravel files inside. Think of it like creating a new folder for your school project! 📁
Now, go into that folder:
cd inertia-appStep 2: Install Inertia.js in Laravel (Server-Side)
Now we need to add Inertia.js to our Laravel project. Run this command:
composer require inertiajs/inertia-laravelWhat does this do? This command installs the Inertia package for Laravel. It's like adding a special tool to your toolbox that helps Laravel talk to React or Vue.
Create the Root Template
Inertia needs one main HTML file that will load your React/Vue components. Let's create it! Go to resources/views folder and create a file called app.blade.php:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Inertia App</title>
<!-- Load our CSS and JavaScript files -->
@vite(['resources/css/app.css', 'resources/js/app.jsx'])
@inertiaHead
</head>
<body>
@inertia
</body>
</html>Think of this like: This is your website's main container. The @inertia part is like a magic box where all your React/Vue pages will appear!
Set Up Inertia Middleware
Middleware is like a security guard that checks things before they enter your website. Let's publish Inertia's middleware:
php artisan inertia:middlewareNow open bootstrap/app.php and add the middleware to the web group:
use App\Http\Middleware\HandleInertiaRequests;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
HandleInertiaRequests::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();Step 3: Install Inertia.js for React (Client-Side)
Now let's add Inertia to the React side! We'll use React in this example, but you can also use Vue or Svelte.
npm install @inertiajs/react react react-domWhat's happening? This installs React and the Inertia React adapter. It's like downloading apps on your phone—these are the tools React needs to work with Inertia!
Install Vite Plugin
Vite is a tool that bundles your JavaScript code. We need the Inertia plugin for it:
npm install @vitejs/plugin-reactConfigure Vite
Open vite.config.js and update it:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.jsx'],
refresh: true,
}),
react(),
],
});Step 4: Set Up Your React Application
Now let's create the main React file that will connect everything together. Go to resources/js and rename app.js to app.jsx, then replace its content with:
import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
createInertiaApp({
// This tells Inertia where to find your React page components
resolve: (name) =>
resolvePageComponent(
`./Pages/${name}.jsx`,
import.meta.glob('./Pages/**/*.jsx')
),
// This sets up your app
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />);
},
});Simple explanation: This code tells React: "Hey, when someone visits a page, look in the Pages folder for the matching component and show it!"
Step 5: Create Your First React Page Component
Let's create a simple homepage! Create a new folder: resources/js/Pages, then inside it, create Home.jsx:
import React from 'react';
import { Head, Link } from '@inertiajs/react';
export default function Home({ message, userName }) {
return (
<>
<Head title="Welcome to Inertia.js" />
<div className="min-h-screen bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
<div className="bg-white rounded-lg shadow-2xl p-8 max-w-md">
<h1 className="text-4xl font-bold text-gray-800 mb-4">
🎉 {message}
</h1>
<p className="text-xl text-gray-600 mb-6">
Hello, <strong>{userName}</strong>! Welcome to your first Inertia.js app!
</p>
<Link prefetch={false}
href="/about"
className="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition"
>
Go to About Page →
</Link>
</div>
</div>
</>
);
}What's special here? Notice how we receive message and userName as props? These come directly from Laravel! Also, the Link component makes navigation super smooth without page reloads.
Step 6: Create Laravel Routes and Controllers
Now let's tell Laravel: "When someone visits the homepage, show them the Home component." Open routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
// Home page route
Route::get('/', function () {
return Inertia::render('Home', [
'message' => 'Welcome to Inertia.js!',
'userName' => 'Student',
]);
});
// About page route
Route::get('/about', function () {
return Inertia::render('About', [
'title' => 'About Us',
'description' => 'This is a simple Inertia.js application built with Laravel and React!',
]);
});See what happened? Inertia::render('Home', [...]) tells Laravel: "Render the Home.jsx component and send this data to it." No API needed! 🚀
Create the About Page
Let's create resources/js/Pages/About.jsx:
import React from 'react';
import { Head, Link } from '@inertiajs/react';
export default function About({ title, description }) {
return (
<>
<Head title={title} />
<div className="min-h-screen bg-gradient-to-br from-green-500 to-teal-600 flex items-center justify-center">
<div className="bg-white rounded-lg shadow-2xl p-8 max-w-md">
<h1 className="text-3xl font-bold text-gray-800 mb-4">
{title}
</h1>
<p className="text-lg text-gray-600 mb-6">
{description}
</p>
<Link prefetch={false}
href="/"
className="bg-green-500 text-white px-6 py-3 rounded-lg hover:bg-green-600 transition"
>
← Back to Home
</Link>
</div>
</div>
</>
);
}Step 7: Run Your Application
Time to see your app in action! Open two terminal windows:
Terminal 1: Start Laravel Server
php artisan serveThis runs your Laravel backend at http://localhost:8000
Terminal 2: Start Vite Dev Server
npm run devThis watches your React files and automatically updates when you make changes. It's like having a helper that rebuilds your code instantly!
🎊 Congratulations!
Open your browser and visit http://localhost:8000. You should see your beautiful homepage! Try clicking the "About" link—notice how the page changes smoothly without reloading? That's Inertia.js magic! ✨
Step 8: Working with Forms in Inertia.js
Let's learn how to submit forms! Inertia makes this super easy. Create a new page resources/js/Pages/Contact.jsx:
import React from 'react';
import { Head, useForm } from '@inertiajs/react';
export default function Contact() {
// useForm hook manages form state for us
const { data, setData, post, processing, errors } = useForm({
name: '',
email: '',
message: '',
});
const handleSubmit = (e) => {
e.preventDefault();
// This sends data to Laravel without page reload!
post('/contact');
};
return (
<>
<Head title="Contact Us" />
<div className="min-h-screen bg-gray-100 py-12 px-4">
<div className="max-w-md mx-auto bg-white rounded-lg shadow-md p-8">
<h1 className="text-3xl font-bold mb-6">Contact Us</h1>
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label className="block text-gray-700 mb-2">Name:</label>
<input
type="text"
value={data.name}
onChange={e => setData('name', e.target.value)}
className="w-full border border-gray-300 rounded px-4 py-2"
/>
{errors.name && (
<p className="text-red-500 text-sm mt-1">{errors.name}</p>
)}
</div>
<div className="mb-4">
<label className="block text-gray-700 mb-2">Email:</label>
<input
type="email"
value={data.email}
onChange={e => setData('email', e.target.value)}
className="w-full border border-gray-300 rounded px-4 py-2"
/>
{errors.email && (
<p className="text-red-500 text-sm mt-1">{errors.email}</p>
)}
</div>
<div className="mb-6">
<label className="block text-gray-700 mb-2">Message:</label>
<textarea
value={data.message}
onChange={e => setData('message', e.target.value)}
className="w-full border border-gray-300 rounded px-4 py-2"
rows="4"
/>
{errors.message && (
<p className="text-red-500 text-sm mt-1">{errors.message}</p>
)}
</div>
<button
type="submit"
disabled={processing}
className="w-full bg-blue-500 text-white py-3 rounded hover:bg-blue-600 transition disabled:bg-gray-400"
>
{processing ? 'Sending...' : 'Send Message'}
</button>
</form>
</div>
</div>
</>
);
}Now add the route in routes/web.php:
Route::get('/contact', function () {
return Inertia::render('Contact');
});
Route::post('/contact', function (Request $request) {
// Validate the form data
$validated = $request->validate([
'name' => 'required|min:3',
'email' => 'required|email',
'message' => 'required|min:10',
]);
// In real app, save to database or send email
// For now, just redirect back with success message
return redirect()->back()->with('success', 'Message sent successfully!');
});What's cool here? The useForm hook handles everything: form state, submission, loading states, and even displays Laravel's validation errors automatically!
Step 9: Share Data Across All Pages
Sometimes you want to show the same data on every page (like the logged-in user's name). Open app/Http/Middleware/HandleInertiaRequests.php:
public function share(Request $request): array
{
return [
...parent::share($request),
// This data is available on ALL pages!
'auth' => [
'user' => $request->user() ? [
'name' => $request->user()->name,
'email' => $request->user()->email,
] : null,
],
// Flash messages (success/error notifications)
'flash' => [
'success' => $request->session()->get('success'),
'error' => $request->session()->get('error'),
],
];
}Now in ANY React component, you can access this shared data using the usePage hook:
import { usePage } from '@inertiajs/react';
export default function MyComponent() {
const { auth, flash } = usePage().props;
return (
<div>
{auth.user && <p>Welcome, {auth.user.name}!</p>}
{flash.success && <div className="alert">{flash.success}</div>}
</div>
);
}Step 10: Create a Reusable Layout
Most websites have a common header and footer. Let's create a layout component! Create resources/js/Layouts/MainLayout.jsx:
import React from 'react';
import { Link, usePage } from '@inertiajs/react';
export default function MainLayout({ children }) {
const { auth } = usePage().props;
return (
<div className="min-h-screen bg-gray-50">
{/* Header/Navigation */}
<nav className="bg-white shadow-md">
<div className="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
<Link prefetch={false}href="/" className="text-2xl font-bold text-blue-600">
MyApp
</Link>
<div className="space-x-4">
<Link prefetch={false}href="/" className="text-gray-700 hover:text-blue-600">
Home
</Link>
<Link prefetch={false}href="/about" className="text-gray-700 hover:text-blue-600">
About
</Link>
<Link prefetch={false}href="/contact" className="text-gray-700 hover:text-blue-600">
Contact
</Link>
</div>
<div>
{auth.user ? (
<span className="text-gray-700">
Hello, {auth.user.name}
</span>
) : (
<Link prefetch={false}href="/login" className="bg-blue-500 text-white px-4 py-2 rounded">
Login
</Link>
)}
</div>
</div>
</nav>
{/* Main Content */}
<main className="max-w-7xl mx-auto py-8 px-4">
{children}
</main>
{/* Footer */}
<footer className="bg-gray-800 text-white py-6 mt-12">
<div className="max-w-7xl mx-auto px-4 text-center">
<p>© 2025 MyApp. Built with Laravel & Inertia.js</p>
</div>
</footer>
</div>
);
}Now wrap your pages with this layout:
import MainLayout from '@/Layouts/MainLayout';
export default function Home({ message, userName }) {
return (
<MainLayout>
<div className="bg-white rounded-lg shadow-md p-8">
<h1 className="text-4xl font-bold">{message}</h1>
<p>Hello, {userName}!</p>
</div>
</MainLayout>
);
}Advanced Features (Optional)
1. Prefetching Links
Make your app even faster by loading page data before the user clicks:
<Link prefetch={false}href="/about" prefetch="hover">
About Us
</Link>2. Partial Reloads
Only reload specific parts of your data:
import { router } from '@inertiajs/react';
// Only reload 'posts' data, keep everything else the same
router.reload({ only: ['posts'] });3. Progress Indicator
Show a loading bar when navigating between pages. Add this to resources/js/app.jsx:
import { router } from '@inertiajs/react';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
router.on('start', () => NProgress.start());
router.on('finish', () => NProgress.done());Don't forget to install nprogress:
npm install nprogressCommon Problems and Solutions
❌ Problem: "Vite manifest not found"
Solution: Make sure you ran npm run dev in a separate terminal. Both Laravel server AND Vite must be running during development.
❌ Problem: Page not found
Solution: Check that your component name matches the route. If your route says Inertia::render('Home'), your file must be Pages/Home.jsx.
❌ Problem: Data not showing up
Solution: Make sure you're passing data from Laravel correctly and receiving it as props in React. Check the browser console for errors.
❌ Problem: Forms not submitting
Solution: Check that your route matches (GET for displaying form, POST for submitting). Also verify you're using post('/route') in your form, not get().
Best Practices for Using Inertia.js
✅ DO:
- • Use shared data for common information
- • Create reusable layout components
- • Validate forms on the server (Laravel)
- • Use Inertia's form helper for easy submission
- • Keep components organized in folders
❌ DON'T:
- • Don't create separate APIs for Inertia
- • Don't use window.location for navigation
- • Don't mix Inertia routes with API routes
- • Don't forget CSRF protection for forms
- • Don't skip validation on the backend
Conclusion: You Did It! 🎉
Congratulations! You've just learned how to build modern web applications using Inertia.js with Laravel and React. Let's recap what you've learned:
- ✅ What Inertia.js is and why it's awesome
- ✅ How to install and configure Inertia.js in Laravel
- ✅ How to create React page components
- ✅ How to pass data from Laravel to React
- ✅ How to handle forms and validation
- ✅ How to share data across all pages
- ✅ How to create reusable layouts
Remember: Inertia.js is like a bridge that connects your Laravel backend with your React frontend. You don't need to build APIs, and you can use Laravel for everything you're already familiar with!
🚀 Next Steps:
- • Try building a simple blog or todo app
- • Explore Inertia.js official documentation at inertiajs.com
- • Learn about authentication with Laravel Breeze + Inertia
- • Experiment with Vue or Svelte instead of React
- • Join the Inertia.js community on Discord
Keep practicing, keep building, and most importantly—have fun! If you found this guide helpful, share it with your friends who are learning web development. Happy coding! 💻✨
Frequently Asked Questions
Helpful Resources
📚 Inertia.js Documentation
Official docs with detailed guides and examples
📖 Laravel Documentation
Complete Laravel framework documentation
⚛️ React Documentation
Learn React fundamentals and advanced concepts
💻 GitHub Repository
Explore Inertia.js source code and examples
Related Articles You May Like
- Top Coding Tips: Clean Code, Boost Productivity, Master Practices
Best Practices • Intermediate
- The Ultimate Guide to Code Debugging: Techniques, Tools & Tips
Debugging • Intermediate
- GitHub Actions: Complete CI/CD Automation Guide
Git • Intermediate
- Laravel API Example: Creating Efficient Endpoints
Laravel • Advanced
- Laravel Tips and Tricks: Hidden Features Most Developers Miss
Laravel • Advanced
- How to Debug Laravel SQL Queries in API Requests: A Developer's Guide
Laravel • Intermediate