This is the sixth blog post on the series of blog post I am posting about strapi,nextjs, and tailwind. We are recreating my portfolio/blogpost page that along the way we'll learn the fundamentals of strapi,nextjs, and tailwind. You can check it out at myportfolio If you know the basics of javascript and react then you should be good to follow this blog post and coming blog post on the series. I hope you'll get something out of this series.
If you've not gone through the previous blog posts then make sure to check them out
In this blog post, we're going to build two pages in our blog/portfolio site
- Playlists - This will show all the playlists along with recent three blogs
- Playlist - This will show all the posts on a particular playlist. We'll use dynamic SSG for this page
Playlists page
So let's first build the playlists page for that let's write the query which will fetch the required data
import { gql } from 'graphql-request';
export const playlistsQuery = gql`
query Playlists {
playlists {
title
description
id
slug
posts(sort: "updated_at:desc", limit: 3) {
updated_at
title
slug
description
topics
}
}
}
`;
Create a file playlists.tsx inside the pages and add the following code
import { request } from 'graphql-request';
import { useRouter } from 'next/dist/client/router';
import React from 'react';
import Link from 'next/link';
import { BlogCard } from '../components/BlogCard';
import { PlaylistsQuery } from '../gql/graphql';
import { playlistsQuery } from '../queries/playlists';
export const getStaticProps = async () => {
const data: PlaylistsQuery = await request(
'http://localhost:1337/graphql',
playlistsQuery
);
return { props: data };
};
function playlists({ playlists }: PlaylistsQuery) {
return (
<div className='p-2 container sm:mx-auto'>
<GobackButton />
<main>
<div className='space-y-2'>
<h1 className='text-4xl'>Welcome to Blog playlist</h1>
<h4 className='text-md text-gray-500'>
A playlist is series of blogpost where I write about particular tool
or subject
</h4>
</div>
<div className='my-10'>
{playlists?.map((playlist) => (
<div className='my-10' key={playlist?.id}>
<Link href={`/playlist/${playlist?.slug}`} passHref>
<h3 className='hover:underline cursor-pointer text-3xl capitalize'>
{playlist?.title}
</h3>
</Link>
<div className='md:grid md:grid-cols-2 md:gap-3 xl:grid-cols-3'>
{playlist?.posts?.map((post) => (
<div key={post?.slug} className='my-2 mx-2 h-full'>
<BlogCard
slug={post?.slug!}
title={post?.title!}
description={post?.description!}
topics={post?.topics!}
updated_at={post?.updated_at!}
/>
</div>
))}
</div>
</div>
))}
</div>
</main>
</div>
);
}
export const GobackButton = () => {
const router = useRouter();
return (
<button
onClick={() => router.back()}
className='text-green-500 hover:bg-gray-200 rounded-md p-2'
>
← go back
</button>
);
};
export default playlists;
Playlist page
We'll require two different queries first one to just get the slugs for different playlist page and the second one for the actual data.
import { gql } from 'graphql-request';
export const playlistPathsQuery = gql`
query PlaylistPaths {
playlists {
slug
}
}
`;
export const playlistQuery = gql`
query Playlist($slug: String!) {
playlists(where: { slug: $slug }) {
title
description
slug
posts(sort: "updated_at:desc") {
id
updated_at
title
slug
description
topics
}
}
}
`;
We'll use the first query to dynamically build the pages and the second one for the actual data that we need
So go ahead and create a folder inside the pages directory and name it playlist and inside the folder create [slug].tsx file
//[slug].tsx file
import request from 'graphql-request';
import { GetStaticProps } from 'next';
import { BlogCard } from '../../components/BlogCard';
import {
PlaylistPathsQuery,
PlaylistQuery,
PlaylistsQuery,
} from '../../gql/graphql';
import { playlistPathsQuery, playlistQuery } from '../../queries/playlist';
import { GobackButton } from '../playlists';
export async function getStaticPaths() {
const paths: PlaylistPathsQuery = await request(
'http://localhost:1337/graphql',
playlistPathsQuery
);
const pathFormat: any = [];
paths.playlists?.forEach((path) =>
pathFormat.push({ params: { slug: path?.slug } })
);
return {
paths: pathFormat,
fallback: false,
};
}
export const getStaticProps: GetStaticProps = async (context) => {
const posts: PlaylistQuery = await request(
'http://localhost:1337/graphql',
playlistQuery,
{
slug: context?.params?.slug,
}
);
return {
props: posts,
};
};
function Playlist({ playlists }: PlaylistsQuery) {
console.log(playlists);
const playlist = playlists![0];
return (
<div className='p-2'>
<GobackButton />
<div className='space-y-2'>
<h1 className='text-4xl capitalize'>{playlist?.title}</h1>
<h3 className='text-gray-500'>{playlist?.description}</h3>
</div>
<div className='space-y-2 md:grid md:grid-cols-2 md:gap-4 md:items-center xl:grid-cols-3'>
{playlist?.posts?.map((post) => (
<BlogCard
key={post?.slug!}
title={post?.title!}
description={post?.description!}
updated_at={post?.updated_at!}
topics={post?.topics!}
slug={post?.slug!}
/>
))}
</div>
</div>
);
}
export default Playlist;
And that is it about Using getStaticProps and getStaticPaths for static site generation (SSG) in nextjs. In another blog post, we'll create the actual blog page. If you have any problem with this code and then let me know in the discussion.
Top comments (0)