Skip to content

Edvins Antonovs

Building dynamic routes in Next.js with Supabase

In this tutorial, we'll explore how to implement dynamic routes in a Next.js app using Supabase for data fetching. Specifically, we'll create a dynamic route for individual blog posts and a directory listing all blog posts. Code snippets will work with Next.js Pages Router (not App Router), but you can adapt them to work with App Router if needed.


Setting up the dynamic route

Create a dynamic route to fetch specific blog post data based on the blog ID.

  1. Inside the pages/blog directory, create a file named [id].jsx (dynamic route).
pages/blog/[id].jsx
1import { useRouter } from 'next/router';
2import { supabase } from '../../lib/supabase';
3
4export default function BlogPage({ blog }) {
5 const router = useRouter();
6
7 if (router.isFallback) {
8 return <div>Loading...</div>;
9 }
10
11 return (
12 <div>
13 <h1>{blog.title}</h1>
14 <p>{blog.content}</p>
15 </div>
16 );
17}
18
19export async function getStaticPaths() {
20 const { data, error } = await supabase.from('blogs').select('id');
21
22 if (error) {
23 console.error('Error fetching blog IDs:', error.message);
24 return {
25 paths: [],
26 fallback: true,
27 };
28 }
29
30 const paths = data.map((blog) => ({
31 params: { id: blog.id.toString() },
32 }));
33
34 return {
35 paths,
36 fallback: true,
37 };
38}
39
40export async function getStaticProps({ params }) {
41 const { id } = params;
42 const { data: blog, error } = await supabase
43 .from('blogs')
44 .select()
45 .eq('id', id)
46 .single();
47
48 if (error) {
49 console.error('Error fetching blog data:', error.message);
50
51 return {
52 notFound: true,
53 };
54 }
55
56 return {
57 props: {
58 blog,
59 },
60 revalidate: 60, // Revalidate the page at most once every 60 seconds
61 };
62}

Here, revalidate: 60 ensures that the blog post page will be regenerated in the background if a request is made 60 seconds after the last regeneration. This allows the blog post content to stay relatively up-to-date without needing to rebuild the entire application frequently.

  1. Ensure you have a Supabase client set up. Create a supabase.js file in the lib directory and update it with your Supabase URL and anon key.
lib/supabase.js
1import { createClient } from '@supabase/supabase-js';
2
3const supabaseUrl = 'YOUR_SUPABASE_URL';
4const supabaseKey = 'YOUR_SUPABASE_ANON_KEY';
5
6export const supabase = createClient(supabaseUrl, supabaseKey);

Creating a blogs directory

Create a page to list all blogs, linking to their respective dynamic routes.

  1. Create an index.jsx file inside the pages/blogs directory.
pages/blogs/index.jsx
1import Link from 'next/link';
2import { supabase } from '../../lib/supabase';
3
4export default function BlogsPage({ blogs }) {
5 return (
6 <div>
7 <h1>All Blogs</h1>
8 <ul>
9 {blogs.map((blog) => (
10 <li key={blog.id}>
11 <Link href={`/blog/${blog.id}`}>
12 <a>{blog.title}</a>
13 </Link>
14 </li>
15 ))}
16 </ul>
17 </div>
18 );
19}
20
21export async function getStaticProps() {
22 const { data: blogs, error } = await supabase.from('blogs').select('*');
23
24 if (error) {
25 console.error('Error fetching blogs:', error.message);
26
27 return {
28 notFound: true,
29 };
30 }
31
32 return {
33 props: {
34 blogs,
35 },
36 revalidate: 60, // Revalidate the page at most once every 60 seconds
37 };
38}

With these steps, you now have a Next.js app with dynamic routing powered by Supabase. You can navigate to /blogs to see a directory of all blogs, and each blog link will take you to a dynamically generated page with the blog's details.

This setup allows for efficient and scalable data fetching and rendering in your Next.js applications. I personally use it for one of my side projects, and it works like a charm.

© 2024 by Edvins Antonovs. All rights reserved.