Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Jaun's avatar
Level 6

Conditional layouts

Hi everyone! In a project using Laravel + Vue, I´d like to use two different vue layouts depending on the user being logged in or not. In some places it´s ok to change small bits with v-if, but in some others I think it would be good to change layouts (and keep them persistent). I´m new to this, didn´t manage to make it work... could solve it with two different routes, but there must be a better approach. Help?

0 likes
6 replies
LaryAI's avatar
Level 58

To achieve conditional layouts in a Laravel + Vue project based on whether the user is logged in or not, you can follow these steps:

  1. Create Two Layout Components: Create two different Vue components for your layouts, one for authenticated users and one for guests.

  2. Use Vue Router with Meta Fields: Use Vue Router to define routes and add meta fields to specify which layout to use.

  3. Check Authentication Status: Use a global navigation guard in Vue Router to check the user's authentication status and dynamically set the layout.

Here’s a step-by-step solution:

Step 1: Create Layout Components

Create two layout components, e.g., AuthLayout.vue and GuestLayout.vue.

<!-- AuthLayout.vue -->
<template>
  <div>
    <header>Authenticated Header</header>
    <main>
      <router-view></router-view>
    </main>
    <footer>Authenticated Footer</footer>
  </div>
</template>

<script>
export default {
  name: 'AuthLayout',
};
</script>
<!-- GuestLayout.vue -->
<template>
  <div>
    <header>Guest Header</header>
    <main>
      <router-view></router-view>
    </main>
    <footer>Guest Footer</footer>
  </div>
</template>

<script>
export default {
  name: 'GuestLayout',
};
</script>

Step 2: Define Routes with Meta Fields

Define your routes in router/index.js and use meta fields to specify the layout.

import Vue from 'vue';
import Router from 'vue-router';
import AuthLayout from '@/layouts/AuthLayout.vue';
import GuestLayout from '@/layouts/GuestLayout.vue';
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';

Vue.use(Router);

const routes = [
  {
    path: '/',
    component: Home,
    meta: { layout: 'auth' },
  },
  {
    path: '/login',
    component: Login,
    meta: { layout: 'guest' },
  },
];

const router = new Router({
  mode: 'history',
  routes,
});

export default router;

Step 3: Use a Global Navigation Guard

In your main App.vue or a similar entry point, use a global navigation guard to dynamically set the layout based on the user's authentication status.

Step 4: Authentication Logic

Ensure you have a way to check if the user is authenticated. This example uses localStorage to store an authentication token, but you should replace it with your actual authentication logic.

Conclusion

By following these steps, you can conditionally render different layouts based on the user's authentication status in a Laravel + Vue project. This approach keeps your layouts persistent and avoids the need for multiple routes for the same content.

1 like
experimentor's avatar

@jaun, Lary nailed it. But, If you are using Breeze + Inertia + Vue, it will come preloaded with 2 layouts. AuthenticatedLayout.vue and GuestLayout.vue. GuestLayout is used on all public routes like login, register, etc...

You can scaffold a new laravel project with Breeze + Inertia + Vue to refer and understand how the two layouts are used.

Jaun's avatar
Level 6

Thank you @experimentor! I´m using Jetstream on this specific project, and using both layouts (GuestLayout and AuthenticatedLayout) and everything goes fine but I can only use one layout per route... as an example, let´s say I have a post.edit, I´m always using AuthenticatedLayout, but on my post.index I´m always using GuestLayout, even if the user is actually authenticated... I can conditionally hide/show components dependending on the authentication situation, but didn´t manage to change the entire layout and keep it persistent. I´ve seen Lary´s aproach in my previous searches and I guess I could use a conditional in the meta field... the thing is I´m not using vue´s router, but Laravel´s. I haven´t researched yet if there´s a way to use this meta field there, I think it´s my next step!

experimentor's avatar

@Jaun, as you mentioned the "meta" approach works for application with vue's router. Its vue router specific. When using Jetstream with inertia, "meta" is not a solution.

You can easily create any number of layouts in your project and use them wherever needed. Here is an approach which might work for you... assuming you want to utilise the AuthenticatedLayout with some changes for some pages (or routes).

  • Create a copy of the AuthenticatedLayout.vue. Let's call it NewLayout.vue.
  • Make the necessary changes: add/remove/edit elements as needed
  • So Layouts folder has 3 files now: GuestLayout, AuthenticatedLayout, NewLayout
  • In the Pages folder, choose the page file for which you need the modified layout.
  • Replace these lines..
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';

<AuthenticatedLayout>
</AuthenticatedLayout>
  • with this:
import NewLayout from '@/Layouts/NewLayout.vue';

<NewLayout>
</NewLayout>

Hope this works for you.

1 like
puklipo's avatar

This can be solved by modifying the AuthenticatedLayout so that it displays correctly for guest users.

I always modify this for blade layouts too.

1 like
Jaun's avatar
Level 6

I´m just keeping one AppLayout... as this time the layouts for authenticated and guest users were quiet different, I wanted to avoid having too many conditionals and CSS styles inside the layout file, and thought I could use the conditional before loading the layout file... but in the end I grouped things differently, reduced the amount of conditionals and I think it´s quiet ok. I would still like learn if what I thought it´s doable, but I´ll leave it in pause for now to not get stuck. I will still use in some cases different layouts as @experimentor says. Thanks a lot for the replies!

1 like

Please or to participate in this conversation.