ButterCMS and Spree integration
ButterCMS is a headless content management system that boasts an easy-to-use marketing dashboard and blazing fast content API for modern apps. By using ButterCMS, you can give your sales and marketing team full control creative control of even the most complex, segmented content.
The benefits of using ButterCMS for your ecommerce business
- Using ButterCMS, you can have separate interfaces for your marketing staff and store admins.
- Global content API that integrates into any tech stack.
- With a headless CMS, you don’t need to worry about the database and infrastructure behind your blog.
- Easily migrate your blog to any other solution in the future without losing content or data.
- Scaling, maintenance, and security are all handled by the ButterCMS team.
How to integrate ButterCMS with Spree
CREATING A SKELETON FOR THE BLOG PAGES
Before modifying the website layout and adding a link to the blog, we have to generate the Spree views:
docker-compose run web bash
rails g spree:frontend:copy_storefront
The above command populated the app/views/spree directory with the platform views.
CREATING THE CONTROLLER
Create the new controller file for our blog:
touch app/controllers/blogs_controller.rb
The controller will consist of two actions: index and show. The index action will be used to display all blog posts and the show action to render specific blog posts.
Open the previously created controller file and put the following contents in there:
class BlogsController < Spree::StoreController
def index
end
def show
end
end
Notice that we inherit from the Spree::StoreController, not ApplicationController. Thanks to this, the blog page is an integral part of the platform.
You can start with the blank pages, add a link to the layout, and hook up Butter CMS when the navigation works properly.
CREATING VIEWS
The controller definition is ready, so you can add blank views:
mkdir app/views/blogs/
touch app/views/blogs/index.html.erb
touch app/views/blogs/show.html.erb
UPDATING ROUTES
The blog pages are not yet reachable, so you have to update the routes configuration. Open the config/routes.rb file and add the following line:
resources :blogs, only: %i[show index], path: 'blog'
The path “blogs” looks slightly weird, so I passed the path option with the custom singular name.
Now, you can access http://localhost:3000/blog and http://localhost:3000/blog/not-existing-post, and you will see blank pages in the platform layout. You are now ready to put some content there.
The last step regarding blog accessibility is to add a link to the menu. Open /app/views/spree/shared/_main_nav_bar.html.erb and add the new element to the menu list:
<li>
<%= link_to "Blog", blogs_path, class: 'nav-link main-nav-bar-item main-nav-bar-category-button' %>
</li>
CONFIGURING YOUR BUTTER CMS ACCOUNT
Visit https://buttercms.com/ and create a new account if you don’t have one. Sign in and visit the settings page – https://buttercms.com/settings/.
The “Read API token” is the only thing you need to effectively connect Butter CMS with your Spree platform. Having that token, we can now install the Butter CMS gem in our application.
INSTALLING THE BUTTER CMS GEM
Run the following command to add the gem to the Gemfile and install it in your system:
docker-compose run web bash
bundle add buttercms-ruby
You need an initializer file that will save our Butter CMS API key at the application start. Create it:
touch config/initializers/butter_cms.rb
Put the following contents there:
ButterCMS::api_token = "YourToken"
Replace the “YourToken” placeholder with the API key present in the settings tab of your ButterCMS account. Remember not to store this token in the repository. It should be a secret credential not visible anywhere on the internet. One of the best ways to handle such sensitive data is to store them in the environment variables. For this article’s purpose, I will put the API key directly in the initializer.
You are now ready to add the blog listing page.
BLOG LISTING PAGE
Open BlogsController and add the following code to the index action so we can pull all posts from ButterCMS and pass them to the view:
@posts = ButterCMS::Post.all
Now, open app/views/blogs/index.html.erb and display the post titles along with the link to the specific blog post:
<div class="container mb-3 d-md-flex">
<div class="col-md-12 col-lg-9">
<div class="row">
<% @posts.each do |post| %>
<div class="col-sm-4 col-6 mb-3 mb-md-4 pr-sm-0 pr-md-0 pl-md-4 pl-sm-4">
<div class="product-component-name">
<%= post.title %>
</div>
<div class="product-component-price">
<%= link_to('Read more', blog_path(id: post.slug)) %>
</div>
</div>
<% end %>
</div>
</div>
</div>
Feel free to add your own styles to make the blog listing page look even better.
The last step is to implement a single blog post page.
BLOG POST PAGE
Open the show action in the BlogsController and add the following line:
@post = ButterCMS::Post.find(params[:id])
You can now access the post object in the view and display it the same way we would show records in an ordinary Ruby on Rails application.
Open app/views/blogs/show.html.erb view and add the following code there:
<div class="container pt-4 product-details">
<div class="row">
<div class="col-12 col-md-5">
<div id="product-description">
<h1 class="mt-3 mt-md-0 text-center text-md-left product-details-title">
<%= @post.title %>
</h1>
</div>
</div>
<div class="pb-4 pt-md-5 row">
<%= @post.body.html_safe %>
</div>
</div>
</div>
To be more consistent with the platform style we can also add breadcrumbs at the top of the page:
<div class="container">
<nav id="breadcrumbs" class="col-12 mt-1 mt-sm-3 mt-lg-4">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<%= link_to('/') do %>
<span>Home</span>
<% end %>
<span itemprop="item" itemscope="itemscope" itemtype="https://schema.org/Thing" itemid="/"></span>
</li>
<li class="breadcrumb-item">
<%= link_to(blogs_path) do %>
<span>Blog</span>
<% end %>
<span itemprop="item" itemscope="itemscope" itemtype="https://schema.org/Thing" itemid="/"></span>
</li>
<li class="breadcrumb-item">
<%= link_to(blog_path(id: @post.slug)) do %>
<span><%= @post.title %></span>
<% end %>
</li>
</ol>
</div>