β‡  chan.dev / posts

Rest parameter dynamic routes

🌱 This post is in the growth phase. It may still be useful as it grows up.

I find getStaticPaths() confusing. These examples help me make sense of it.

Rest paramaters match infinitely segments

A file named [...thing].astro (placed in the root) will match all of these paths:

βœ… /
βœ… /thing
βœ… /doesnt-have-to-be-thing
βœ… /nested/thing
βœ… /nested/anything
βœ… /deeply/nested/thing
βœ… /you/get/the/idea/nested/deeply/thing

Nesting in statically named directories

When nested in a static directory (nested, not [nested]), the rest parameter file matches infinitely nested paths inside that subdirectory path.

⛔️ /
⛔️ /thing
⛔️ /doesnt-have-to-be-thing
βœ… /nested/thing
βœ… /nested/anything
βœ… /nested/deeply/thing
⛔️️ /you/get/the/idea/nested/deeply/thing

Nesting in dynamically named directories

When nested in a dynamic directory ([nested], not nested), the rest parameter file matches infinitely nested paths for any subdirectory path.

⛔️ /
⛔️ /thing
⛔️ /doesnt-have-to-be-thing
βœ… /nested/thing
βœ… /nested/anything
βœ… /nested/deeply/thing
βœ… /you/get/the/idea/nested/deeply/thing

But this only works for pages that getStaticPaths() has generated a first segment for. In the example above, the first segments are /nested and /you.

To match all the paths above, the resulting getStaticPaths() needs to look like this:

;[
{params: {nested: 'nested', thing: 'thing'}},
{params: {nested: 'nested', thing: 'anything'}},
{params: {nested: 'nested', thing: 'deepy/thing'}},
{
params: {
nested: 'you',
thing: 'get/the/idea/nested/deeply/thing',
},
},
]

Note how the entire unmatched path is passed as thing.

Mix static and dynamic

Dynamic and static routes can be mixed and matched. I love this example from the Astro docs.

// `/[org]/[repo]/tree/[branch]/[...file]`
;[
{
org: 'withastro',
repo: 'astro',
branch: 'main',
file: 'docs/public/favicon.svg',
},
{
org: 'chantastic',
repo: 'sites',
branch: 'main',
file: 'chan.dev',
},
]

Keep rest parameters at the end of a path

Just like rest paramaters in JavaScript, limit yourself to one per path, and keep them at the end of discrete file trees.

Weird things happen you attempt two dynamic filenames with rest parameters.

You can fork a path, one dynamic the other static

Dynamic routes don’t have to exhaustive. You can waste a lot of good effort trying to make your dynamic routes inclusive of your url paths. Many times you can just add more static paths, or fork dynamic paths.

pages/
β”œβ”€ [dynamic_collection]
β”‚ β”œβ”€ [...dynamic_resource].astro
β”œβ”€ static_collection
β”‚ β”œβ”€ static_resource.astro
β”œβ”€ [different_param]
β”œβ”€ static_page_with_links_to_both_static_and_dynamic_pages

This is the file structure I use to render the lessons, lesson collections, and collection years on this site.

pages/lessons/
β”œβ”€ [...lesson_slug].astro
β”œβ”€ [year].astro
β”œβ”€ [collections].astro
β”œβ”€ [collection].astro
β”‚ β”œβ”€ [year].astro