All notes
Web & Framework2 min readUpdated August 7, 2026

Laravel as the API, Next.js as the Frontend

How to arrange the two frameworks as one system, what separating them actually costs, and when not to separate them at all.

LaravelNext.jsREST APISanctumCORSArchitecture

The common arrangement: Laravel owns the data, the business rules and authentication and exposes them as JSON; Next.js owns presentation and user experience and fetches that data over HTTP. They run as two separate applications.

Who owns what

ConcernOwned by
Database schema and migrationsLaravel
Business rules and validationLaravel
Authentication and authorisationLaravel
Page routing and navigationNext.js
Presentation, animation, interactionNext.js
SEO and meta tagsNext.js

Where the data should be fetched

Calls to the Laravel API can come from a Server Component or from the browser. Both are legitimate, but they carry different consequences, and choosing without noticing is a common source of security problems.

  • From a Server Component — server to server. The token never reaches the browser, and the page can be rendered complete before it is sent, which is good for SEO. This is the right default for data you display.
  • From a Client Component — browser to Laravel. Necessary for data that changes after user interaction. The API then has to allow CORS, and whatever the request carries is visible to the user.

Authentication with Sanctum

Laravel Sanctum offers two modes that are easy to confuse. SPA mode uses session cookies and only works when both applications sit under the same parent domain — a good fit for internal applications. API token mode sends a token in the Authorization header, does not depend on domains, and suits a frontend and backend deployed far apart.

Calling the Laravel API from a Server Component
// Runs on the server: the token is never sent to the browser
async function getVisitors() {
  const res = await fetch(`${process.env.API_URL}/api/visitors`, {
    headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
  });

  if (!res.ok) throw new Error(`Failed to load: ${res.status}`);
  return res.json();
}

What it costs

  • Two applications to deploy, monitor and upgrade instead of one.
  • CORS has to be configured correctly, and misconfiguring it produces browser errors that read as nonsense.
  • The shape of the JSON becomes a contract between the two sides; changing it in Laravel can break the frontend with no warning at all.
  • Authentication is more involved than a plain session inside a single application.

More notes