Using Advanced Layouts In SvelteKit

Published Feb 10, 2023

Table of Contents

Previously

This is part of a SvelteKit series and while each part is meant to be self-contained here are the previous parts in case you want to catch up:

Project Setup

If you want to follow along the easiest method is to open the starting project on StackBlitz but if you prefer the comfort of your editor I provided a repository on GitHub with the starting and final example.

Clone the project.

terminal
git clone https://github.com/joysofcode/advanced-layouts.git

After you clone the project you can install the dependencies and start the development server.

terminal
npm i && npm run dev

If you want to look at the solution switch the branch.

terminal
git checkout solution

Sometimes You Want Routes With Different Layouts

Let’s say I have a million dollar idea and it’s named Plume β€” a site for discovering and sharing inspiring quotes.

A site for discovering and sharing inspiring quotes

The investors are lined up but before I can push the yacht to sea I need to push the code into production but I’ve ran into a problem.

I shouldn’t be sharing trade secrets but here’s the routes structure.

routes
routes
β”œβ”€β”€ admin
β”‚   β”œβ”€β”€ +layout.svelte
β”‚   β”œβ”€β”€ +page.server.ts
β”‚   └── +page.svelte
└── quotes
    β”œβ”€β”€ id
    β”‚   └── [quoteId]
    β”‚       β”œβ”€β”€ +page.server.ts
    β”‚       └── +page.svelte
    β”œβ”€β”€ tags
    β”‚   β”œβ”€β”€ [tag]
    β”‚   β”‚   β”œβ”€β”€ +page.server.ts
    β”‚   β”‚   └── +page.svelte
    β”‚   β”œβ”€β”€ +page.server.ts
    β”‚   └── +page.svelte
    β”œβ”€β”€ +layout.server.ts
    β”œβ”€β”€ +layout.svelte
    └── +page.svelte

That’s a sweet tree but it hides dark secrets.

If you navigate to /admin you’re going to notice the first issue where the admin layout (/admin/+layout.svelte) shares the root layout (/routes/+layout.svelte) which makes me look like a clown in the eyes of the investors. 🀑

Admin route layout problem

Yikes! But that’s not everything.

Notice the /quotes route? I want a layout that shows more quotes at the end of the page if I go to other child routes like /quotes/id/[quoteId] but I might not want that layout for /quotes/tags.

Tags route layout problem

Sure, I could move the /tags route outside the /quotes route which would solve the problem but I don’t want to do that. Because every child route in /quotes shares the same layout from /quotes/+layout.svelte if you go to /quotes/tags it shows other quotes.

This is where group layouts help.

Group layouts let you group routes inside a directory wrapped in parenthesis but they don’t create a new route.

To fix the admin layout I’m going to create an (app) and (dashboard) group. If you want the group to be the root (/) of your app you can put the +page.svelte file inside the group.

I’m going to keep the global styles inside /routes/+layout.svelte but move everything else which is going to leave us with a blank root layout.

src/routes/+layout.svelte
<script lang="ts">
  import '@picocss/pico'
  import '../app.css'
</script>

<svelte:head>
  <link rel="icon" href="https://fav.farm/πŸͺΆ" />
  <title>Plume</title>
</svelte:head>

<slot />

I’m going to move the navigation from /routes/+layout.svelte and /routes/+page.svelte including the /quotes route inside the (app) directory and then I only have to drag the /admin route inside the (dashboard) directory.

routes
routes
β”œβ”€β”€ (app)
β”‚   └── quotes
β”‚       β”œβ”€β”€ id
β”‚       β”‚   └── ...
β”‚       β”œβ”€β”€ tags
β”‚       β”‚   └── ...
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       └── +page.svelte
β”œβ”€β”€ (dashboard)
β”‚   └── admin
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       β”œβ”€β”€ +page.server.ts
β”‚       └── +page.svelte
└── +layout.svelte

Wonderful!

Admin route using app group layout

To fix the tags layout I’m going to use a group layout to create separate groups for (quote) and (tags) under the /quotes route and move the /quotes/id route inside quotes/(quote) and the /quotes/tags route inside /quotes/(tags).

routes
routes
β”œβ”€β”€ (app)
β”‚   └── quotes
β”‚       β”œβ”€β”€ (quote)
β”‚       β”‚   β”œβ”€β”€ id
β”‚       β”‚   β”‚   └── ...
β”‚       β”‚   β”œβ”€β”€ +layout.server.ts
β”‚       β”‚   β”œβ”€β”€ +layout.svelte
β”‚       β”‚   └── +page.svelte
β”‚       β”œβ”€β”€ (tags)
β”‚       β”‚   β”œβ”€β”€ tags
β”‚       β”‚   β”‚   └── ...
β”‚       β”‚   └── +layout.svelte
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       └── +page.svelte
β”œβ”€β”€ (dashboard)
β”‚   └── admin
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       β”œβ”€β”€ +page.server.ts
β”‚       └── +page.svelte
└── +layout.svelte

That’s it!

Tags route using the dashboard group layout

I think what makes group layouts confusing is when you start nesting layouts because you can think of group layouts as buckets to put things into but if you’re not confident in using layouts yet this is going to be hard to wrap your head around.

If you’re not sure when to use a layout ask yourself if the child routes of a given route have some repeating content you want to show β€” also remember we previously learned that data returned from layout load functions is available to child routes on the data prop which is useful.

You don’t have to use group layouts, so put this away in your pocket in case you need it and focus on the fundamentals instead.

If you thought this was mind-bending in the next section I’m going to show you that individual pages and layouts can also change layouts.

Breaking Out Of Layouts

Group layouts are nice if you want some pages and their children to have a different layout but you can also use a different layout for a specific page and layout.

Right now the /(app)/quotes/(quote)/id/[quoteId]/+page.svelte route shares the app layout and quotes layout but if you didn’t want to use the quotes layout for showing more quotes you can use the app layout instead and rename +page.svelte to +page@(app).svelte.

routes
routes
β”œβ”€β”€ (app)
β”‚   └── quotes
β”‚       β”œβ”€β”€ (quote)
β”‚       β”‚   β”œβ”€β”€ id
β”‚       β”‚   β”‚   └── [quoteId]
β”‚       β”‚   β”‚       β”œβ”€β”€ +page.server.ts
β”‚       β”‚   β”‚       └── +page@(app).svelte
β”‚       β”‚   β”œβ”€β”€ +layout.server.ts
β”‚       β”‚   β”œβ”€β”€ +layout.svelte
β”‚       β”‚   └── +page.svelte
β”‚       β”œβ”€β”€ (tags)
β”‚       β”‚   β”œβ”€β”€ tags
β”‚       β”‚   β”‚   └── ...
β”‚       β”‚   └── +layout.svelte
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       └── +page.svelte
β”œβ”€β”€ (dashboard)
β”‚   └── admin
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       β”œβ”€β”€ +page.server.ts
β”‚       └── +page.svelte
└── +layout.svelte
Example showing a page reset

If you ever looked up how to reset a layout in SvelteKit you were probably confused because to do so you would need a blank root layout which only makes sense now after you learned about group layouts and breaking out of layouts.

If you want to reset a layout and use the root layout you can use an empty string +page@.svelte or +layout@.svelte to use the root layout.

The (app)/quotes/(tags)/+layout.svelte route shares the app layout and it’s children are going to inherit the tags layout if you visit /quotes/tags but if you wanted to change the parent app layout layout and use the root layout you can rename +layout.svelte to +layout@.svelte.

routes
routes
β”œβ”€β”€ (app)
β”‚   └── quotes
β”‚       β”œβ”€β”€ (quote)
β”‚       β”‚   β”œβ”€β”€ id
β”‚       β”‚   β”‚   └── [quoteId]
β”‚       β”‚   β”‚       β”œβ”€β”€ +page.server.ts
β”‚       β”‚   β”‚       └── +page@(app).svelte
β”‚       β”‚   β”œβ”€β”€ +layout.server.ts
β”‚       β”‚   β”œβ”€β”€ +layout.svelte
β”‚       β”‚   └── +page.svelte
β”‚       β”œβ”€β”€ (tags)
β”‚       β”‚   β”œβ”€β”€ tags
β”‚       β”‚   β”‚   └── ...
β”‚       β”‚   └── +layout@.svelte
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       └── +page.svelte
β”œβ”€β”€ (dashboard)
β”‚   └── admin
β”‚       β”œβ”€β”€ +layout.svelte
β”‚       β”œβ”€β”€ +page.server.ts
β”‚       └── +page.svelte
└── +layout.svelte
Example showing a layout reset

Now you know how to break out of layouts if you have to.

In the next part you’re going to learn about SvelteKit hooks before you learn how to deploy a SvelteKit project.

Support

If you want to support the content you're reading or watching on YouTube consider becoming a patreon starting low as 1$ per month.

Become a patreon
Subscribe For Updates
Found a mistake?

Every post is a Markdown file so contributing is simple as following the link below and pressing the pencil icon inside GitHub to edit it.

Edit on GitHub