# Nuxt 4 in front of a Laravel API

> Nuxt renders the public site. Laravel stays the API. The cookie rules stay in the Sanctum guide. This page is the Nuxt call.

- URL: https://laravel-vuejs.space/nuxt-laravel-api
- Author: Anass Ez-zouaine (https://laravel-vuejs.space/author/anass-ez-zouaine)
- Published: 2026-10-10
- Topics: Laravel, VueJs, NuxtJs, Sanctum

Nuxt renders a beautiful public site, then the logged-in list comes back empty on the server and fine in the browser. That is the cookie, not Nuxt. Here is the Nuxt side of a Laravel API: the URL, the request, and where server rendering stops.

> **TL;DR**
>
> -   Start new front ends on Nuxt 4; Nuxt 3 stopped receiving updates on 31 July 2026.
> -   Keep the Laravel origin in `runtimeConfig.public.apiUrl`, overridden by `NUXT_PUBLIC_API_URL`.
> -   `credentials: 'include'` sends the cookie from the browser, not from the Nuxt server.
> -   Use the Sanctum session cookie, not a token in `localStorage`.
>
> **What you'll learn**
>
> -   Which Nuxt and Node versions to start on
> -   How to configure the Laravel API URL
> -   Why SSR does not send the Laravel cookie
>
> **Who it's for:** Vue developers putting Nuxt in front of Laravel
>
> **Applies to:** Nuxt 4.6 · Node 22.22.3+ / 24.15.0+ / 26 · Laravel 13 · Sanctum

Use Nuxt when the public site is the product and Laravel is the API behind it. Nuxt 3 stopped receiving updates on 31 July 2026, so a new front end starts on Nuxt 4. Nuxt 4.6 requires Node 22.22.3 or newer, Node 24.15.0 or newer, or Node 26. That is stricter than the Vite floor in [the requirements](https://laravel-vuejs.space/requirements). Do not start here for an internal tool. The Vue starter kit already has login and routing. That choice is [Inertia, a SPA, or Nuxt](https://laravel-vuejs.space/laravel-vue-in-2026).

## The API URL

> **Gotcha: hardcoded localhost ships**
>
> Keep the Laravel origin in runtime config. A hardcoded `localhost:8000` inside a component is the URL that ships to production.

```bash
npm create nuxt@latest
```

`nuxt.config.ts`
```ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiUrl: "http://localhost:8000",
    },
  },
});
```

Set `NUXT_PUBLIC_API_URL` in the Nuxt environment when the host changes. Nuxt maps that name onto `runtimeConfig.public.apiUrl`.

## The request

> **Heads up: SSR has no Laravel cookie**
>
> `credentials: 'include'` sends the session cookie from the browser. It does not attach that cookie when Nuxt server-renders an absolute Laravel URL, because the Nuxt server never received a cookie that lives on the Laravel origin. A logged-in list has to load in the browser, or through a relative proxy that forwards the cookie.

The cookie only exists after the Sanctum flow: stateful domains, `supports_credentials`, `GET /sanctum/csrf-cookie`, then `POST /login`. Those steps are [Sanctum for a Vue SPA](https://laravel-vuejs.space/laravel-sanctum-vue-spa). Nuxt’s dev server is usually port 3000, so that origin is the one you add. CORS for that port is [the CORS guide](https://laravel-vuejs.space/laravel-vue-cors). This page does not copy either setup.

```vue
<script setup lang="ts">
const config = useRuntimeConfig();

const { data, error } = await useFetch(`${config.public.apiUrl}/api/posts`, {
  credentials: "include",
});
</script>

<template>
  <p v-if="error">Could not load posts.</p>
  <article v-for="post in data?.data" :key="post.id">
    <h2>{{ post.title }}</h2>
  </article>
</template>
```

`data.data` is there because a Laravel paginator or an API resource collection returns `{ data, links, meta }`. The resource class is [API resources](https://laravel-vuejs.space/laravel-api-resources-vue). If the controller returns a raw array, drop the extra `.data`. Guessing which shape you have is how the list renders blank.

> **Check the shape before you render**
>
> Log `data.value` once in the browser console. If it has `data`, `links` and `meta`, keep `data?.data`. If it is an array, drop the extra `.data`.

## Auth from Nuxt

Call `/sanctum/csrf-cookie` and `/login` on the Laravel origin, with credentials, before this `useFetch` expects a user. A 401 means there is no session. A 419 means the CSRF cookie was missing. Both are diagnosed in the Sanctum guide. Nuxt middleware can redirect to your login page on 401. It cannot fix the cookie.

> **Tip: cookie, not localStorage**
>
> Do not put a Laravel token in `localStorage` for this first-party site. Sanctum’s own docs tell a first-party SPA to use the session cookie.

## Where this stops

Admin screens that only staff use can stay on Inertia inside Laravel. You do not have to rebuild them in Nuxt. Deploy the two apps as two processes. The Laravel half still follows [deploy](https://laravel-vuejs.space/deploy-laravel-vue), including `public/hot` and `php artisan optimize`.

## Recap

- Nuxt 4 for new front ends; check the Node floor.
- API origin in runtime config, not in components.
- Server rendering cannot send a cookie that lives on the Laravel origin.
- Sanctum, CORS and the resource shape each have their own guide.

## FAQ

**Q: Should I use Nuxt 3 or Nuxt 4 with Laravel?**

Nuxt 4. Nuxt 3 stopped receiving updates on 31 July 2026.

**Q: Why is my Nuxt useFetch to Laravel unauthenticated during SSR?**

The session cookie lives on the Laravel origin, so the Nuxt server never has it. Load logged-in data in the browser, or proxy through a relative path that forwards the cookie.

**Q: Why does my Nuxt list render blank?**

A Laravel paginator or resource collection returns `{ data, links, meta }`. Loop over `data.data`, or drop `.data` if the controller returns a plain array.

## Next steps

- [Sanctum for a Vue SPA](https://laravel-vuejs.space/laravel-sanctum-vue-spa)
- [Laravel and Vue CORS errors](https://laravel-vuejs.space/laravel-vue-cors)
- [Laravel API resources for a Vue client](https://laravel-vuejs.space/laravel-api-resources-vue)

## Sources

- [Nuxt: Runtime config](https://nuxt.com/docs/guide/going-further/runtime-config)
- [Nuxt: useFetch](https://nuxt.com/docs/api/composables/use-fetch)
- [Laravel 13: Sanctum, SPA authentication](https://laravel.com/docs/13.x/sanctum#spa-authentication)
