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.
Installing the prismic-cli
command line tool.
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 documentspackage.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.
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.
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.
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:
version
ensures you are using the latest Now 2.0 platform versionbuilds
instructs Now to use the@now/next
Builder to build your approutes
routes slug based requests to the correct location with theid
parameter
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.