DEV Community

Bishal Neupane
Bishal Neupane

Posted on

Using getStaticProps and getStaticPaths for static site generation (ssg) in nextjs

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
      }
    }
  }
`;

Enter fullscreen mode Exit fullscreen mode

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'
    >
      &larr; go back
    </button>
  );
};

export default playlists;
Enter fullscreen mode Exit fullscreen mode

Playlist page

Image description
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
      }
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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)