Kritim Yantra
Jun 05, 2025
In the ever-evolving web development landscape, combining Laravel (a powerful PHP backend framework) with Next.js (a modern React-based frontend framework) offers developers a robust, scalable, and high-performing full-stack solution. This comprehensive guide walks you through multiple approaches to integrating Laravel 12 with Next.js 15, covering setup, authentication, deployment, and optimization.
Laravel brings:
Next.js delivers:
Together, they create:
composer create-project laravel/laravel laravel-backend
config/cors.php
:return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_origins' => ['http://localhost:3000'],
'allowed_methods' => ['*'],
'allowed_headers' => ['*'],
'supports_credentials' => true,
];
routes/api.php
:Route::middleware('auth:sanctum')->get('/user', fn (Request $request) => $request->user());
Route::get('/posts', [PostController::class, 'index']);
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
npx create-next-app@latest nextjs-frontend
npm install axios
lib/api.js
):const apiClient = axios.create({
baseURL: 'http://localhost:8000/api',
withCredentials: true,
});
export default {
getPosts: () => apiClient.get('/posts'),
};
pages/posts/index.js
:import { useEffect, useState } from 'react';
import api from '../../lib/api';
export default function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
api.getPosts().then(res => setPosts(res.data));
}, []);
return (
<ul>
{posts.map(p => <li key={p.id}>{p.title}</li>)}
</ul>
);
}
Use Next.js API routes as a proxy layer between the frontend and Laravel.
pages/api/posts.js
import axios from 'axios';
export default async function handler(req, res) {
try {
const response = await axios({
method: req.method,
url: `http://localhost:8000/api/posts`,
data: req.body,
});
res.status(response.status).json(response.data);
} catch (error) {
res.status(500).json({ error: 'Internal Server Error' });
}
}
npm run build && npm export
Copy out/
folder content to Laravel public/
Route Laravel wildcard to index:
Route::get('/{any}', fn() => file_get_contents(public_path('index.html')))->where('any', '.*');
.env
:SANCTUM_STATEFUL_DOMAINS=localhost:3000
SESSION_DOMAIN=localhost
await axios.get('http://localhost:8000/sanctum/csrf-cookie', { withCredentials: true });
await axios.post('http://localhost:8000/login', credentials, { withCredentials: true });
export const AuthContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
useEffect(() => {
axios.get('/api/user', { withCredentials: true }).then(r => setUser(r.data));
}, []);
return <AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>;
}
npm install swr
import useSWR from 'swr';
export function usePosts() {
const fetcher = (url) => fetch(url).then(res => res.json());
const { data, error } = useSWR('/api/posts', fetcher);
return { posts: data, isLoading: !error && !data, isError: error };
}
const { posts, isLoading } = usePosts();
public/
Use docker-compose
with services for Laravel, Next.js, and MySQL for unified local development and deployment.
php artisan route:cache
withCredentials
/sanctum/csrf-cookie
firstLaravel 12 and Next.js 15 together provide unmatched power and flexibility. With Laravel managing your backend APIs and Next.js delivering blazing-fast UIs, you can build everything from SPAs to large-scale web apps.
By following this guide, you're now equipped to:
Now it's your turn to innovate. Happy coding! 🧰
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google