Building modern web applications often requires combining a powerful backend framework with a dynamic frontend library. Laravel 12 and React make an excellent pair, offering robust server-side capabilities alongside reactive user interfaces. While Laravel provides starter kits like Breeze and Jetstream, sometimes you need more control over your setup.
In this comprehensive guide, I'll walk you through setting up React with Laravel 12 from scratch, giving you complete control over your application architecture.
Why Choose React with Laravel 12?
Before diving into the setup, let's understand why this combination works so well:
- Laravel 12 provides a robust API backend with excellent developer experience
- React offers component-based UI development with excellent performance
- Vite (Laravel's default build tool) provides fast hot module replacement
- Complete separation of frontend and backend concerns
- Flexibility to customize your stack exactly as needed
Prerequisites
Make sure you have the following installed:
- PHP 8.2 or higher
- Composer
- Node.js 18 or higher
- npm or yarn
Step-by-Step Setup
Step 1: Create a Fresh Laravel 12 Project
Start by creating a new Laravel project:
composer create-project laravel/laravel your-app-name cd your-app-name
This gives us a clean Laravel installation without any frontend scaffolding.
Step 2: Install Node.js Dependencies
Install the necessary packages for React and build tools:
npm install react react-dom @vitejs/plugin-react npm install -D @types/react @types/react-dom
These packages provide:
- react and react-dom: Core React libraries
- @vitejs/plugin-react: Vite plugin for React support
- @types/*: TypeScript definitions for better IDE support
Step 3: Configure Vite for React
Update your vite.config.js file to support React:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react-swc';
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
react(),
laravel({
input: ['resources/css/app.css', 'resources/js/app.jsx'],
refresh: true,
}),
tailwindcss(),
],
});
Key changes:
- Added React plugin
- Changed entry point from app.js to app.jsx
- Enabled hot module replacement with refresh: true
Step 4: Set Up React Entry Point
Rename resources/js/app.js to resources/js/app.jsx and replace its contents:
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './components/App';
import '../css/app.css';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);
This file:
- Imports React and the new createRoot API
- Imports our main App component
- Renders the React app into the DOM element with id "app"
Step 5: Create Your First React Component
Create a directory resources/js/components/ and add App.jsx:
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-3xl font-bold text-gray-800 mb-4">
React + Laravel 12
</h1>
<div className="space-y-4">
<p className="text-gray-600">Count: {count}</p>
<div className="space-x-2">
<button
onClick={() => setCount(count + 1)}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Increment
</button>
<button
onClick={() => setCount(count - 1)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Decrement
</button>
</div>
</div>
</div>
</div>
);
}
export default App;
This creates a simple counter component to verify everything works correctly.
Step 6: Update Your Blade Template
Create or update resources/views/app.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React + Laravel</title>
@viteReactRefresh
@vite(['resources/css/app.css', 'resources/js/app.jsx'])
</head>
<body>
<div id="app"></div>
</body>
</html>
Important points:
- The @vite directive loads our compiled assets
- The div with id "app" is where React will mount
- We're loading both CSS and JSX files
Step 7: Set Up Routes
Update routes/web.php to handle client-side routing:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/{any}', function () {
return view('app');
})->where('any', '.*');
This catch-all route ensures that all requests serve your React application, enabling client-side routing.
Step 9: Build and Run
Start both development servers:
# Terminal 1: Laravel development server php artisan serve # Terminal 2: Vite development server npm run dev
Visit http://localhost:8000 to see your React + Laravel application in action!
Setting Up API Integration
To connect your React frontend with Laravel's API, first create API routes in routes/api.php:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/test', function () {
return response()->json(['message' => 'Hello from Laravel API!']);
});
Then in your React components, you can fetch data:
useEffect(() => {
fetch('/api/test')
.then(response => response.json())
.then(data => console.log(data));
}, []);
Final Project Structure
Your project should now look like this:
your-app-name/ ├── resources/ │ ├── js/ │ │ ├── components/ │ │ │ └── App.jsx │ │ └── app.jsx │ ├── css/ │ │ └── app.css │ └── views/ │ └── app.blade.php ├── routes/ │ ├── web.php │ └── api.php ├── vite.config.js └── package.json
Next Steps
Now that you have a solid foundation, you can:
- Add React Router for client-side navigation
- Set up state management with Redux or Zustand
- Create API endpoints in Laravel for your React components
- Add authentication using Laravel Sanctum
- Implement real-time features with Laravel Broadcasting
Conclusion
Setting up React with Laravel 12 manually gives you complete control over your application architecture. This approach is perfect when you need:
- Custom build configurations
- Specific package versions
- Complete separation of concerns
- Full understanding of your stack
While starter kits are convenient, this manual setup ensures you understand every piece of your application and can customize it exactly to your needs.
The combination of Laravel's robust backend capabilities with React's dynamic frontend creates a powerful foundation for modern web applications. With hot module replacement from Vite, you'll have an excellent developer experience that scales with your project's complexity.
Happy coding! 🚀
Have questions about this setup? Feel free to reach out or check the Laravel and React documentation for more advanced configurations.