Back to Blog
ArchitectureAug 28, 20269 min read

Laravel + Next.js: Architecture for Full Stack Applications

How to structure a Laravel backend with a Next.js frontend for production applications, covering API design, authentication flow, and deployment strategies.

The Laravel + Next.js Stack

Laravel handles the backend logic, API, database, and authentication. Next.js handles the frontend rendering, routing, and user interface. Together, they give you a powerful full stack setup.

I've used this architecture for healthcare platforms and business applications where both performance and developer experience matter.

Project Structure

project/
├── backend/          # Laravel API
│   ├── app/
│   ├── routes/
│   └── ...
├── frontend/         # Next.js app
│   ├── app/
│   ├── components/
│   ├── lib/
│   └── ...
└── docker-compose.yml

API Design

Keep your Laravel API focused on data and business logic:

// Backend: routes/api.php
Route::prefix('v1')->group(function () {
    Route::post('login', [AuthController::class, 'login']);
    Route::post('register', [AuthController::class, 'register']);

    Route::middleware('auth:api')->group(function () {
        Route::apiResource('patients', PatientController::class);
        Route::apiResource('appointments', AppointmentController::class);
    });
});

Frontend API Layer

Create a clean API layer in Next.js:

// lib/api.ts
const API_BASE = process.env.NEXT_PUBLIC_API_URL;

async function apiFetch<T>(endpoint: string, options?: RequestInit): Promise<T> {
  const token = localStorage.getItem('token');

  const response = await fetch(`${API_BASE}/api/v1${endpoint}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...options?.headers,
    },
  });

  if (!response.ok) {
    throw new ApiError(response.status, await response.json());
  }

  return response.json();
}

export const api = {
  get: <T>(endpoint: string) => apiFetch<T>(endpoint),
  post: <T>(endpoint: string, data: unknown) =>
    apiFetch<T>(endpoint, { method: 'POST', body: JSON.stringify(data) }),
};

Authentication Flow

1. User submits credentials to Next.js form

2. Next.js sends POST to Laravel /api/v1/login

3. Laravel returns JWT token

4. Next.js stores token in localStorage

5. Subsequent requests include Authorization: Bearer <token> header

CORS Configuration

Laravel needs to allow requests from your Next.js dev server:

// config/cors.php
'allowed_origins' => [
    'http://localhost:3000',
    'https://your-domain.com',
],

Deployment Strategy

  • Laravel API: Deploy to VPS with Nginx + PM2 or Laravel Forge
  • Next.js: Deploy to Vercel or self-hosted with PM2
  • Use environment variables for API URLs in each environment
  • Key Takeaways

  • Keep Laravel focused on API logic, Next.js on UI
  • Create a typed API layer in the frontend
  • Handle authentication with JWT across both stacks
  • Configure CORS properly for development and production
  • Deploy independently — the frontend and backend are separate apps