Create and Deploy a Next.js and Prismic Application with Now

Creating a Next.js project with Prismic as a content source and deploying to Now

In this guide, you will create a Next.js blog site from scratch that will show you how to; source the content you have in a Prismic repository, create pages programmatically, handle dynamic routing, and deploy it with Now.

Next.js from ZEIT is a production-ready framework that helps you create fast React applications. Prismic is a Headless Content Management System that helps developers and content managers to work on websites and apps together.

Step 1: Set Up Your Prismic + Next.js App

For this guide, you will start with installing a boilerplate Next.js project that uses Prismic. Start with installing the Prismic CLI package, followed by quick-starting your project from the provided git repo.

This process clones the codebase and guides you through setting up the repository that will be used as your blog's content source.

yarn global add prismic-cli

Installing the prismic-cli command line tool.

prismic theme https://github.com/raulg/prismic-next-blog

Quickstarting your Prismic boilerplate project.

Navigate to the folder you have created and inspect the files and folders that are included in this barebones project. You will find the following:

  • /custom_types, which details the data modeling for your Prismic repository, in this case the blog_home and post documents
  • package.json, which includes the Next.js and React dependencies, as well as scripts to develop and deploy for Now

You can run your application with the yarn dev command, and check at localhost:3000 that the app is running correctly.

You will notice that for now it is only a simple index page, as defined in /pages. This takes care of getting your simple Next.js app started, you can now begin setting up your Prismic repository.

Continue by installing the required packages to integrate your Next.js web application with Prismic.

yarn add prismic-javascript prismic-reactjs

Adding the prismic-javascript and prismic-reactjs dependencies to fetch and render documents.

If you open the prismic-configuration.js file, you might notice that the API endpoint has already been set up according to the repository you created during the installation process.

Confirm the name of the repository so you can access the Prismic dashboard to manage your content. Move into the Prismic repository that you started earlier, and create some content that you will use in your project.

Just a simple blog home page and a couple of posts will do for now, but you can get as creative as you wish to.

Note: In this case, you will be using a rich text field that will serve as the body of the post, for the sake of simplicity. Normally, the body of a document would be a group of Slices to allow more flexibility when creating your posts.

Step 2: Sourcing Your Content From Prismic

With the relevant Prismic dependencies installed, you can start building a page that will serve as a blog index. /pages/index.js will have a component that will get the blog_home document with getInitialProps and render it's Rich Text fields.

import React from 'react'
import Prismic from 'prismic-javascript'
import { RichText, Date } from 'prismic-reactjs'
import { client } from '../prismic-configuration'

const BlogHome = props => (
  <div>
    <img src={props.home.data.image.url} alt="avatar image" />
    <h1>{RichText.asText(props.home.data.headline)}</h1>
    <p>{RichText.asText(props.home.data.description)}</p>
  </div>
)

BlogHome.getInitialProps = async context => {
  const home = await client.getSingle('blog_home')

  return { home }
}

export default BlogHome

An example /pages/index.js file fetching the author data from blog_home.

The home prop now contains the document object received from the API, including the data fields you set earlier for the blog author's image, title, and short description.

Note: If you run the app now with yarn dev, you will see this information displayed at localhost:3000.

There are many ways to query the API to get the data you require. For now, use a Predicate to get all the post documents you have created and sort them in descending order based on their assigned date.

const BlogHome = props => (
  <div>
    <img src={props.home.data.image.url} alt="avatar image" />
    <h1>{RichText.asText(props.home.data.headline)}</h1>
    <p>{RichText.asText(props.home.data.description)}</p>

    <ul>
      {props.posts.results.map(post => (
        <li key={post.uid}>{RichText.render(post.data.title)}</li>
      ))}
    </ul>
  </div>
)

BlogHome.getInitialProps = async context => {
  const home = await client.getSingle('blog_home')
  const posts = await client.query(
    Prismic.Predicates.at('document.type', 'post'),
    { orderings: '[my.post.date desc]' }
  )

  return { home, posts }
}

export default BlogHome

An example /pages/index.js file that displays a list of all blog posts.

The posts prop contains an array of all the blog posts in your repository, arranged in descending chronological order. The title field of each item is rendered in an unordered list.

That's it for a minimalist blog home page. Let's move on to rendering the pages for each of your blog posts.

Step 3: Rendering Dynamic Posts

To create a page for each blog post document, you will set it up so that the page is generated dynamically using the unique individual slug (UID) that identifies each post document.

This approach is very similar to that used with the home page, but the API query in getInitialProps will instead fetch the document depending on its UID.

import React from 'react'
import { RichText, Date } from 'prismic-reactjs'
import { client } from '../prismic-configuration'
import Link from 'next/link'

const Post = props => (
  <div>
    <Link href="/">
      <a>back to blog list</a>
    </Link>
    {RichText.render(props.post.data.title)}
    <span>{Date(props.post.data.date).toString()}</span>
    {RichText.render(props.post.data.post_body)}
  </div>
)

Post.getInitialProps = async context => {
  const { uid } = context.query
  const post = await client.getByUID('post', uid)

  return { post }
}

export default Post

An example /pages/post.js file that generates pages depending on the UID provided by the context.

Your blog posts are rendered, but there's no way to test them out since there's no easy way to navigate to each one currently. For that, you'll have to setup custom routing by creating a now.json file.

{
  "version": 2,
  "builds": [{ "src": "package.json", "use": "@now/next" }],
  "routes": [{ "src": "/blog/(?<uid>[^/]+)$", "dest": "/post?uid=$uid" }]
}

An example now.json file with build and routing configuration.

The above now.json file achieves three things:

With this, you can access each post directly with their UID slug. For example, a blog post with the UID slug best-foot-forward will be accessible in your local environment after you relaunch it with yarn dev at the address http://localhost:3000/blog/best-foot-forward.

Step 4: Build Client Side Navigation Links

Now that the pages for your blog post documents are accessible, you can modify the index page so that the list of titles actually links to each of the posts. To do this, it's best to use the <Link> component, included with Next.js, to provide client-side navigation without a page refresh.

The <Link> component requires two main props for navigation: href, which will be the path used to route to the page, and as, which will be the path as rendered in the browser. To aid in creating these two different paths, you can use the linkResolver and hrefResolver helper functions, defined within prismic-configuration.js.

// Manages links to internal Prismic documents
linkResolver: function (doc) {
  if (doc.type === 'post') {
    return `/blog/${doc.uid}`
  }
  return '/'
},
// Additional helper function for Next/Link components
hrefResolver: function (doc) {
  if (doc.type === 'post') {
    return `/post?uid=${doc.uid}`
  }
  return '/'
}

Helper functions in the prismic-configuration.js file.

These helper functions generate both the aesthetic path with linkResolver; and the functional path that will correctly pass the UID with hrefResolver.

These will need to be modified along with your project as your routing expands, so that they always reflect the routing you have set up in your now.json file.

You can adjust the unordered list in /pages/index.js so that it wraps a <Link> around the title, as well as adding the Date value for each of the blog posts.

+ import { client, linkResolver, hrefResolver } from '../prismic-configuration'
+ import Link from 'next/link'

const BlogHome = (props) => (
  <div>
    <img src={props.home.data.image.url} alt='avatar image' />
    <h1>{RichText.asText(props.home.data.headline)}</h1>
    <p>{RichText.asText(props.home.data.description)}</p>

    <ul>
      {props.posts.results.map((post) => (
        <li key={post.uid}>
-         {RichText.render(post.data.title)}
+         <Link href={hrefResolver(post)} as={linkResolver(post)} passHref prefetch>
+           <a>{RichText.render(post.data.title)}</a>
+         </Link>
+         <span>{Date(post.data.date).toString()}</span>
        </li>
      ))}
    </ul>
  </div>
)

Modifying the /pages/index.js file to add the blog posts link list.

You can now refresh your site at localhost:3000 and test out the navigation for your blog. It's quite minimalistic, but you've built it from scratch.

Step 5: Deploying With Now

So far, you have been using yarn dev to develop locally, but what good is a blog if you don't show it off to the world. It's time to deploy it to the Now platform and enjoy your serverless web application.

Edit the now.json configuration file to include a project name. This is optional, but it helps to have human-readable addresses when sharing your project with the public.

{
  ...
  "name": "mini-blog",
}

Adding a name property to your now.json file.

You can run yarn deploy to launch the Now CLI which will quickly setup and deploy your project online. Once it's done, you can check the generated url.

Your minimalistic blog using Prismic and built with Next.js is now online on Now and can be shared instantly using the URL given by the Now CLI.

Bonus: Serverless Pre-Rendering

For increased performance, you can take advantage of the Serverless Pre-rendering feature to serve your dynamic content with static speeds.

All you need to do is add a couple of lines to your index.js and post.js files in the getInitialProps method.

if (context.res) {
  context.res.setHeader('Cache-Control', 's-maxage=1, stale-while-revalidate')
}

Enabling SPR in your BlogHome.getInitialProps and Post.getInitialProps functions.

Deploy this new version to Now with yarn deploy. You minimal blog is now being served even faster thanks to the Now Smart CDN. You can try adding or modifying content in your Prismic repository and it will be served instantaneously on your now public site.

This small guide goes over the basics of setting up a Prismic + Next.js project. You can build much more complex web applications that will be served at blazing fast speeds for users all around the globe by reading the resources below.

Resources

For more information, consult the documentation about working with Next and Prismic.



Written By
Written by raulgraulg
on June 26th 2019