This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

Laravel React Guide: How to Build & Deploy a Modern SPA

Updated on January 26, 2026

14 Min Read
laravel react

Key Takeaways

  • Inertia.js connects Laravel and React seamlessly, removing the need for separate APIs.
  • React enables instant page transitions and dynamic updates without browser reloads.
  • Laravel Breeze automates the configuration of Vite, React, and authentication scaffolding.
  • Production deployment requires server-side asset compilation for the React frontend to function.

Web users today expect applications to be instant and interactive, behaving more like mobile apps than traditional websites. While Laravel is a robust backend framework, its standard server-side rendering often relies on full page reloads, which can feel clunky.

The solution is React JS. By handling the interface directly in the browser, React eliminates those constant page reloads, making every click and transition feel instant.

Merging these two technologies allows you to maintain the robust security and structure of a Laravel backend while delivering the snappy user experience of a Single Page Application (SPA).

In this blog, I’ll show you how to integrate React JS in Laravel. We will start by creating a new project on a local setup, configuring the React frontend, and finally deploying it to a production-ready Cloudways server.

Why Integrate React JS with Laravel?

Ten years ago, it was normal for a web page to refresh completely every time a user clicked a button like “Save.” The screen would flash, the page would reload, and users would wait for the response. At the time, this behavior was accepted as part of using the web.

Today, user expectations are very different. Modern users expect fast feedback, smooth transitions, and interfaces that respond instantly to their actions. Web applications are now expected to feel closer to mobile apps than traditional websites.

Integrating React with Laravel helps achieve this experience in a practical way. Laravel handles backend responsibilities such as authentication, authorization, database operations, validation, and business logic. React focuses on the frontend, updating the user interface dynamically without forcing the browser to reload entire pages.

1. Single Page Application Experience

In a traditional server-rendered application, every navigation or form submission sends a request to the server and returns a full HTML page. While this approach is reliable, it often feels slow and interruptive.

When React is integrated with Laravel, commonly using tools like Inertia.js, the application loads once. After that initial load, navigation happens by updating components instead of reloading pages. This results in faster transitions and a smoother overall experience for the user.

2. Component Reusability

As applications grow, interactive features such as file uploads, live validation, modals, and dashboards can become difficult to manage when built directly inside PHP templates. Logic often becomes scattered and hard to maintain.

React encourages building these features as self-contained components. A file uploader, for example, can be built once and reused across the application. Each component manages its own state and behavior, which keeps the codebase organized and easier to extend over time.

3. Access to the JavaScript Package Ecosystem

React is part of the broader JavaScript ecosystem, which is supported by a package manager called NPM. NPM is a repository of reusable JavaScript packages that solve common development problems.

These packages include tools for data tables, charts, form handling, animations, and many other interface-related features. Most of them are open source, actively maintained, and widely used in production environments. By using React, developers can rely on these existing solutions instead of building everything from scratch.

4. Preparation for Mobile Development

Using React on the frontend also makes future mobile development more straightforward. React Native allows developers to reuse much of their JavaScript logic to build native mobile applications for iOS and Android.

The same Laravel backend can serve both the web application and mobile apps through APIs. This approach reduces duplication of effort and makes it easier to maintain consistent behavior across platforms.

For teams building modern applications, the React and Laravel combination provides a balance between strong backend structure and a responsive, user-friendly frontend.

Stop Configuring Servers. Start Coding.

Don’t waste hours wrestling with Nginx, PHP versions, and MySQL configs. Launch a pre-optimized Laravel server in 1 click so you can focus on building your app.

How to Integrate React JS in Laravel

In this tutorial, we will focus on the most efficient way to combine these technologies: the Inertia.js stack. This approach allows you to build a modern, single-page application using classic Laravel routing and controllers, but with React as your frontend view layer.

What We Will Build: To show you this integration, we will build a Reactive Task List. By the end of this guide, you will have a functional app where you can view tasks fetched from your Laravel database and add new ones instantly, all without ever reloading the browser page.

Source Code: If you get stuck or want to see the final result, you can view the complete project on my GitHub Repository.

Prerequisites for this Tutorial

Before we dive into the code, ensure your development environment is ready. You will need the following tools installed to run a modern Laravel 11 application:

  • PHP 8.2 or higher: Laravel 11 requires the latest PHP features for optimal performance.
  • Composer: The standard dependency manager for PHP, used to install the framework.
  • Node.js & NPM (Critical): You must have Node.js installed to build the frontend. Download the Windows Installer (.msi) here. After installing Node.js, you must close and restart your Command Prompt for the changes to take effect.
  • A Database: MySQL (or MariaDB) is the standard choice, though you can use SQLite for quick local testing.
Note: If you are following this guide on a Cloudways server, you can skip the environment setup. Your server comes pre-configured with the latest versions of PHP, Composer, and Node.js, so you are ready to start coding immediately.

Step 1: Install the Laravel Project

  • First, we will create a fresh Laravel installation.
  • Open your Command Prompt (CMD), navigate to the folder where you keep your projects (e.g., cd Desktop or cd xampp/htdocs), and run the following command:
composer create-project laravel/laravel react-task-app
  • This command downloads the latest version of Laravel (currently version 11) and creates a folder named react-task-app.
  • Once the installation is complete, navigate into your project folder:
cd react-task-app

composer create project and navigate into your project folder

Step 2: Configure the Database

  • Since we are building a Task List, we need a database to store the tasks.
  • Open XAMPP Control Panel and ensure Apache and MySQL are running.

apache and mysql running in phpmyadmin

  • Go to phpMyAdmin in your browser (usually http://localhost/phpmyadmin).
  • Click New in the sidebar.
  • Name your database react_task_app.
  • In the dropdown next to the name (Collation), select utf8mb4_unicode_ci.
  • Click Create.

create database in phpmyadmin

  • Now, connect this database to your Laravel project. Open the project folder in your code editor (like VS Code, notepad), find the .env file, and update the database settings:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=react_task_app
DB_USERNAME=root
DB_PASSWORD=
Note: By default in XAMPP, the username is root and the password is empty. If you set a password, add it here.

Here is a screenshot of my updated .env file:

connect laravel app with phpmyadmin database by editing env file

Step 3: Install React via Laravel Breeze

  • This is the most critical step. In the past, developers had to manually install React and configure Webpack. Today, we use Laravel Breeze, which automatically sets up React, Vite, and Inertia.js for us.

Setting up Node.js

To build the React assets, you need Node.js installed.

  • Recommended: If you used the standard Windows Installer (.msi), your system is already configured. You can skip ahead to the Composer command.
  • My Setup (Portable/Zip): For this tutorial, I used the Standalone Binary (.zip) version. Because of this, I need to explicitly tell the terminal where Node is located before running commands. I did this by running:
set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.13.0-win-x64\node-v24.13.0-win-x64

set path for node.js

  • Now that Node is ready, run the following command in your terminal to install the Breeze package:
composer require laravel/breeze --dev

Install React via Laravel Breeze

  • Next, run the installation command and select the React stack:
php artisan breeze:install react

run the installation command and select the React stack

  • After the scaffolding is installed, we need to ensure the frontend assets are compiled. Run the following commands to install the JavaScript libraries and build the React files:
npm install
npm run build

npm install

  • This ensures that even if you have a custom environment setup, all necessary React dependencies are correctly installed and built.

Step 4: Run the Migrations

  • Now that we have connected our database in the .env file, we need to create the tables (like the Users table) so the login system works.
  • If you skip this step, you will encounter a “Table not found” error when trying to view the app.
  • Run the following command:
php artisan migrate

php artisan migrate command

Step 5: Verify the Installation

  • At this point, your installation is complete. Let’s verify it works before we start coding the Task List.
  • Start the Laravel server:
php artisan serve
  • Open your browser and visit: http://127.0.0.1:8000
  • You should see the Laravel homepage. Look at the top right corner: if you see “Log in” and “Register” links, you have successfully integrated React with Laravel.

Laravel homepage

Building the Reactive Task List

Now that our environment is ready, we will build a simple “Task List” application. This will demonstrate how to pass data from Laravel to React and how to send data back from Laravel without page reloads.

Step 1: Create the Model and Migration

  • First, we need a database table to store our tasks. In Laravel, we use a “Model” to interact with the database.
  • Run this command in your terminal:
php artisan make:model Task -m
  • (The -m flag tells Laravel to also create a “migration” file for the database table).
  • Now, open the newly created migration file located at database/migrations/xxxx_xx_xx_create_tasks_table.php. Update the up() method to include a column for the task title:
public function up(): void
{
    Schema::create('tasks', function (Blueprint $table) {
        $table->id();
        $table->string('title'); // Add this line
        $table->boolean('is_completed')->default(false); // Optional: to track completion
        $table->timestamps();
    });
}
  • Next, open the Model file at app/Models/Task.php.
  • Replace the entire file content with the code below. This ensures the necessary “HasFactory” trait is imported correctly:
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'is_completed'];
}
  • Finally, run the migration to create the table in your database:
php artisan migrate

Step 2: Create the Controller

  • We need a Controller to handle the logic—fetching tasks from the database and saving new ones.
  • Run this command:
php artisan make:controller TaskController
  • Open app/Http/Controllers/TaskController.php and paste the following code. This is where the magic happens: instead of returning a generic view, we return an Inertia render.
<?php

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;
use Inertia\Inertia; // Import Inertia

class TaskController extends Controller
{
    public function index()
    {
        // Fetch all tasks, ordered by newest first
        $tasks = Task::orderBy('id', 'desc')->get();

        // Render the React component named "Tasks/Index" and pass the tasks as props
        return Inertia::render('Tasks/Index', [
            'tasks' => $tasks
        ]);
    }

    public function store(Request $request)
    {
        // Validate the input
        $request->validate([
            'title' => 'required|string|max:255'
        ]);

        // Create the task
        Task::create([
            'title' => $request->input('title')
        ]);

        // Redirect back (Inertia will handle the update without a full reload)
        return redirect()->back();
    }
}

Step 3: Define the Routes

  • Finally, we need to tell Laravel where to direct the traffic. Open routes/web.php and add these two routes:
use App\Http\Controllers\TaskController;

// ... existing routes ...

Route::get('/tasks', [TaskController::class, 'index'])->name('tasks.index');
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
  • Here is how my updated file looks like:
<?php

use App\Http\Controllers\ProfileController;
use App\Http\Controllers\TaskController;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});

Route::get('/dashboard', function () {
    return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');

    Route::get('/tasks', [TaskController::class, 'index'])
        ->name('tasks.index');

    Route::post('/tasks', [TaskController::class, 'store'])
        ->name('tasks.store');
});

require __DIR__.'/auth.php';

Step 4: Create the React Frontend

Now, let’s build the interface. When we returned Inertia::render('Tasks/Index') in our Controller, Inertia looked for a file located at resources/js/Pages/Tasks/Index.jsx.

Let’s create that file now.

1. Create the Component File

  • Navigate to resources/js/Pages.
  • Create a new folder named Tasks.
  • Inside that folder, create a file named Index.jsx.

Folder structure showing resources-js-Pages-Tasks with Index.jsx file inside

2. Add the React Code

Paste the following code into your new file. This component does two things:

  1. Displays Tasks: It accepts the tasks prop from Laravel and maps over them to show the list.
  2. Adds Tasks: It uses the useForm hook from Inertia to handle the form submission without reloading the page.
import React from 'react';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; // Uses Breeze's default layout
import { Head, useForm } from '@inertiajs/react';

export default function Index({ auth, tasks }) {
    // We use the useForm hook to handle form data and submission
    const { data, setData, post, processing, reset, errors } = useForm({
        title: '',
    });

    const submit = (e) => {
        e.preventDefault();
        
        // This sends a POST request to the Laravel route named 'tasks.store'
        post(route('tasks.store'), {
            onSuccess: () => reset(), // Clear the form on success
        });
    };

    return (
        <AuthenticatedLayout
            user={auth.user}
            header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">My Task List</h2>}
        >
            <Head title="Tasks" />

            <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 p-6">
                        
                        {/* THE FORM */}
                        <form onSubmit={submit} className="flex gap-4 mb-8">
                            <div className="flex-1">
                                <input
                                    type="text"
                                    className="border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm w-full"
                                    placeholder="What needs to be done?"
                                    value={data.title}
                                    onChange={(e) => setData('title', e.target.value)}
                                />
                                {errors.title && <div className="text-red-500 text-sm mt-1">{errors.title}</div>}
                            </div>
                            <button
                                type="submit"
                                disabled={processing}
                                className="bg-gray-800 text-white px-4 py-2 rounded-md hover:bg-gray-700 transition"
                            >
                                Add Task
                            </button>
                        </form>

                        {/* THE TASK LIST */}
                        <div className="space-y-4">
                            {tasks.map((task) => (
                                <div key={task.id} className="p-4 border border-gray-200 rounded-lg flex items-center justify-between">
                                    <span className="text-gray-800">{task.title}</span>
                                    <span className="text-xs text-gray-500">
                                        {new Date(task.created_at).toLocaleTimeString()}
                                    </span>
                                </div>
                            ))}
                            {tasks.length === 0 && (
                                <p className="text-gray-500 text-center">No tasks yet. Add one above!</p>
                            )}
                        </div>

                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}

3. Test the Application

Now comes the moment of truth. Let’s see your application in action.

  • Compile your assets: Because we just created a new React component, we need to tell Vite to include it. Run the build command one last time:
npm run build
  • Start the Server: Ensure your Laravel server is running:
php artisan serve
  • Log In: Open your browser to http://127.0.0.1:8000. Since this is a fresh database, click Register to create a new account.

register for laravel

  • Visit the Task List: Once logged in, manually change the URL in your address bar to:

http://127.0.0.1:8000/tasks

You should see your new “My Task List” page.

laravel node.js project final output

Try it out: Type a task name and hit “Add Task.” You will see the task appear in the list instantly. The form clears, the list updates, and the page does not reload.

And that is it! We have successfully built a Reactive Single Page Application (SPA) using Laravel and React.

Deploying Your React Application to Cloudways

In this final section, we will move our Reactive Task List application to a production environment.

We will use Git to push our code to a central repository, and then connect a Cloudways server to pull that code automatically. This workflow is the industry standard for modern web development.

Deployment Prerequisites

  • Git: Ensure Git is installed on your computer. (Download here).
  • GitHub Account: You will need a repository to host your code.
  • Cloudways Server: You need an active server. Start a free trial if you don’t have one.

1. Prepare Your Local Repository

First, we need to convert your project folder into a Git repository. This allows us to track changes and synchronize them with the server.

Open your terminal inside the react-task-app folder and run these commands:

# Initialize Git
git init

# Stage all files
git add .

# Commit your changes
git commit -m "Initial launch of React Task App"

# Rename branch to main
git branch -M main

Move From Localhost to Live in Minutes

You’ve built the app—now launch it without the stress. Connect your GitHub repo to Cloudways and deploy your code to a production-grade server automatically.

2. Push to GitHub

Now, let’s create a remote home for your code.

  • Log in to GitHub and create a New Repository.
  • Name it react-task-app and click Create.

create new github repository for our react-task-app

GitHub will provide a set of commands to push your existing repository. Copy the commands that look like this:

git remote add origin https://github.com/YOUR_USERNAME/react-task-app.git
git push -u origin main

push an existing repository from the command line

Run them in your terminal one by one.

run the commands to complete the PUSH

Once the push is complete, refresh your GitHub page. You should see your project files listed there.

project files listed

3. Provision the Server

If you don’t have a server yet, launch one on Cloudways by signing up for a 3-day free trial. Select Laravel as your application type and name it TaskApp.

create a laravel app on cloudways

4. Authorize Cloudways via SSH

For security, we will use an SSH Key to let Cloudways talk to GitHub. This is safer than using passwords.

  • On Cloudways, go to Applications → TaskApp → Deployment via Git.

click on deployment via git option in cloudways

  • Click Generate SSH Keys and then View SSH Key. Copy the key.

view ssh keys on cloudways

  • Go to your GitHub Repository → Settings → Deploy Keys.
  • Click Add deploy key, paste the key, give it a title, and save.

deploy ssh keys on github

5. Deploy the Codebase

With the permission set, we can now pull the code.

  • In GitHub, click the green Code button and copy the SSH URL (starts with [email protected]...).

In GitHub, click the green Code button and copy the SSH URL

  • Back in Cloudways, paste this into the Git Remote Address field.
  • Click Authenticate.

authenticate git remote access in cloudways

  • Select the main branch and click Start Deployment.

Select the main branch and click Start Deployment

Cloudways will now clone your repository to the server.

6. Build Assets and Configure Database

This is the most critical step for React applications. Unlike a standard PHP site, we must compile our JavaScript assets on the server or the frontend will not load.

A. Access the Server Terminal

Go to the Master Credentials tab in Cloudways and launch the SSH Terminal. Log in with your credentials.

cloudways master credentials for server

B. Navigate to Your App

Find your database name in the Access Details tab (e.g., qxyrz...). Then, in the SSH terminal window, navigate to your app folder by running the command below:

cd applications/[YOUR_DB_NAME]/public_html

C. Install and Build (The React Step)

Important: Before running the install commands, go to your Cloudways Application Settings and click Reset Permissions. This prevents “Permission denied” errors during installation.

reset app permissions in cloudways

Run the following three commands in order. This installs the backend libraries, the frontend libraries, and then builds the production React files.

composer install
npm install
npm run build

Note: The npm run build command is what converts your React code into the static files the browser needs.

D. Finalize Database Connection

First, we need to clean up default Cloudways migration files that conflict with Laravel 11. Run this command to prevent “Table already exists” errors:

rm database/migrations/2014_*.php database/migrations/2019_*.php

Next, update your .env file with the live database credentials found in your Access Details tab.

nano .env

Update DB_DATABASE, DB_USERNAME, and DB_PASSWORD. Save the file (Ctrl+X, Y, Enter).

update the env file

Then, run the migration to create your tasks table:

php artisan migrate:fresh --force

7. Go Live

At this point, your deployment is complete. Go ahead and open your Cloudways application URL and click the Register link on the top right of your site.

Create a new account and once registered, add /tasks to the end of your app URL. You should see your fully functional, reactive application running on the live server.

Here it is in action on the live server:

task list app in laravel with node.js on cloudways server

And here is the data being saved in the Cloudways database:

data saved in cloudways DB from the laravel node.js app

Conclusion

You have successfully bridged the gap between a robust backend and a dynamic frontend. By integrating Laravel and React using Inertia.js, you avoided the complexity of building a separate API while keeping your development workflow simple and efficient.

In this guide, you went from a blank slate to a fully functional “Task List” application. You set up a modern local environment, built a reactive interface that updates instantly without page reloads, and deployed the final result to a production-ready Cloudways server.

If you want to review the code or use this project as a starting point, you can find the complete source code on my GitHub Repository.

This setup—Laravel for logic, React for the interface, and Cloudways for hosting—gives you a scalable foundation. Whether you are building internal tools, client projects, or the next big SaaS platform, you now have the architecture to make it happen.

Can Laravel be used with React?

A) Yes, absolutely. Laravel provides excellent support for React. By using Inertia.js (as shown in this guide) or Laravel Passport/Sanctum for APIs, you can seamlessly connect Laravel’s robust backend with React’s dynamic frontend.

Which is better, ReactJS or Laravel?

A) They serve different purposes, so neither is “better”—they are complementary. Laravel is a backend PHP framework that handles the database, security, and logic. ReactJS is a frontend library that handles the user interface. The best approach is often to use both together to build a full-stack application.

Is Laravel for frontend?

A) Laravel includes a server-side templating engine called Blade, which handles frontend views. However, for modern, interactive applications, Laravel is increasingly used strictly as the backend, while dedicated JavaScript frameworks like React or Vue.js manage the frontend experience.

Is Laravel still in demand?

A) Yes, Laravel remains the most popular PHP framework globally. With regular updates (like the recent Laravel 11), a massive ecosystem, and high adoption in the enterprise sector, demand for Laravel developers continues to grow alongside modern frontend skills like React.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Abdul Rehman

Abdul is a tech-savvy, coffee-fueled, and creatively driven marketer who loves keeping up with the latest software updates and tech gadgets. He's also a skilled technical writer who can explain complex concepts simply for a broad audience. Abdul enjoys sharing his knowledge of the Cloud industry through user manuals, documentation, and blog posts.

×

Webinar: How to Get 100% Scores on Core Web Vitals

Join Joe Williams & Aleksandar Savkovic on 29th of March, 2021.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Want to Experience the Cloudways Platform in Its Full Glory?

Take a FREE guided tour of Cloudways and see for yourself how easily you can manage your server & apps on the leading cloud-hosting platform.

Start my tour