What Is Laravel 12's React Starter Kit and Why Use It?
The React Starter Kit is Laravel's official solution for developers who want a React frontend tightly integrated with Laravel's backend authentication system.The React Starter Kit, in particular, is designed for developers who prefer React for their frontend while leveraging Laravel's robust backend capabilities. It integrates Inertia.js version 2, which allows you to build single-page applications (SPAs) without the complexity of a separate API layer. Inertia bridges the gap between server-side rendering and client-side reactivity, enabling Laravel controllers to render React components directly. Additionally, the kit comes pre-configured with TypeScript for type safety, Tailwind CSS for styling, and shadcn/ui — a popular component library that offers customizable, accessible UI elements.
Before this starter kit existed, developers had to manually wire up React with Laravel, configure CORS for API requests, manage CSRF tokens, and build authentication screens from scratch. The React Starter Kit eliminates all of that boilerplate, giving you a production-ready foundation in minutes. If you're evaluating different authentication strategies, check out our guide on Best Authentication Options in Laravel 12 Using WorkOS AuthKit for a comparison.

Table Of Content
1 Prerequisites
- PHP ≥ 8.2 — Laravel 12 requires PHP 8.2 or higher. Run php -v to check your version.
- Composer — PHP's dependency manager. Install it from getcomposer.org.
- Node.js 18+ — Required for compiling frontend assets with Vite. Check with node -v.
- npm or pnpm — Comes bundled with Node.js. Either package manager works.
- MySQL / PostgreSQL / SQLite — Any Laravel-supported database. We'll use MySQL in this tutorial.
- Basic knowledge of Laravel and React — You should understand controllers, routes, and JSX components.
If you're new to Laravel 12, we recommend reading our Laravel 12 Routing and Middleware Guide first to get familiar with the framework's core concepts.
2 Introduction
This tutorial will guide you through the full setup process, from installation to configuring authentication with Laravel Fortify. By the end, you'll have a fully functional Laravel 12 application with a React frontend and secure user authentication.
We'll include sample code snippets with detailed explanations to help you understand each step. Whether you're a beginner transitioning from older Laravel versions or an experienced developer exploring the new features, this guide aims to get you up and running quickly.
What you'll build: A Laravel 12 application with a React-powered frontend that includes user registration, login, email verification, two-factor authentication (2FA), password reset, and a protected dashboard — all using Laravel Fortify for backend logic and Inertia.js to connect React components to Laravel controllers without a separate API.
Why this approach matters: Traditional SPAs require a separate API backend, JWT or token management, and CORS configuration. With Inertia.js v2 and the React Starter Kit, you get the SPA experience while keeping Laravel's server-side routing, middleware, and session-based authentication intact. This means fewer moving parts, simpler deployment, and better security out of the box.
3 Installing Laravel 12 and the React Starter Kit
The installation process is straightforward thanks to the Laravel CLI installer. It will scaffold both the backend (Laravel) and frontend (React + Inertia + TypeScript + Tailwind) in one step. Let's walk through it.
3.1 Install Laravel Project
laravel new my-laravel-react-app
During the installation, the CLI will prompt you to select a starter kit. Choose the "React" option. This command scaffolds the entire application, including the backend Laravel structure and the frontend React setup with Inertia.
Once installed, navigate into the project directory:
cd my-laravel-react-app
Next, install the Node (frontend) dependencies:
npm install
This pulls in React, Inertia, TypeScript, Tailwind, shadcn/ui, and other packages defined in package.json. After installation,
build the assets:
npm run build
In a separate terminal, run php artisan serve. Your app should now be accessible at http://localhost:8000. The default setup includes a dashboard page, demonstrating Inertia's page rendering. 3.2 Configure Your Database (.env)
Open the .env file in your project root and configure the database connection. Laravel supports MySQL, PostgreSQL, SQLite, and SQL Server. For this tutorial, we'll use MySQL:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_12_react_starter
DB_USERNAME=root
DB_PASSWORD=
Replace DB_DATABASE, DB_USERNAME, and DB_PASSWORD with your actual MySQL credentials. Make sure the database exists before running migrations — you can create it manually via phpMyAdmin or the MySQL CLI:
mysql -u root -p -e "CREATE DATABASE laravel_12_react_starter;"
Tip: If you prefer a simpler setup for local development, you can use SQLite instead. Just set DB_CONNECTION=sqlite and remove the other DB_ variables — Laravel will automatically create a database/database.sqlite file.
4 Configuring Authentication with Laravel Fortify
Authentication is a core feature in most web apps, and Laravel 12's React Starter Kit uses Laravel Fortify for backend auth logic, seamlessly integrated with React frontend pages.
Fortify is a headless authentication backend — it provides actions for registration, login, password reset, email verification, and two-factor authentication, without prescribing any UI. The starter kit builds React components on top of these actions using Inertia to bridge the frontend and backend.
To enable authentication, it's already partially set up, but let's customize it. First, ensure your database is migrated:
php artisan migrate
This creates the users, password_reset_tokens, sessions, and other tables needed for authentication.
Next, edit config/fortify.php to enable the features you need:
<?php
use Laravel\Fortify\Features;
return [
'guard' => 'web',
'username' => 'email',
'email' => 'email',
'home' => '/dashboard',
'prefix' => '',
'domain' => null,
'middleware' => ['web'],
'limiters' => [
'login' => 'login',
'two-factor' => 'two-factor',
],
'paths' => [
'home' => 'dashboard',
],
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication([
'confirm' => true,
'confirmPassword' => true,
]),
],
];
Here's what each feature does:
- Features::registration() — Enables the /register route for new user sign-ups.
- Features::resetPasswords() — Adds the forgot/reset password flow via email.
- Features::emailVerification() — Sends a verification email after registration (requires MustVerifyEmail on the User model).
- Features::updateProfileInformation() — Allows users to update their name and email from a settings page.
- Features::updatePasswords() — Lets users change their password from a settings page.
- Features::twoFactorAuthentication() — Adds 2FA support using TOTP apps like Google Authenticator or Authy. Setting confirm and confirmPassword to true requires users to confirm their password before enabling 2FA.
The limiters array configures rate limiting for login and 2FA attempts to protect against brute force attacks. You can customize these in app/Providers/FortifyServiceProvider.php.
5 Enable Email Verification if Needed
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail; // Add this for email verification
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable implements MustVerifyEmail // Implement MustVerifyEmail
{
use HasApiTokens, HasFactory, Notifiable, TwoFactorAuthenticatable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
6 Fortify Files
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\CreatesNewUsers;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
public function create(array $input): User
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
])->validate();
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
}
app/Actions/Fortify/PasswordValidationRules.php (Password Rules)
<?php
namespace App\Actions\Fortify;
use Laravel\Fortify\Rules\Password;
trait PasswordValidationRules
{
protected function passwordRules()
{
return ['required', 'string', new Password, 'confirmed'];
}
}
7 Frontend React Files (resources/js/)
The React Starter Kit organizes frontend code inside resources/js/. Here are the key files you'll work with:
resources/js/app.tsx (Entry Point)This is the main entry point that boots the Inertia app. It dynamically resolves page components from the pages/ directory:
import { createInertiaApp } from '@inertiajs/react';
import { createRoot } from 'react-dom/client';
createInertiaApp({
resolve: name => {
const pages = import.meta.glob('./pages/**/*.tsx', { eager: true });
return pages[`./pages/${name}.tsx`];
},
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />);
},
});
The resolve function uses Vite's import.meta.glob to automatically discover all .tsx files in the pages directory. When Laravel returns an Inertia response like Inertia::render('Dashboard'), this resolver loads pages/Dashboard.tsx.
resources/js/pages/Dashboard.tsx (Protected Dashboard Page)This is the page users see after logging in. It's a simple React component rendered by Inertia when the /dashboard route is visited:
import { Head } from '@inertiajs/react';
export default function Dashboard() {
return (
<>
<Head title="Dashboard" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 text-gray-900">
You're logged in!
</div>
</div>
</div>
</div>
</>
);
}
The <Head> component from Inertia sets the page's <title> tag. This component is protected by the auth middleware on the server side, so unauthenticated users will be redirected to /login.
resources/js/pages/Auth/Login.tsx (Login Form)The login page uses shadcn/ui components and Inertia's useForm hook for form state management and submission:
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import { useForm, router } from '@inertiajs/react';
import { FormEventHandler } from 'react';
import AuthLayout from '@/layouts/auth-layout';
export default function Login({ status }: { status?: string }) {
const { data, setData, post, processing, errors, reset } = useForm({
email: '',
password: '',
remember: false,
});
const submit: FormEventHandler = (e) => {
e.preventDefault();
post(router.resolve('/login'), { onFinish: () => reset('password') });
};
return (
<AuthLayout title="Login">
{status && <div className="mb-4 text-green-600">{status}</div>}
<form onSubmit={submit} className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
value={data.email}
onChange={(e) => setData('email', e.target.value)}
error={errors.email}
/>
</div>
<div>
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
value={data.password}
onChange={(e) => setData('password', e.target.value)}
error={errors.password}
/>
</div>
<div className="flex items-center">
<Checkbox
id="remember"
checked={data.remember}
onCheckedChange={(checked) => setData('remember', !!checked)}
/>
<Label htmlFor="remember" className="ml-2">Remember me</Label>
</div>
<Button type="submit" disabled={processing}>Log in</Button>
</form>
</AuthLayout>
);
}
Key points: The useForm hook manages form state, validation errors, and the submission lifecycle. The processing flag disables the submit button during the request to prevent double submissions. Errors returned from Fortify's validation are automatically available via the errors object.
resources/js/pages/Auth/Register.tsx (Registration Form)The registration form follows the same pattern as the login form, with additional fields for name and password confirmation:
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useForm, router } from '@inertiajs/react';
import { FormEventHandler } from 'react';
import AuthLayout from '@/layouts/auth-layout';
export default function Register() {
const { data, setData, post, processing, errors } = useForm({
name: '',
email: '',
password: '',
password_confirmation: '',
});
const submit: FormEventHandler = (e) => {
e.preventDefault();
post(router.resolve('/register'));
};
return (
<AuthLayout title="Register">
<form onSubmit={submit} className="space-y-4">
<div>
<Label htmlFor="name">Name</Label>
<Input
id="name"
type="text"
value={data.name}
onChange={(e) => setData('name', e.target.value)}
error={errors.name}
/>
</div>
<div>
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
value={data.email}
onChange={(e) => setData('email', e.target.value)}
error={errors.email}
/>
</div>
<div>
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
value={data.password}
onChange={(e) => setData('password', e.target.value)}
error={errors.password}
/>
</div>
<div>
<Label htmlFor="password_confirmation">Confirm Password</Label>
<Input
id="password_confirmation"
type="password"
value={data.password_confirmation}
onChange={(e) => setData('password_confirmation', e.target.value)}
error={errors.password_confirmation}
/>
</div>
<Button type="submit" disabled={processing}>Register</Button>
</form>
</AuthLayout>
);
}
When the form is submitted, Fortify's CreateNewUser action (which we configured in Section 6) handles the validation and user creation. If validation fails, Inertia automatically redirects back with errors populated in the errors object.
8 Define Routes
The React Starter Kit pre-configures most routes for you, but understanding them is essential. In routes/web.php, the authenticated routes use Inertia to render React pages:
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->name('dashboard');
});
The Inertia::render('Dashboard') call tells Inertia to load the resources/js/pages/Dashboard.tsx component. Any data you pass as the second argument becomes available as props in the React component.
Enable Email Verification: If you implemented MustVerifyEmail on the User model (Section 5), add the verified middleware to your protected routes:
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->name('dashboard');
// Add more protected routes here
});
Fortify automatically registers routes for /login, /register, /forgot-password, /reset-password, and /two-factor-challenge — you don't need to define these manually. For a deeper understanding of how routing and middleware work in Laravel 12, read our Laravel 12 Routing and Middleware Complete Guide.
9 Folder Structure
Here is the correct folder structure for the key files in a Laravel 12 React Starter Kit project:
Important notes on the structure: The app.tsx entry point lives at resources/js/app.tsx (not inside the pages folder). The Dashboard.tsx component is at resources/js/pages/Dashboard.tsx, while auth-related pages (Login, Register) are organized under resources/js/pages/Auth/. The fortify.php config file is in the config/ directory, not in routes/.
10 Test the Application
After completing the setup, it's time to test the full authentication flow. Start by running both servers in separate terminal windows:
# Terminal 1: Start the Laravel backend
php artisan serve
# Terminal 2: Start the Vite dev server for hot module replacement
npm run dev
Now test the authentication flow step by step:
- Registration: Visit http://localhost:8000/register and create a new user account. Verify that validation errors appear if you submit incomplete data.
- Email Verification: If you enabled MustVerifyEmail, check your mail setup. For local development, use Mailtrap or set MAIL_MAILER=log in .env to view emails in storage/logs/laravel.log.
- Login: Visit /login, enter your credentials, and confirm you're redirected to /dashboard.
- Protected Routes: Try accessing /dashboard while logged out — you should be redirected to /login.
Common issues and fixes:
- Blank page or 500 error: Check storage/logs/laravel.log for details. Run php artisan config:clear and php artisan cache:clear.
- Vite not loading assets: Make sure npm run dev is running. Check that your APP_URL in .env matches the URL you're accessing.
- TypeScript errors in console: The kit's types/ folder helps with autocompletion. Run npx tsc --noEmit to check for type issues.
- CSRF token mismatch: Ensure your session driver is configured properly in .env (default is file).
For production deployment, build the assets with npm run build and configure your web server (Nginx/Apache) to serve the Laravel application. You can also explore our Laravel 12 Performance Optimization Tips to ensure your app runs efficiently in production.
11 Conclusion
Laravel 12's React Starter Kit simplifies full-stack development by combining Laravel's backend power with React's flexible UI capabilities. With built-in authentication via Fortify, TypeScript for type safety, and shadcn/ui for polished components, you can build secure and scalable applications faster than ever.
In this guide, we covered the complete setup — from project installation and database configuration to Fortify authentication features (registration, login, 2FA, email verification), React frontend pages, and routing. This foundation gives you everything you need to start building real features immediately.
Next steps to explore:
- Build a REST API alongside your Inertia frontend — see our How to Build a REST API in Laravel 12 guide.
- Learn advanced Eloquent patterns for your models — check out Laravel 12 Eloquent Tips and Tricks.
- Set up background jobs for email sending and notifications — follow our Laravel 12 Queue and Jobs Tutorial.
- Debug common issues faster — bookmark our Common Laravel 12 Errors and How to Fix Them guide.
Experiment with the starter kit, customize it to fit your project, and deploy with confidence. Happy coding!
Related Laravel 12 Tutorials
Now that you have a working Laravel 12 React app with authentication, here are some related tutorials to help you build on this foundation:
- Best Authentication Options in Laravel 12 Using WorkOS AuthKit — Compare Fortify with WorkOS AuthKit for enterprise-grade authentication including SSO and social logins.
- How to Build a REST API in Laravel 12 — Learn to create RESTful endpoints alongside your Inertia frontend for mobile apps or third-party integrations.
- Laravel 12 Routing and Middleware Complete Guide — Deep dive into route groups, middleware, and request handling in Laravel 12.
- Laravel 12 Eloquent Tips and Tricks for Beginners — Master the ORM with practical tips for querying, relationships, and performance.
- Laravel 12 Queue and Jobs Tutorial: Background Processing — Offload email sending, notifications, and heavy tasks to background queues.
- Laravel 12 Performance Optimization Tips — 12 proven techniques to make your Laravel app load 50-80% faster.
- Common Laravel 12 Errors and How to Fix Them — Quick solutions for the most frequent Laravel 12 development issues.
Written by Revathi M
PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel
Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.
Frequently Asked Questions
The React Starter Kit is Laravel 12's official pre-configured template that provides a React frontend integrated with Laravel's backend using Inertia.js v2. It comes with TypeScript, Tailwind CSS, shadcn/ui components, and authentication via Fortify — all set up and ready to use out of the box.
Run laravel new app-name in your terminal and select "React" when prompted to choose a starter kit. Then run npm install and npm run build to set up the frontend dependencies. The CLI scaffolds both the Laravel backend and React frontend in one step.
Yes, authentication is built-in via Laravel Fortify. It supports user registration, login, password reset, email verification, profile updates, and two-factor authentication (2FA) using TOTP apps like Google Authenticator. All of these features can be toggled on or off in config/fortify.php.
The React Starter Kit uses shadcn/ui for pre-built, accessible UI components (buttons, inputs, checkboxes, dialogs, etc.) styled with Tailwind CSS. shadcn/ui components are copied into your project so you can fully customize them without being locked into a third-party library.
Yes, Inertia.js v2 supports server-side rendering. Run npm run build:ssr to build the SSR bundle, then start the Inertia SSR server. This improves initial page load performance and SEO by rendering React components on the server before sending them to the browser.
