Next.js Logo

Next.js Blog Engine

You've got better things to do than build another blog

Add Butter to your Next.js app and get back to more interesting problems

Try ButterCMS free

ButterCMS is an API-based Next.js blog engine that integrates seamlessly with new and existing Next.js apps. Add ButterCMS to your Next.js app in minutes using our Node.js API client. Use ButterCMS with Next.js to enable dynamic content in your apps for blogs, pages, and more.

Above is quick video of integrating Butter's blog engine into an application.

Butter's Blog API slides right into our apps and helps avoid having yet another WordPress site.

Daniel, Founder of Collective Idea

All your requirements, solved

  • ButterCMS Feature Image Use main domain (for SEO)
  • ButterCMS Feature Image Friendly admin interface
  • ButterCMS Feature Image Upload images and media
  • ButterCMS Feature Image Edit slugs and meta tags
  • ButterCMS Feature Image Tag and categorize posts
  • ButterCMS Feature Image RSS/Atom Feeds
  • ButterCMS Feature Image Search
  • ButterCMS Feature Image Webhooks

Powerful admin interface

Integrates with Next.js

Our blog engine has a simple API and drop-in Next.js source plugin.

Save development time

Save thousands of dollars worth of development time with our easy setup.

Gives you great SEO

Host your blog on your main domain and customize slugs and meta tags.

Try ButterCMS in your Next.js app

Setup in minutes

Official Next.js Guide



Integrating Butter into your Next.js app is dead simple. Here's a mini tutorial to get a feel for of setting up your blog home and blog post pages. For full a integration guide check out our Official Next.js Guide

To display posts we create a new component in blog.js to fetch and list blog posts from the Butter API. See our API reference for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination.

In blog.js:

import React from 'react'
import Link from 'next/link'
import Butter from 'buttercms'

const butter = Butter('')

export default class extends React.Component {
  static async getInitialProps({ query }) {
    let page = query.page || 1;

    const resp = await butter.post.list({page: page, page_size: 10})    
    return resp.data;
  }
  render() {
    const { next_page, previous_page } = this.props.meta;

    return (
      <div>
        {this.props.data.map((post) => {
          return (
            <div><a href={`/post/${post.slug}`}>{post.title}</a></div>
          )
        })}

        <div>
          {previous_page && <Link href={`/?page=${previous_page}`}><a>Prev</a></Link>}
          {next_page && <Link href={`/?page=${next_page}`}><a>Next</a></Link>}
        </div>
      </div>
    )
  }
}

With Next.js getInitialProps will execute on the server on initial page loads, and then on the client when navigating to a different routes using the built-in <Link> component. getInitialProps also receives a context object with various properties – we access the query property for handling pagination. We are fetching posts from a ButterCMS test account – sign in with Github to setup your own posts.

In our render() method we use some clever syntax to only display pagination links only when they're applicable. Our post links will take us to a 404 – we'll get these working next.

Setup the Blog Post page to list a single post

We'll also update our post component to fetch blog posts via slug and render the title and body. See a full list of available post properties in our API reference:

import React from 'react'
import Butter from 'buttercms'

const butter = Butter('')

export default class extends React.Component {
  static async getInitialProps({ query }) {
    const resp = await butter.post.retrieve(query.slug);  
    return resp.data;
  }
  render() {
    const post = this.props.data;

    return (
      <div>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.body }} />
      </div>
    )
  }
}

Add routes to the server

To get our post links working we need to setup dynamic routing for our blog posts. First, create a custom server ./server.js that routes all /posts/:slug URLs to our post component, and the /posts URL to our index page:

const next = require('next')
const express = require('express')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const port = 3000

app.prepare().then(() => {
  const server = express()

  server.get('/posts', (req, res) => {
    return app.render(req, res, '/index', { slug: req.params.slug })
  })

  server.get('/posts/:slug', (req, res) => {
    return app.render(req, res, '/post', { slug: req.params.slug })
  })

  server.get('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})

Finally, update our package.json start script to use our customer server and restart:

"scripts": {
  "start": "node server.js"
}

SEO

Next.js provides a Head component for setting HTML titles and meta tags. Add import Head from 'next/head' to the top of ./pages/post.js and use the component in the render() method:

render() {
  const post = this.props.data;

  return (
    <div>
      <head>
        <title>{post.seo_title}</title>
        <meta name="description" content={post.meta_description} />
        <meta name="og:image" content={post.featured_image} />
      </head>

      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{__html: post.body}} />
    </div>
  )
}}

Restart the server and inspect the HTML source of a post to verify that tags are getting set correctly. Now our app has a working blog that can be updated easily in the ButterCMS dashboard.

Try ButterCMS in your Next.js app

About ButterCMS

ButterCMS is an API-based, or "headless", CMS. We're a hosted service and we maintain all of the infrastructure. For more information on how we compare to a traditional CMS check out API-based CMS vs Traditional CMS.

How do you compare to Wordpress?

In short, we offer all the same easy-to-use editing capabilities of Wordpress but are significantly easier for developers to setup and maintain. This means you spend less time working on your CMS and more time focusing on things important to your business.

Learn more about how we're a wordpress alternative.

What's my blog going to look like?

Unlike CMS's you might be used to, we don't control or host any of your templates. The design of your blog (HTML + CSS) lives in your application along side the rest of your app. Your application calls our Blog Engine API to get the raw blog post content and then injects it into your own templates during rendering. This has many benefits including blog your instantly matching the rest of your site branding giving it a unique feel; not the cookie-cutter blog themes you'll experience with other CMS's.

Can I import my existing blog content?

Yep. To import content from another platform, simply send us an email.

What kind of database can I use?


No database required! We're a SaaS CMS or CaaS. You simply call our Content API from your app. We host and maintain all of the CMS infrastructure.

Can I host this?


No, we're a SaaS CMS or CaaS. You simply call our Content API from your app. We host and maintain all of the CMS infrastructure.

I have other questions


We're happy to help.

Chat with us

About Next.js

Next.js is a universal JavaScript framework that runs in the browser and the server. It offers developers an easy way to get started, and as it uses React.js for templating it is also a straightforward way for developers with React experience to get productive fast.

Blog Engine for these technologies and more

Ruby, Rails, Node.js, Python, ASP.NET, C#, Flask, Django, Go, PHP, React, Phoenix, Elixir, Angular, Vue.js, Gatsby.js, Pelican, Next.js

Try Butter free for 30-days

Try ButterCMS in your Next.js app

Get started now

Sign up with Google Sign up with Github
or