Brice Sanchez
Brice Sanchez
Senior web developer in Québec city (Canada).
6 Jul 2017 · 2 min read

Use Refinery CMS as a headless API-first CMS

In this article, i will explain how to use Refinery CMS with its Rest API to manage the content of a Middleman static website hosted on the Netlify platform.

The final goal for me is to have one headless CMS app for multiple clients and one Middleman website hosted on Netlify for each customer.

In order to achieve this, we will:

  1. Bootstrap a new Refinery CMS 3.0.x app with a blog
  2. Install and configure the Rest API extension
  3. Create a new middleman app with a blog
  4. Install and configure the middleman-refinery extension
  5. Deploy the middleman website on Netlify
  6. Set the Webhook on your Refinery CMS app

BONUS: I have worked on a refinerycms-multisites extension in order to allow us to create one Refinery CMS app and host multiples customers on it.

1. Bootstrap a new Refinery CMS 3.0.x app with a blog

Follow the Heroku official Refinery CMS guide: Creating a new Refinery application on Heroku

Add the refinerycms-blog extension :

gem 'refinerycms-blog', git: 'https://github.com/refinery/refinerycms-blog', branch: 'master'

2. Install and configure the Rest API extension

Add the refinerycms-api extension at the bottom of your newly created Gemfile

gem 'refinerycms-api', git: 'https://github.com/refinerycms-contrib/refinerycms-api', branch: 'master'

Run bundle install, then

$ rails g refinery:api
$ rake db:migrate

Generate your first API Token with your admin user

$ rake refinery_api:user:api_token:generate EMAIL=refinery@example.org

Great! You can now start using the Rest API

$ curl --header "X-Refinery-Token: YOUR_API_TOKEN" http://localhost:3000/api/v1/pages

3. Create a new middleman app with a blog

Follow these guides:

  1. Middleman: Starting a New Site
  2. Blogging with Middleman

Now you should have a working middleman website with a blog extension.

4. Install and configure the middleman-refinery extension

Add the middleman-refinery extension in the Gemfile of your Middleman app:

gem 'middleman-refinery' git: 'https://github.com/refinerycms-contrib/middleman-refinery', branch: 'master'

Run bundle install, then activate the extension with the blog content_type given by Refinery CMS:

activate :refinery do |f|
  f.api_url = 'http://localhost:3000'
  f.api_token = ENV['REFINERY_API_TOKEN']
  f.content_types = [
    {
      content_type: 'Blog::Posts',
      node: 'posts',
      destination: 'source/blog/data',
      format: '.html.md',
      mapper: MiddlemanRefinery::BlogPostMapper
    }
  ]
end

Now you can run this command to import Blog posts in your middleman folder and rebuild the app

$ bundle exec middleman refinery --rebuild

5. Deploy the middleman website on Netlify

  1. Create an account on Netlify
  2. Sync the repo of your app to perform automatic deploys on git push
  3. Change the build command by
$ middleman refinery --rebuild
  1. Set the API token ENV variable
  2. Generate a webhook URL

6. Set the Webhook on your Refinery CMS app

Create the publish event interactor.

You will need interactor and httparty gems in your Gemfile.

# app/interactors/refinery/publish_event.rb
require 'httparty'

module Refinery
  class PublishEvent
    include Interactor

    def call
      current_account = Refinery::Multisites::Account.find_by(subdomain: Apartment::Tenant.current)

      if current_account.present? && current_account.webhook_url.present?
        if response = HTTParty.post(current_account.webhook_url)
          return true
        else
          context.fail!(message: "refinery.publish_event.failure")
        end
      else
        context.fail!(message: "refinery.publish_event.failure")
      end
    end
  end
end

Create the blog posts controller decorator

# app/decorators/controllers/refinery/blog/admin/posts_controller_decorator.rb
module RefineryBlogAdminPostsControllerPublishEventDecorator
  def self.prepended(base)
    base.prepend_after_action :publish_event, only: [:create, :update, :destroy]
  end

  def publish_event
    result = Refinery::PublishEvent.call

    if result.success?
      flash.now[:notice] << t("refinery.publish_event.success")
    else
      flash.now[:notice] << t(result.message)
    end
  end
end

Refinery::Blog::Admin::PostsController.send :prepend, RefineryBlogAdminPostsControllerPublishEventDecorator

Conclusion

We have seen that in few steps and extensions we are able to use this classic CMS like a headless API-first CMS.

In a future post, i will explain how to use the Rest API of Refinery to receive form entries.

Possibilities are endless and it’s already works in production.

Brice Sanchez
I’m a senior web developer in Québec City (Canada). I’m specialized in Ruby programming language and core team member of Refinery CMS.