Next.js Quick start guide

Estimated duration: 10 minutes

This guide shows you how to connect Prepr to a Next.js project to get data from Prepr CMS. You'll learn how to make a simple blog with Next.js and Prepr CMS. By the end of this guide, you'll have a working app that looks like the image below.

Next.js QSG end result

If you want to skip ahead, try out the zero installation demo on Stackblitz (opens in a new tab) or clone the repository on GitHub (opens in a new tab) to run the demo locally. These resources and the steps below are based on the latest version of Next.js.

Prerequisites

You need to have the following setup before you connect your Next.js project to Prepr.

Create a simple Blog website with Next.js and Prepr CMS

Create a new Next.js project

The instructions below show you how to create an empty Next.js project for your blog app. You can skip this step if you have an existing Next.js project.

  1. Open a terminal, go to your development projects folder and execute the following command to create a new Next.js project called prepr-next:

    npx create-next-app@latest prepr-next

    Mark the options (Y or N) as shown in the image below to create the same project structure used in this guide.

    default options

    In this guide, we've chosen JavaScript instead of TypeScript. For more details on using TypeScript, check out the Next.js complete guide.

  2. Now that the project is successfully created, go to the prepr-next folder, the root directory of the project, and run the project with the following commands in the terminal:

    cd prepr-next
    npm run dev
  3. You should now be able to view your app on your localhost, for example, http://localhost:3000/.

  4. Open your project with your preferred code editor.

  5. Go to the src/app folder and replace the code in the page.js file with the following code to display your blog:

    ./src/app/page.js
    export default async function Home() {
      return (
        <div>
          <h1>My blog site</h1>
        </div>
      );
    }
  6. Go to the layout.js file in the src/app folder and replace the default code with the simplified layout below.

    ./src/app/layout.js
    export const metadata = {
      title: 'My blog site',
      description: 'A simple blog app project',
    }
     
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>{children}</body>
        </html>
      )
    }
  7. Empty the globals.css file in the app folder to remove the existing formatting.

You should now see something like the image below on your localhost.

My blog site

Install the Apollo client

The Apollo client is an integration tool that helps to retrieve CMS data with GraphQL. The instructions below show you how to install the Apollo client so that you can add GraphQL queries to request data from the Prepr API.

  1. Stop the server you started in the above step (CTRL-C) and execute the following command in the terminal:

    npm install @apollo/client graphql
  2. In the src directory of the project, create a file called apollo-client.js. Copy the following code to this file to import and initialize the Apollo client:

    ./src/apollo-client.js
    import { ApolloClient, InMemoryCache } from "@apollo/client";
     
    const client = new ApolloClient({
        uri: `https://graphql.prepr.io/${process.env.PREPR_ACCESS_TOKEN}`,
        cache: new InMemoryCache(),
    });
     
    export default client;

    This client will be used to make API requests to endpoints provided by the Prepr CMS across your Next application.

  3. We recommend using environment variables to store sensitive information like access tokens. To add environment variables, create a .env file in the root directory of your project and add the access token like this:

    ./.env
    PREPR_ACCESS_TOKEN=<YOUR-ACCESS-TOKEN>
  4. Replace the placeholder value <YOUR-ACCESS-TOKEN> with an access token from Prepr. Get an access token by logging into your Prepr account:
    a. Go to Settings → Access tokens to view all the access tokens.
    b. Click to open the GraphQL Production access token and use this value to only retrieve published content items on your site.

    access token

    Use the GraphQL Production access token to request published content items for your live app and use the GraphQL Preview token to make a preview of unpublished content items for your content editors.

  5. Execute the following command to restart the server and to make sure that the Apollo client is installed correctly:

    npm run dev

If your app runs without errors, then the setup above was done correctly. The next step is to fetch content from Prepr using the installed Apollo client.

Troubleshooting
Build error: Failed to compile - Module not found: Can't resolve '@apollo-client'
Cause: The path to the src folder has not been defined.
Solution: Make sure your jsconfig.json has the following path defined:

jsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Once done, go back to the beginning of this step and reinstall the Apollo client

Fetch multiple blog posts

Now that your Apollo client is installed and connected to Prepr, fetch the blog posts from Prepr.

Add a GraphQL query

  1. Create a queries folder in the src directory of your project and create a file named get-posts.js.

  2. Add the following query to this file to retrieve all blog posts:

    ./src/queries/get-posts.js
    import { gql } from "@apollo/client";
     
    export const GetPosts = gql`
        query {
            Posts {
                items {
                    _id
                    _slug
                    title
                }
            }
        }
    `

    You can create and test GraphQL queries using the Apollo explorer (opens in a new tab) from Prepr. Open the API Explorer directly in Prepr from a specific Post content item or the access token details.

If you’re using preloaded demo data in your Prepr CMS environment as mentioned above in the Prerequisites section, you should have a few published blog posts as shown in the below image. The query retrieves the ID, Slug, and Title of each blog post.

demo blog posts

In the next step, we'll fetch and process the query response.

Fetch data

Now that the query has been added, fetch the blog posts from Prepr and display them in the app.

  1. Open the page.js file in the app folder and replace the content with the code below to display the data retrieved from the query.

    For different rendering and caching options, check out the Next.js docs (opens in a new tab) for more details.

    ./src/app/page.js
    import { GetPosts } from "@/queries/get-posts";
    import client from "@/apollo-client";
     
    import Link from "next/link";
     
    export const revalidate = 0;
     
    async function getData() {
      // Execute the query and return the results
      const {data} = await client.query({
        query: GetPosts,
      });
      return data.Posts.items;
    }
     
    export default async function Home() {
      const posts = await getData();
     
      return (
        <div>
          <h1>My blog site</h1>
          <ul>
            {posts.map((post) => (
     
              //List the fetched blog posts
              <li key={post._id}>
                <Link href={post._slug}>{post.title}</Link>
              </li>
            ))}
          </ul>
        </div>
      );
    }

Now when you view the website on your localhost, you'll see something like the image below.

List of blog posts

Fetch each blog post

Now you have the list of blog posts with links to them. When a visitor clicks a blog post link, your app should open a detailed post page automatically. However, we haven't created the detailed page yet. Now, when you click the link, a new page opens with the slug in the URL, but a Page 404 error is displayed.

The instructions below show you how to set up the routing from the main page to the detailed page and how to fetch the blog post details based on the slug of the blog post that was clicked.

  1. Create a file called get-post-by-slug.js in the queries folder and add the following to query a specific post by its slug:

    ./src/queries/get-post-by-slug.js
    import { gql } from "@apollo/client";
     
    export const GetPostBySlug = gql`
        query ($slug: String) {
            Post (slug: $slug) {
                _id
                title
                cover {
                    url(width: 300, height: 250)
                }
                content {
                    __typename
                    ... on Text {
                        _id
                        body
                        text
                    }
                    ... on Assets {
                        items {
                            _id
                            url(width: 300, height: 250)
                        }
                    }
                }
            }
        }
    `

    Now that the query is added, fetch the individual post by its slug. Fetch the title, the cover image and the post content.

    The Post content is stored in a Dynamic content field. Check out the GraphQL docs for more details on how to fetch the data within this field.

  2. Go to the the src/app folder and create a new folder called [slug]. Create a new page.js in this folder and add the code below to fetch a specific blog post by its slug and display the post details.

    ./src/app/[slug]/page.js
    import client from "@/apollo-client";
    import {GetPostBySlug} from "@/queries/get-post-by-slug";
     
    export const revalidate = 0;
     
    async function getData(slug) {
      const {data} = await client.query({
        query: GetPostBySlug,
        variables: {
          slug
        }
      })
     
      return data.Post
    }
     
    export default async function PostPage(props) {
      const params = await props.params;
      const {slug} = params;
      const post = await getData(slug);
     
     
      return (
          <>
            <h1>
              {post?.title}
            </h1>
     
            <div className="my-10" key={post?.cover.url}>
              <img
                  src={post?.cover.url}
              />
            </div>
     
            {/* Loop through content types in post content */}
     
            {post?.content.map((contentType) => {
     
              //Display image if it exists
              if (contentType.__typename === 'Assets' && contentType.items.length) {
                return (
                    <div className="my-10" key={contentType.items[0]?._id}>
                      <img
                          src={contentType.items[0]?.url}
                      />
                    </div>
                )
              }
     
              //Display text as HTML
     
              if (contentType.__typename === 'Text') {
     
                return (
                    <div key={contentType._id} dangerouslySetInnerHTML={{__html: contentType.body}}></div>
                )
              }
            })}
          </>
      )
    }

Now, when you view your site, you can click a blog post which will direct you to that specific post like in the image below.

blog post detail

Troubleshooting
Error: Page 404 after clicking the blog post link.
Cause: The app cannot find the detailed blog post page.
Solution: Make sure your detailed page.js is in the correct folder: srcapp[slug]

All done

Congratulations! You have successfully connected a Next project to Prepr for a simple Blog app.

Next steps

To learn more on how to expand your project, check out the following resources:

Last updated on

Was this article helpful?

We’d love to learn from your feedback