Creating A Redirect in Astro
Get to the point. TLDR;
We needed to redirect a current URL to a different page. In our case, we wanted /agenda
to redirect to an event page. So, to explain it like you’re a five-year-old, who knows a decent amount of developer knowledge, when someone would go to website-name.com/agenda
they would actually go to website-name.com/desired-page
.
You used to be able to do this using the Astro.redirect method, but it has been deprecated as of version 2.6, unless you’re using Server Side Rendering then you’re good. If using static site generation (like we do) you can use this approach that Astro recommends using the meta refresh attribute
.
Before I get into the nuts and bolts of the post, I must admit that my attention to detail in the Astro docs was pretty lacking because I missed them suggesting the use of the meta refresh. I did, however, see this in Lloyd Atkinson’s post on his blog. In his post, Atkinson shows us how he uses the meta refresh attribute to redirect to his latest blog post. In our case, we wanted our redirect to be specific so we didn’t need to worry about some of the extra stuff Lloyd was doing.
Creating The Redirect
I decided to start in the file that I would be redirecting from. For this post, I’ll create a redirect page.
- src
- pages
- redirect
index.astro
In here, I’ll add a redirect
variable. I want to drive some more traffic to our Pets of RIMdev page so I’ll set that URL to the value of the redirect. The frontmatter looks like this:
const redirect = "/the-pets-of-rimdev"
Now that we have our redirect defined, we need to get that info to the Head.astro
component. We pass the parameters to the layout component we are using. In this case, it’s our MainLayout.astro
.
<MainLayout title={title} image={image} redirect={redirect}>
<h1>Redirects!</h1>
</MainLayout>
Let’s head to the MainLayout
and add redirect
to our props.
const { title, image, authorImage, author, imageCredit, imageUrl, url, redirect } = Astro.props;
Our Head.astro
component is used inside the MainLayout
file so we need to pass the redirect prop there as well.
<Head title={title} image={image} permalink={url} redirect={redirect} />
Inside our Head.astro
component we want to add the meta refresh tag.
<!-- redirects -->
{redirect ? (
<meta
http-equiv="refresh"
content={ `0; url=${ redirect }` }
/>
) : null}
Here we check for redirect
because not every page will have one so there’s no point to render this. The redirect is used in the content
which tells the browser what page to redirect to. Check it out here. Pretty cool.
This definitely works, but I feel like we could make it a little better. We can by using Content Collections and Dynamic Pages.
Using Dynamic Pages
We already have a dynamic page, [slug].astro
, created for our posts. This allows us to create specific slugs for our posts. We’ll use this for our redirects because we’ll want to specify slugs for these redirects. Our dynamic page lives right in our pages
folder.
src
- content
- authors
- posts
- redirects
- pages
[slug].astro
Using Content Collections, we have a content folder inside our src directory. This is where we need to create a redirects folder. We can add our files or pages for each redirect in the redirects folder. Each file will represent an individual redirect. Because we’re using the dynamic [slug]
page, we can name these .md files anything we want. This will help other devs know what the file is doing. So we can name our redirect, gotopets.md
.
<!-- gotopets.md -->
---
title: "Sample Redirect"
slug: show-me-cute-animals
redirect:
url: "/the-pets-of-rimdev"
timing: null
---
I created a redirect object in the frontmatter because I figured why not give someone the option to set the timing for the redirect. It might not always be instant or 0. In the meta tag in the head, however, it will default to 0 unless a timing function is specified. Take a look:
Head.astro
<!-- Add redirect to the list of props -->
const { title, description, image, permalink, redirect } = Astro.props;
<!-- redirects -->
{redirect ? (
<meta
http-equiv="refresh"
content={ `${ redirect.timing ? redirect.timing : '0' }; url=${ redirect.url }` }
/>
) : null}
Our dynamic [slug].astro
needs updates too.
export async function getStaticPaths() {
const entries = [
...(await getCollection('posts')),
...(await getCollection('redirects')),
];
return entries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
We need to add `redirects to the entries array. Then we’ll wrap our current Post related code checking for the posts collection. We’ll do the same thing for collections.
{
entry.collection === 'redirects' ? (
<MainLayout
title={title}
url={entry.slug}
redirect={redirect}
>
<div class="container" data-pagefind-body>
<article>
<Content />
</article>
</div>
</MainLayout>
) : null
}
Wanna see how it works? So you can see how it works, I’ll add a timing param of 5 seconds. Check this out show-me-cute-animals.