Using different app layouts in one Inertia app

Hey everyone,

Have you guys tried using different app layouts in one Inertia + Vue app?

Let's say, for the back office (admin) we'll use admin.blade.php instead of the default app.blade.php

And for the front side e.g. e-commerce, we'll use the default app.blade.php

I need to do this because I'm using a template, the front-side UI is different from the back office (admin).

whoami (Daryl)
whoami (Daryl)
0
17
817
Haz
Haz
Moderator

Hello,

I would only have one app.blade.php file. Then with Vue, create multiple layouts.

AppLayout.vue:

<template>
	<h1>User area</h1>

    <slot />
</template>

Dashboard.vue:

<template>
	<AppLayout>
		<h1>Dashboard</h1>
	</AppLayout>
</template>

AdminLayout.vue:

<template>
	<div>Admin area</div>

    <slot />
</template>

Users.vue:

<template>
	<AdminLayout>
		<h1>Users</h1>
	</AdminLayout>
</template>

See also:

Creating layouts

Persistent layouts

Default layouts

alex
alex
Moderator

Yep, this is the best approach for multiple layouts.

Multiple base template files will cause a headache down the line unless you have incredibly separated applications :)

whoami (Daryl)
whoami (Daryl)

Hey @alex

Thanks for your response, my concern with it is that I'm not able to use different CSS files.

E.g. In my admin.blade.php, I will put the CSS files included with the back office template.

And in my app.blade.php, I will put the CSS files included in the e-commerce template.

whoami (Daryl)
whoami (Daryl)

Thanks @Haz

Haz
Haz
Moderator

Put them in app.blade.php or AdminLayout.vue.

There's nothing stopping you from adding link and script tags.

You have a couple of choices here:

useScriptTag

AdminLayout.vue:

<script setup>
	useScript(...)
</script>

<template>
	<link rel="..." href="...">
	
	<slot />
</template>

I think you could also just do this:

<script setup>
	//
</script>

<template>
	<head>
		<link rel="..." href="...">

		<script src="..."></script>
	</head>

	<slot />
</template>

Remember, it's just a layout. I hope this helps.

whoami (Daryl)
whoami (Daryl)

Hey, I'll try this. But I think this will not behave like the way we load assets in our blade files through @vite?

Haz
Haz
Moderator

Hello,

I'm not sure. Are these CDNs and precompiled assets? It's hard to comment without knowing more context.

whoami (Daryl)
whoami (Daryl)

Sorry, let's take this css file as an example for the admin design.

Ideally, we place this inside resources/css and then import it in our app.js.

// app.js
import "../css/styles.css";
// vite.config.js
...
    laravel({
      input: ["resources/js/app.js"],
      refresh: true,
    }),

Finally, in app.blade.php

@vite('resources/js/app.js')

While writing this, I realized I need multiple app.js too, separate for each UI (admin, e-commerce). I'm confused right now. 😅

Haz
Haz
Moderator

Hello,

I think you are overcomplicating it.

Remove the following line (and any other lines that are specific to a layout) from your app.js file and app.css file. Shared assets can remain.

import "../css/styles.css";

AdminLayout.vue:

<template>
	<head>
		<!-- make sure the path is correct -->
		<link rel="stylesheet" href="../css/styles.css">
	</head>

	<slot />
</template>

Let's say you have a users page under your admin area for example...

Users.vue:

<template>
	<AdminLayout>
		<h1>Users</h1>
	</AdminLayout>
</template>

See my post above regarding script tags.

You are still going to use Vite to bundle assets, providing that you aren't using SB Admin Pro dist assets.

I was going to create an example repo for you, but SB Pro Admin is a paid product. If you share what assets you need to load, I can provide further assistance.

whoami (Daryl)
whoami (Daryl)

Hey, Haz,

You're right, I'm over complicating it, sorry about that, I'm new with this Inertia setup.

Let me try your approach, thank you.

If you still wanna create an example repo, you can use this free SB admin.

whoami (Daryl)
whoami (Daryl)

Just an update, I tried this one.

AdminLayout.vue:

<template>
	<head>
		<!-- make sure the path is correct -->
		<link rel="stylesheet" href="../css/styles.css">
	</head>

	<slot />
</template>

It is working but the styles.css is not included when I run npm run build, that's because I link it directly.

Also, I found this thread. I'm not sure if it's a good workaround.

public function rootView(Request $request): string
{
    if ($request->routeIs('admin.*')) {
        return 'layouts.admin';
    }

    return $this->rootView;
}
Haz
Haz
Moderator

Hey,

Crazy weekend here. Will get back you sometime tomorrow. I’ll update this post.

whoami (Daryl)
whoami (Daryl)

Hey, Haz,

Thank you.

Haz
Haz
Moderator
Solution

Hello,

I have been playing around with this. I honestly don't think you need that workaround solution.

The following should be enough:

<Head>
<link>
<style>
<script>
useScriptTag

It is working but the styles.css is not included when I run npm run build, that's because I link it directly.

You need to instruct Vite to build it.

vite.config.js:

        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
                'resources/css/custom.css',
                'resources/js/custom.js',
                'resources/css/admin.css',
                'resources/js/admin.js',
            ],
            refresh: true,
        }),

I made a simple app to test it all out. You can find the repo here. Check the routes to follow along.

If you still wanna create an example repo, you can use this free SB admin.

I checked it.

It seems that you have all of the files locally, so the approach taken in the example app above is pretty much the same. One key difference is that SB Admin uses Sass, so you will need to install a Sass plugin if you want to heavily customise it. Luckily Vite has you covered:

CSS Pre-processors

I think I have given you all the information that you need to take over. Let me know if you need anything else.

I hope this helps.

Note: You will notice that there aren't any dedicated layouts here, but the logic in each page can be easily moved. I was just demonstrating how you can separate assets and build them.

whoami (Daryl)
whoami (Daryl)

Hey, Haz,

Sorry for the late reply, appreciate your effort in this.

Haz
Haz
Moderator

Helllo @whoami,

I wanted to check if your issue was solved. I saw you marked the best answer, but want to make sure it's actually working.

whoami (Daryl)
whoami (Daryl)

Hey, Haz,

Thanks for checking out. Yeah, it works.

I also use the VueUse's useScriptTag for some scripts.

Thanks again!