How to Build a Next.js React Universal App

Tony Spiro is the Co-Founder of Cosmic JS, an API-first Content Management Platform for building content-powered apps.

Next.js is an amazing new addition to the React open-source ecosystem. It is “a minimalistic framework for universal server-rendered React applications” that makes the process of building these types of applications much faster and easier. Recently I demoed a new app on the Cosmic JS Apps page that is built using the Next.js framework. I’ve built a few React Universal apps from scratch before and I found taking the Next.js route to speed things along quite a bit. And adding content management capability from Cosmic JS to the Next.js structure was very intuitive.

In this tutorial I’m going to show you how I built the Next.js application and integrated content powered by Cosmic JS. This full app is available on the Cosmic JS Apps page for you to download, hack, install and deploy live.

Getting Started

Let’s get started by creating our app and installing next:

mkdir next.js-website
cd next.js-website
yarn add next

Creating Pages

Now lets create a new folder to hold our pages.

mkdir pages

With Next.js, any page that we add to our pages folder will be available at its corresponding url. So index.js will be available at / and about.js will be found at /about and so on. Let’s first create our index.js file. Add the following to index.js:

import React from 'react'
export default class Home extends React.Component {
render () {
return <div>Hello World</div>
}
}

Now let’s start our next server to see our page:

next

Navigate to http://localhost:3000 to see our Hello World example. Next let’s add another page to show our about page content. In a file titled about.js add:

import React from 'react'
export default class Home extends React.Component {
render () {
return <div>About me</div>
}
}

Then run next again. Now go to http://localhost:3000/about to see this page.

We could hard code the content for all of our pages, but for our purposes, let’s hook up the Cosmic JS API so we can let our team add and edit content using the Cosmic JS CMS API. For each page we want to be able to pull that specific page from the Cosmic JS API and serve the content to our Next.js application.

Adding Cosmic JS-Powered Content

First install the Cosmic JS NPM module:

yarn add cosmicjs

Then create a new folder titled models and add the following to a file titled cosmic.js:

const config = {
bucket: {
slug: 'nextjs-website' // add your bucket slug here
}
}
import Cosmic from 'cosmicjs'
export default {
getPage(slug) {
const data = new Promise(resolve => {
Cosmic.getObject(config, { slug }, (err, res) => {
resolve(res)
})
})
return data
}
}

So the purpose of this piece of code is to take whatever slug is supplied to the “getPage” function and render the Cosmic JS Object.

Dynamic Pages

Let’s create a basic page structure for all of our pages. Create a folder titled “templates” and addd the following file titled basic-page.js:

import React from 'react'
export default class BasicPage extends React.Component {
render() {
const page = this.props.page
return (
<div>
<main>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{__html: page.content}}/>
</main>
</div>
)
}
}

Next let’s edit our index.js file to include the following:

import React from 'react'
import BasicPage from '../templates/basic-page'
import Cosmic from '../models/cosmic'
export default class Home extends React.Component {
static async getInitialProps () {
return await Cosmic.getPage('home')
}
render () {
const page = this.props.object
return <BasicPage page={page}/>
}
}

Now we have created a basic page template that will render the page title and content. And in our index.js file, before rendering, the getInitialProps function will fetch the page content from the Cosmic JS API. Now for our about page, all we need to do is change the slug. about.js now looks like this:

import React from 'react'
import BasicPage from '../templates/basic-page'
import Cosmic from '../models/cosmic'
export default class Home extends React.Component {
static async getInitialProps () {
return await Cosmic.getPage('about')
}
render () {
const page = this.props.object
return <BasicPage page={page}/>
}
}

Now run the application:

next

Navigate to / and /about and notice that the Cosmic JS content comes through not only when you view source (server side) but it also renders on the client as a React Universal Application.

In Conclusion

So when creating a React universal application using the Next.js framework there was a lot of stuff I didn’t have to do: I didn’t have to set up react-router. I didn’t have to set up Flux or Redux to manage state. I didn’t have to do any server-side node.js coding. I didn’t have to do a lot (or any!) webpack configuration for hot-reloading and bundle routing. So yea, I saved a TON of time on boilerplate setup and config using the Next.js framework to accomplish my universal React needs. It really is a remarkable piece of tech and I’m looking forward to see where it will go next (no pun intended).

I hope you enjoyed this tutorial. If you have any questions about setting up your Cosmic JS-powered Next.js Universal App reach our to us in our Slack community or on Twitter.