So in the earlier chapter on routing,
we learned how to create routes with dynamic parameters.
But sometimes it's helpful to make a parameter optional.
A really good example of this is when you're using the path name to
determine the locale.
So you might begin your routes with slash fr for your French users, slash de for
your German users, and so on.
But you also want to have a default locale.
So at the moment, we're doubling things up.
We have our default page.svelte here,
and then we also have the language-specific ones up here.
And this one here is kind of duplicative, we wanna get rid of that.
So we can change this lang directory here to use double brackets instead, and
that makes that parameter optional.
Just gonna hit the Rename button there and
change that to lang with double brackets.
And the app is now failing to build because we have a conflict
between this route and this route.
In other words, it's ambiguous, SvelteKit doesn't know which of these is supposed to
apply if you hit the slash route.
So we're gonna just delete this altogether.
And then finally, we're gonna edit the page.server.js inside
the lang directory to specify a default local.
So here's our internationalization data here.
I'm just gonna add a fallback here for when lang is undefined.
Sometimes you'll have a route that has an unknown number of path segments.
And in these cases, we can use what's called a rest parameter to match
any number of segments from zero to whatever.
And it's named after its resemblance to the rest parameters in JavaScript.
So let's take this src slash routes slash path directory and
rename it to dot dot dot path.
Right, this will now match any route whatsoever.
So we can keep clicking this and it will still match the current route
Until eventually we reset.
And when you have a situation like this,
other more specific routes will be tested first.
So the rest parameter is essentially a catchall.
This is useful to have innested inside other directories.
For example, if you want custom 404 pages for different parts of your app, then you
can create a catchall that has its own error.svelte and its own data loading.
Inside the load function, you could throw in a 404 error and
it would render that error page instead of the fallback error page.
Now, unlike in some frameworks, you do not need to put your rest parameters at
the end of the route, you can have them inside.
So something like slash item slash dot dot dot path slash edit,
is a totally valid route, or slash items slash dot dot dot path.
Dot Jason is also totally valid.
Sometimes we want to add some matching logic to our routing.
For example, you might want a route like colors slash value to match
hex values like ff3e00 or 676779.
But you don't wanna match named colors like colors slash up to green or
any other arbitrary input like this invalid value here.
And we can do that with a thing called a matcher.
First, we create a new file in a directory called params.
I'm gonna call this one hex.js.
And inside this module, I'm gonna export a function called match.
And the job of this function is to return true if the parameter is a successful
match, and false if it's not.
So the regular expression for a hex code is, let's see,
we want the caret to match the start, and
then we want to have any number of 0 to 9, a to f.
No, not any number, we want six of them, followed by the end of the match string.
I'm gonna test the value against that.
Right, and then to use the new matcher,
we're gonna rename this color directory to color equals hex.
Right, and so we can continue navigating between the colors, but
if we now navigate to the invalid route, it's gonna be a 404.
That does not match colors equal hex.
And so these matches, they run on the server when you're doing routing on
the server, and they also run in the client.
So you need to make sure that you're not accessing any server-side information
inside your matches.
As we saw earlier in the workshop, layouts are a way to share user interface and
data loading logic between different routes of your application.
Or sometimes it's useful to have layouts that don't affect the route.
For example, you might have a slash app and slash account routes, and
those need to be behind authentication while your slash about route page is
open to the world.
And we can do this with a thing called a route group,
which is a directory in parentheses.
So first thing we're gonna do, is we're gonna rename the account directory here to
authed/account with the authed in parentheses.
Right, and we can navigate to the account page just as we could before,
nothing has changed.
Even though we have this directory in the tree,
that's not reflected in the routing structure.
We're gonna move app into the same directory.
Again, I'm just gonna hit that Rename button and
prefix it with authed in parentheses, right, and these two things in our group,
and we can navigate to all the same routes that we could before.
But what we can do now, now that we have that route group is,
we can control access to those routes by creating a layout.server.js
inside the authed directory.
So just click on that, and then create the layout.server.js file.
And we're gonna redirect the user if we detect that they're not logged in, and
put the redirect helper from SvelteKit.
Then we're gonna export a load function.
And if the user doesn't have the logged_in cookie,
Then we're gonna throw a redirect and send them to the log in page.
But we're gonna redirect them once they do log in back to wherever we currently are.
Right, so now if we try to visit the account page or the app page,
it's gonna send us to the log in page instead.
The log in route has a form action which sets
the logged_in cookie when we press the Login button.
I'm gonna hit that.
And now I go to the account page.
We can add some UI to these two routes that's distinct from the UIs on the rest
of the app by adding a layout.svelte component inside the authed directory.
So hit that button there and create layout.svelte.
Then inside here, we're gonna create a form,
method = POST, action = logout.
And create that Logout button, followed by the slot so
that we can put the page content in.
So now if I'm on the account page or the app page, I can logout, and
I'll get kicked back out to the homepage where I don't need to be authenticated.
So that's how you create a layout group without affecting the route.
Sometimes we need to do the opposite thing,
sometimes we need to break out of layouts.
Ordinarily, every page inherits every layer above it so
that if we have a page like abc/page.svelte,
then it will inherit all of these layouts.
The route layout, the a layout, the b layout, and the c layout.
And you can see that in this exercise if we navigate between these different pages,
each of these layouts is getting applied in turn.
And sometimes it's useful to be able to break out of the current layout hierarchy.
And we can do that by adding the app sign,
followed by the name of the parents segment that we want to reset to.
So for example, if we were to change this file from +page.svelte to +page@b.svelte,
then it will put the abc route inside the b layout instead of the c layout.
So now these two routes share a layer, or we could change it to a.
And so now we go from home to a, to the b layout, back to the a layout.
Or we could reset it all the way to the top by specifying the empty string.
And so now we go home, a, b, and then back to the route layout.
Right, the route layout here, this applies to every page of your app,
you cannot break out of the route layout.
So if you have some parts of your app that shouldn't have any layout UI whatsoever,
then what you'll need to do is put every other part of your app inside
a route group.
Something like parentheses app, and then put all of your routes inside that, and
then you can use +page@ to reset all the way to the blank layout at the very top.
>> In this falcate docs regarding the data SvelteKit preload code,
hover and tap have this same description, what's their difference?
>> So the difference between hover and tap is that if a link has
the data SvelteKit preload data attribute set to hover,
then when the mouse comes to rest over that link,
SvelteKit will begin fetching the code in the data for the next page.
The assumption being that if the mouse has come to arrest over the link,
there's a very high chance that the user is about to initiate a navigation.
But if you don't want that, then you can specify tap.
And in that case, the preloading won't begin until there's a pointer down then.
That doesn't give you quite as much of a head start,
but it does reduce the number of false positives that you'll encounter.
So if you're trying to save data, then that's a good thing for you to do.
But if you're trying to maximize the speed of navigation,
then you'll want to use hover.
Obviously, hover only applies to desktop because on a mobile device,
you don't have a mouse, there are no hover events.
So in that case, it will fall back to the tap behavior in all cases.
If you do have hover set, then if for whatever reason the the hover hasn't yet
been triggered because the mouse clicks on the link while it's still
moving over the link, then it will also initiate navigation on top.
>> Is the +page@.svelte the same as +layout@.svelte?
>> Yeah, so you can apply a layout reset to your layout components
as well as to your page components if you want a whole group of routes to
be reset to an earlier layout separately, altogether, I guess.
Yeah, I hope that makes sense.
>> Is there a way to have named layouts?
>> The way that you name a layout is just by having it inside a segment.
So wherever you are in the tree,
you can refer to a layout above the route that you're currently at just by
referring to the name of the directory in which that layout is.
>> To be clear, a layout that you can refer to that isn't route-based?
>> No, because if you had something like that, then the layouts would no longer
be bound to the hierarchy and the behavior would be very difficult to reason about.
So the name of the layout is always connected to
the directory in which that layout lives.
If we started having two ways of naming layouts, then it would just add confusion,
but you wouldn't actually gain any expressive power, so we don't do that.