I have a dynamic route at the root of my pages folder in Next; like so src/pages/[page].js
This works great for anything that actually has a slug for example example.com/my-page will return the correct data for my-page.
I want to be able to access a slug named homepage when you're visiting the root of the website. So visiting example.com would actually return the page homepage.
How can this be done? Here's a stripped back version of my component:
import React from "react";
import { fetchAPI } from "../lib/api";
const Page = () => <p>Content...</p>;
export default Page;
export async function getStaticPaths() {
const pages = await fetchAPI("/pages");
return {
paths: pages.map((page) => ({
params: {
page: page.slug,
},
})),
fallback: false,
};
}
export async function getStaticProps({ params }) {
const pages = await fetchAPI(`/pages?slug=${params.page}`);
return {
props: { page: pages[0] },
revalidate: 1,
};
}
In getStaticProps, your params.page will be undefined on your home page because you're using a dynamic route there, so you just need to handle that case:
export async function getStaticProps({ params }) {
const pageSlug = params.page ?? "homepage"
const pages = await fetchAPI(`/pages?slug=${pageSlug}`);
return {
props: { page: pages[0] },
revalidate: 1,
};
}
OP - in your comment below, you said "...but if a user visited something like example.com/asdopmsaiond wouldn't it also show the homepage in this case instead of a 404". While my code above will give you the homepage slug when a user visits the home page, it seems you also want to display the home page when a user visits any page that doesn't truly exist. There are generally three ways to go about this:
You can redirect the user to the home page if no page is found by checking your pages variable - if it doesn't have a valid pages[0] value, you'll know (assuming your api is set up well) that no page was found and you can then redirect to the home page:
export async function getStaticProps({ params }) {
const pageSlug = params.page ?? "homepage"
const pages = await fetchAPI(`/pages?slug=${pageSlug}`);
if(!pages || !pages.length > 0) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: { page: pages[0] },
revalidate: 1,
};
}
I say that this is "preferred" because it will not result in SEO duplicate content penalties like the last option would, and doesn't result in any additional processing or api calls.
You can create a 404.js (or 404.tsx) file which Next uses when it needs to display a 404 page. This file also takes getStaticProps which you can use to just redirect to the home page:
// 404.js
export default function FourOhFourPage() {
return null
}
export async function getStaticProps({ params }) {
return {
redirect: {
destination: '/',
permanent: false,
},
};
}
You can also resubmit your api call with the homepage slug if no pages are found in your api call, and then display that homepage content. This would result in a second api call and you'd want to include a canonical url to your home page so you don't get hit with duplicate content penalties for SEO:
export async function getStaticProps({ params }) {
const pageSlug = params.page ?? "homepage"
// Changed `pages` from `const` to `let` so we can modify it
// if we don't get the desired result from the api call
let pages = await fetchAPI(`/pages?slug=${pageSlug}`);
if(!pages || !pages.length > 0) {
pages = await fetchAPI(`/pages?slug=homepage`);
}
return {
props: { page: pages[0] },
revalidate: 1,
};
}
You can configure rewrites in the next.config.js file to map the / path to the /homepage destination path.
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/',
destination: '/homepage'
}
];
}
};
This will not change the visible URL (/) in the address bar.