Dynamic Page with Sanity + Next.js

#Sanity
#Next.js

[slug].js
import React from 'react';

//You need to use the Portable Text in React plugin from Sanity
import BlockContent from "@sanity/block-content-to-react";

//This code uses the Next-Sanity package and refer to its documentation to get this set up
import { groq } from "next-sanity";
import { getClient } from "../../lib/sanity.server";
import { urlFor } from "../../lib/sanity";
import { config } from "../../lib/config";

export default function Post(props) {
  
  //These variables are just whatever you wanted to get from the document you queried on Sanity
  const {
    body,
    title, 
    image,
  } = props;

  return (
    <div>
    <h1>{title}</h1>
    {/**Use portable text to render Sanity content from rich text editor */}
    <BlockContent
      className=""
      blocks={body}
      imageOptions={{ w: 320, h: 240, fit: "max" }}
      {...config}
            />
    </div>
  );
}


//This GROQ query is a post document, add whatever items you want to query
const query = groq`*[_type == "post" && slug.current == $slug][0]{
  title,
  body,
  image
  }`;

export async function getStaticProps({ params, preview = false }) {
  const slug = await getClient().fetch(query, {
    slug: params.slug,
  });

  return {
    props: slug,
  };
}

export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const posts = await getClient().fetch(groq`*[_type=="post"]{
    slug
  }`);

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { slug: post.slug.current },
  }));

  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false };
}

For this code to work, you should configure and install the following packages and plugins: