Create a Next.js and Storyblok App That Builds and Deploys with ZEIT Now
Use Storyblok as a Headless CMS to power content for your Next.js app deployed with ZEIT Now.
In this guide, you will discover how to create a Next.js app that displays links to posts from the ZEIT blog by utilizing the Storyblok headless CMS, before deploying with a single command to ZEIT Now.
Next.js from ZEIT is a production-ready framework that helps you create fast React apps. Storyblok is a headless CMS with a visual editor, block system, custom field types and localization built in.
By following this guide, you will create a clone of the example app, a starting point to get you up and running with your own Next.js + Storyblok app in minutes.
Step 1: Create your Storyblok Content
From your Content Dashboard, create a new Entry with a Content type of Post by clicking the + Entry button.
After completing the details in the modal, click Create, this will take you to a new view. Now, click the Define schema button, you should see the following in the sidebar:
Add the following fields to your Post Schema, by typing in the input and clicking the + Add button:
title
date
alt
image
url
Your Post Schema should look like this:
Next, click the arrow back at the top left of the page to return to the Content dashboard. Then, click + Entry once more, this time choosing your Post Schema as the Content Type.
All that's required is to add the content where requested, then click Save at the top right of the screen followed by Publish for each post you wish to add.
That's it for creating content! You can edit both the Post and Post Schema at any time, giving you complete flexibility over your content.
At this point, return back to your Content Dashboard and click Settings from the sidebar on the left. Select the API-Keys tab and create a new Public key, you should make a note of this so it can be used later.
Step 2: Creating your Next.js App
Firstly, create a project directory and cd
into it like so:
mkdir my-nextjs-storyblok-project && cd my-nextjs-storyblok-project
Next, initialize your project, creating a package.json
file in the process:
npm init -y
Next, add the project dependencies:
npm i next react react-dom
With the project initialized, create a /pages
directory with a index.js
file inside that uses the following code:
import { useEffect, useState } from 'react' import Head from 'next/head' import Post from '../components/post' function HomePage() { const [posts, setPosts] = useState([]) useEffect(() => { async function getPosts() { const res = await fetch( `https://api.storyblok.com/v1/cdn/stories?token=${ process.env.API_TOKEN }` ) const { stories } = await res.json() setPosts([...stories]) } getPosts() }, []) return ( <> <Head> <title>Next.js + Storyblok</title> <link rel="stylesheet" href="https://css.zeit.sh/v1.css" type="text/css" /> </Head> {posts.length > 0 ? posts.map(p => ( <Post alt={p.content.alt} date={p.content.date} key={p.content.title} image={p.content.image} title={p.content.title} url={p.content.url} /> )) : null} </> ) } export default HomePage
Let's take look at what this file achieves.
Inside the useEffect
hook, an asynchronous function, getPosts
, is defined, this is then called in the useEffect
hook to retrieve the posts on initial load.
With the posts retrieved, they are then mapped over to be displayed with a <Post>
component that you will create next.
Create a /components
directory that contains a post.js
file with the following content:
function Post({ alt, date, image, title, url }) { return ( <div className="container"> <a href={url}> <img alt={alt} src={image} /> </a> <div className="text"> <h2>{title}</h2> <h4>{date}</h4> </div> <style jsx>{` .container { cursor: pointer; height: 453px; margin-bottom: 48px; } a { border-bottom: none; } a:hover { border-bottom: none; } .text { margin-top: -160px; padding: 24px; position: absolute; } h2 { color: white; font-size: 24px; margin-bottom: 0; } h4 { color: rgba(255, 255, 255, 0.8); font-size: 16px; font-weight: 500; margin-top: 8px; } `}</style> </div> ) } export default Post
Now that your page and component files have been created, the next step will show you how to add an environment variable to the project.
Step 3: Adding an Environment Variable
Add a now.json
file at the root of your project directory with the following code:
{ "build": { "env": { "STORYBLOK_API_TOKEN": "@storyblok_api_token" } } }
With your now.json
file created, you should add a next.config.js
file at the root of your project directory with the code below:
module.exports = { env: { API_TOKEN: process.env.STORYBLOK_API_TOKEN } }
The next.config.js
file provides access to environment variables inside your Next.js app.
Now, add the following build script to your package.json
file:
{ ... "scripts": { "build": "next build" } }
Next, you will make your API keys available to your app during local development by creating a .env.build
file.
Create a .env.build
file at the root of your project directory with the following code, adding your API keys where instructed:
STORYBLOK_API_TOKEN=your-api-token
Lastly, to make your API key available for cloud deployment, create a Now Secret with the command below:
now secrets add STORYBLOK_API_TOKEN your-space-id
With those steps out the way you are now able to run your app. You can develop your app locally using the following command:
next dev
Step 4: Deploying the App
With your app ready, it is time to deploy it using a single command:
now
You will see a short build step in your terminal followed by the news that your project has been deployed, it should look similar to the example app.