CMS Integration: How to Add a Blog Into Existing Site
Tags: cmsintegration
Published: 2019-09-27 00:10:36

---
title: CMS Integration: How to Add a Blog Into Existing Site
published: true
description: CMS integration is how to add CMS capabilities into an existing website.
tags: cms integration
---

<ol>
<li><a href="#whatiscmsintegration"><span style="font-weight: 400;">What is CMS Integration</span></a><span style="font-weight: 400;"></span>
<ul>
<li><a href="#historicalchallengesofcmsintegration"><span style="font-weight: 400;">Historical Challenges of CMS Integration</span></a></li>
</ul>
</li>
<li><a href="#cmsintegrationaconceptualoverview"><span style="font-weight: 400;">CMS Integration: A Conceptual Overview</span></a>
<ul>
<li><a href="#contentasdata"><span style="font-weight: 400;">Content as Data</span></a></li>
<li><a href="#cmsintegrationinmoredetail"><span style="font-weight: 400;">CMS Integration In More Detail</span></a>
<ul>
<li><a href="#addingtherouter"><span style="font-weight: 400;">Adding the Router</span></a></li>
<li><a href="#addingtheblogpage"><span style="font-weight: 400;">Adding the Blog Page</span></a></li>
<li><a href="#addingbutter"><span style="font-weight: 400;">Adding Butter</span></a></li>
<li><a href="#addingcontent"><span style="font-weight: 400;">Adding Content</span></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#conclusion"><span style="font-weight: 400;">Conclusion</span></a></li>
<li><a href="#furtherreading"><span style="font-weight: 400;">Further Reading</span></a></li>
</ol>
<h1 id="whatiscmsintegration"><span style="font-weight: 400;">What is CMS Integration</span></h1>
<p><span style="font-weight: 400;">Consider the following scenario: You have a fully-functional website, and you want to add a blog to it. The problem: you haven&rsquo;t previously accounted for this, and you start wondering what the best solution may be that won&rsquo;t require a major rewrite of your working app.&nbsp;</span></p>
<p><span style="font-weight: 400;">Perhaps your website is instead still under development, but all solutions for adding blogging functionality seem difficult to fit in your current stack.</span></p>
<p><span style="font-weight: 400;">Sound familiar?</span></p>
<p><span style="font-weight: 400;"><img src="https://cdn.buttercms.com/fZPkpxkiSVSGUrgoHNfU" alt="CMS integration" width="394" height="367" class="butter-float-left" />You may be a good candidate for CMS (Content Management System) integration for your app or website. CMS integration is simply taking your existing website/web app and integrating a Content Management System with it,&nbsp;</span><i><span style="font-weight: 400;">without </span></i><span style="font-weight: 400;">having to resort to <a href="/blog/headless-wordpress-how-to-use-their-blog-data-in-your-app" target="_blank" rel="noopener" title="CMS integration">a complex monolithic solution like WordPress</a>. It is the degree of freedom you are looking for in order to keep your tech stack of choice and still be able to enjoy the best of what a Content Management System can offer.</span></p>
<p><span style="font-weight: 400;">In other words, </span><b>CMS integration is how to add CMS capabilities into an existing website. </b><span style="font-weight: 400;">This article aims to explain more of it in practice, what the pain points are, how to solve them, and how you can efficiently add a web content management system into your current project without needing to rewrite everything from scratch.</span></p>
<p><span style="font-weight: 400;"></span></p>
<h2 id="historicalchallengesofcmsintegration"><span style="font-weight: 400;">Historical Challenges of CMS Integration</span></h2>
<p><span style="font-weight: 400;">Traditional CMS solutions, like WordPress, have historically <a href="/blog/buttercms-vs-wordpress-headless-cms-vs-traditional-cms" target="_blank" rel="noopener">evolved into whole solutions controlling everything for your app or website</a>. It means that your app will most likely live as a &ldquo;monolith&rdquo;, a single unit of technology that is supposed to control the entirety of your website.</span></p>
<p><span style="font-weight: 400;">This might be fine until it isn&rsquo;t anymore. Suppose you grow tired of WordPress and want to change the CMS provider. After all, you are likely to encounter scalability issues with a monolithic solution as it grows. You now have a problem, as you will need to rebuild core parts of your app that might not even be related to the CMS. Or maybe you are an experienced developer who likes to write web apps using your preferred tech stack, but require an easy interface for non-technical content creators and editors to be able to add and edit content without needing you to update code.</span></p>
<p><span style="font-weight: 400;">Historically, CMS solutions are tightly coupled to the app. You can minimize the impact of an eventual change in the future by early planning, but the reality is that you won&rsquo;t always be able to foresee the need for it - and even if you do, current approaches are just suboptimal, as we will see next.</span></p>
<h3><span style="font-weight: 400;">The Subdomain Approach</span></h3>
<p><span style="font-weight: 400;">A way to circumvent the constraints imposed by a monolith solution is to move your blog to a different subdomain, such as </span><b>blog</b><span style="font-weight: 400;"><strong>.example.com</strong>. By doing this you can set up your CMS and still keep your favorite tech stack. For example, you might have a website built with Angular + NodeJS and install a WordPress blog in another subdomain. </span></p>
<p><span style="font-weight: 400;">&nbsp;</span><span style="font-weight: 400;">While this works there are some caveats with this approach:</span></p> 
<ol>
<li style="font-weight: 400;"><b>SEO</b><span style="font-weight: 400;">. The main issue is that setting up your blog under a subdomain </span><a href="/blog/blog-subdomain-or-subdirectory-hint-one-is-40-better" target="_blank" rel="noopener" title="CMS integration"><span style="font-weight: 400;">can negatively impact your SEO</span></a><span style="font-weight: 400;">. For content that depends on organic searches, this is very undesirable.</span></li>
<li style="font-weight: 400;"><b>UI consistency</b><span style="font-weight: 400;">. You will be tasked with the extra work of maintaining a consistent UI for two separate apps, so you don&rsquo;t confuse your users. As naive as it is, consider the case where you have developed a layout for your web app and now need to find (or develop) a WordPress theme that resembles it.</span></li>
<li style="font-weight: 400;"><b>Multiple apps overhead</b><span style="font-weight: 400;">. Instead of one, you will have </span><i><span style="font-weight: 400;">two </span></i><span style="font-weight: 400;">applications to maintain. In the long run, this may cause a lot of inconvenience. </span></li>
</ol>
<h3><span style="font-weight: 400;">The Subdirectory Approach</span></h3>
<p><span style="font-weight: 400;">An alternative to subdomains is to use subdirectories. In fact, subdirectories mitigate the major issues presented by subdomains. First, </span><a href="/blog/blog-subdomain-or-subdirectory-hint-one-is-40-better" target="_blank" rel="noopener" title="CMS integration"><span style="font-weight: 400;">they are SEO friendly</span></a><span style="font-weight: 400;">. Also, they are still part of the same app, just installed in a different directory. This structure softens the multi-app and multi-UI overhead.</span></p>
<p><span style="font-weight: 400;">The problem is that setting a CMS in a subdirectory can be technically challenging. It is definitely non-trivial to orchestrate everything together. A DevOps problem is something you certainly don&rsquo;t want to foster.</span></p>
<h3><span style="font-weight: 400;">What Then?</span></h3>
<p><span style="font-weight: 400;">Both approaches have in common a considerable integration effort. Moreover, you don&rsquo;t fully decouple your app from the CMS, meaning that they coexist in a clunky way. A truly good solution <a href="/blog/headless-cms-learn-the-what-why-and-how" target="_blank" rel="noopener" title="CMS integration">should neutralize integration risks and have minimal impact on the current architecture</a>, especially from a DevOps perspective. This is something a <a href="/blog/headless-cms-learn-the-what-why-and-how">headless CMS</a> enables you to do.</span></p>

<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_fbebec17d74d7b0e85da677a3_bde6aa4670" value="" tabindex="-1" /></div>
</div>
</form></div>
</div>
</div>
<h1 id="cmsintegrationaconceptualoverview"><span style="font-weight: 400;">CMS Integration: A Conceptual Overview</span></h1>
<p><span style="font-weight: 400;">A headless CMS is a back-end content repository that makes content accessible via API. This approach allows you to treat content as you would treat any regular piece of data.</span></p>
<h2 id="contentasdata"><span style="font-weight: 400;">Content as Data</span></h2>
<p><span style="font-weight: 400;">Suppose that you want to integrate your app with Google Maps. You do not want to make any styling changes, you should not set up any other servers, and you should keep everything in the same domain without creating a new directory. How is this possible? </span><span style="font-weight: 400;"></span></p>
<p><span style="font-weight: 400;">This happens because you assume whatever geolocalization data you might need will be fetched in a predictable way from a 3rd-party application. Hence all you need to do is to prepare to receive that piece of information and display it accordingly. For instance, putting a marker in a map given a set of coordinates.</span><span style="font-weight: 400;"></span></p>
<p><span style="font-weight: 400;">Traditional CMS solutions already perform these operations, but only for internal consumption. <a href="/blog/headless-wordpress-how-to-use-their-blog-data-in-your-app" target="_blank" rel="noopener" title="CMS integration">WordPress will save your content in the database and retrieve it when necessary</a>, without exposing it to other applications. The way your layout or themes consume this data is different from what a regular API does, because you need to use framework-specific methods. These methods add one more layer of complexity, no matter how thorough you find their documentation.</span><span style="font-weight: 400;"></span></p>
<p><span style="font-weight: 400;">This is precisely how a solution like Butter can help. ButterCMS, a headless CMS, allows you to create content normally in a separate environment, as it should be, and consume content directly in your app through an API. The end result is <a href="/blog/weve-launched-a-write-api-for-buttercms" target="_blank" rel="noopener" title="CMS integration">your content being managed as regular data</a>, fetched from Butter&rsquo;s servers and rendered as you wish, without changing the architecture of your app.</span></p>
<p><span style="font-weight: 400;"><br /><br /><img src="https://cdn.buttercms.com/G2HKMpBSnuNW3quqfBrA" alt="CMS integration" style="display: block; margin-left: auto; margin-right: auto;" /><br /></span></p>
<p><span style="font-weight: 400;">&nbsp;</span></p>
<p><span style="font-weight: 400;">Using content as data means that you need to be language agnostic, i.e. you should be able to grab your content regardless of your tech stack. </span><a href="/api-first-cms/" target="_blank" rel="noopener" title="CMS integration"><span style="font-weight: 400;">Butter currently supports all major languages</span></a><span style="font-weight: 400;">, so you can throw it at your app today and start blogging at once.</span></p>
<p><span style="font-weight: 400;">In the next section, we will see how it works in practice by adding a blog into a regular website.</span></p>
<h2 id="cmsintegrationinmoredetail"><span style="font-weight: 400;">CMS Integration In More Detail</span></h2>
<p><span style="font-weight: 400;">Now that we understand what CMS integration means, let us see how one can do it. For the sake of this tutorial, I will be using <a href="/react-cms/" target="_blank" rel="noopener" title="CMS integration">React</a> but as I mentioned earlier, you can work with your favorite stack. Go ahead and </span><a href="/blog-engine/" target="_blank" rel="noopener" title="CMS integration"><span style="font-weight: 400;">check all available APIs in the ButterCMS website</span></a><span style="font-weight: 400;"> if you haven&rsquo;t done that before.</span></p>
<p><span style="font-weight: 400;">In our example, let us assume that we have an existing website and our goal is to add a blog into it. Here&rsquo;s how it looks like before we add any Butter.</span></p>
<figure class="image align-center"><a href="/" title="CMS integration ButterCMS" target="_blank" rel="noopener"><img src="https://cdn.buttercms.com/EcmkQKOrTdm0oHLb5pCY" alt="CMS integration" width="637" height="679" /></a>
<figcaption><i><span style="font-weight: 400;">Simple website with no blog content</span></i></figcaption>
</figure>
<p></p>
<p></p>
<p><span style="font-weight: 400;">There is nothing fancy on the site right now. It&rsquo;s just a regular website with some dummy content. You can follow along this tutorial by </span><a href="https://github.com/rafaelquintanilha/butter-example/tree/without-butter" target="_blank" rel="noopener" title="CMS integration"><span style="font-weight: 400;">checking this GitHub repo</span></a><span style="font-weight: 400;">. This project was bootstrapped with </span><a href="https://facebook.github.io/create-react-app/" target="_blank" rel="noopener"><span style="font-weight: 400;">Create React App</span></a><span style="font-weight: 400;">. For simplicity I&rsquo;ll omit CSS changes but the main file can be inspected </span><a href="https://github.com/rafaelquintanilha/butter-example/blob/master/src/App.css" target="_blank" rel="noopener"><span style="font-weight: 400;">here</span></a><span style="font-weight: 400;">.</span></p>
<h3 id="addingtherouter"><span style="font-weight: 400;">Adding the Router</span></h3>
<p><span style="font-weight: 400;">Let&rsquo;s add a page that will hold our blog content and will work as a subdirectory. As explained before, this approach improves SEO. For this, we will need <a href="https://reacttraining.com/react-router/web/guides/quick-start" target="_blank" rel="noopener">React Router</a>. In your app directory open the terminal and type:</span></p>
<pre><code>$ yarn react-router-dom </code></pre>
<p><span style="font-weight: 400;">Or alternatively:</span></p>
<pre><code>$ npm i --save react-router-dom</code></pre>
<p><span style="font-weight: 400;">To simplify the code, I&rsquo;ll break our home down into three different components. Here is how </span><code><span style="font-weight: 400;">App.js</span></code><span style="font-weight: 400;"> looks like:</span></p>
<pre><code>import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import Header from './Header';
import Footer from './Footer';
class App extends Component {
  render() {
    return (
      &lt;div className="container"&gt;
        &lt;Header /&gt;
        &lt;Home /&gt;
        &lt;Footer /&gt;
      &lt;/div&gt;
    );
  }
}
export default App;
</code></pre>
<p><span style="font-weight: 400;">Now, we want to be able to render either </span><code><span style="font-weight: 400;">Home</span></code><span style="font-weight: 400;"> or the list of blog posts. We will then replace </span><code><span style="font-weight: 400;">Home</span></code><span style="font-weight: 400;"> with the router and make sure that the </span><code><span style="font-weight: 400;">main</span></code><span style="font-weight: 400;"> element is common to all routes:</span></p>
<pre><code>import { 
  BrowserRouter as Router, 
  Route, 
  Switch 
} from 'react-router-dom';
class App extends Component {
  render() {
    return (
      &lt;div className="container"&gt;
        &lt;Router&gt;
          &lt;Header /&gt;
          &lt;main&gt;
            &lt;Switch&gt;
              &lt;Route exact path="/" component={Home} /&gt;
            &lt;/Switch&gt;
          &lt;/main&gt; 
          &lt;Footer /&gt;
        &lt;/Router&gt;
      &lt;/div&gt;
    );
  }
}
</code></pre>
<p><span style="font-weight: 400;"> Save and check your progress by running </span><span style="font-weight: 400;"><code>npm</code> start</span><span style="font-weight: 400;"> and going to </span><a href="http://localhost:3000" target="_blank" rel="noopener"><span style="font-weight: 400;">http://localhost:3000</span></a><span style="font-weight: 400;">. You will see that your app loads normally but if you change the URL to </span><a href="http://localhost:3000/blog" target="_blank" rel="noopener"><span style="font-weight: 400;">http://localhost:3000/blog</span></a><span style="font-weight: 400;"> an empty space will be rendered. Let&rsquo;s fix that!</span></p>
<h3 id="addingtheblogpage"><span style="font-weight: 400;">Adding the Blog Page</span></h3>
<p><span style="font-weight: 400;">Once the router is all set, let us create a dummy page which we will use to hold the blog content in just a moment. Go ahead and create a file called </span><code><span style="font-weight: 400;">Blog.js</span></code><span style="font-weight: 400;">, adding this code:</span></p>
<pre><code>import React from 'react';
const Blog = () =&gt; {
  return (
    &lt;div&gt;
      &lt;h1&gt;Blog&lt;/h1&gt;
    &lt;/div&gt;
  );
}
export default Blog;</code></pre>
<p><span style="font-weight: 400;">Now it&rsquo;s time to make our router aware of this new page. In </span><code><span style="font-weight: 400;">App.js</span></code><span style="font-weight: 400;">:</span></p>
<pre><code>
&lt;main&gt;
  &lt;Switch&gt;
    &lt;Route exact path="/" component={Home} /&gt;
    &lt;Route exact path="/blog" component={Blog} /&gt;
  &lt;/Switch&gt;
&lt;/main&gt;
</code></pre>
<p><span style="font-weight: 400;">We need a way to allow users to visit the blog page without needing to manually change the URL. Let&rsquo;s fix that in </span><code><span style="font-weight: 400;">Header.js</span></code><span style="font-weight: 400;">:</span></p>
<pre><code>import React from 'react';
import { Link } from 'react-router-dom';
const Header = () =&gt; (
  &lt;header&gt;
    &lt;nav&gt;
      &lt;div className="logo"&gt;
        &lt;Link to="/"&gt;
          Fine Coffee &lt;span role="img" aria-label="Coffee"&gt;☕&lt;/span&gt;
        &lt;/Link&gt;
      &lt;/div&gt;
      &lt;ul className="menu"&gt;
        &lt;li&gt;&lt;Link to="/blog"&gt;Blog&lt;/Link&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="tel:"&gt;Call Us&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/nav&gt;
  &lt;/header&gt;
);
export default Header;</code></pre>
<p><span style="font-weight: 400;"> And that&rsquo;s it! Our integration is complete with minimum effort.</span></p>
<p><span style="font-weight: 400;">The <a href="https://github.com/rafaelquintanilha/butter-example" target="_blank" rel="noopener">full code for this tutorial is available on GitHub</a>. There is also a <a href="https://butter-example.netlify.com/" target="_blank" rel="noopener">live example</a> if you are curious about the end result.</span></p>
<h1 id="conclusion"><span style="font-weight: 400;">Conclusion</span></h1>
<p><span style="font-weight: 400;">The web is continuously evolving resulting in obtrusive solutions that don&rsquo;t play along with other technologies being pushed aside. Integration and maintainability are major concerns that need to be addressed with responsibility.</span></p>
<p><span style="font-weight: 400;">Treating your content as regular data gives you the flexibility you need to enjoy the power of CMS solutions without being chained to a piece of technology, as you never know when you may want to switch it in the future. Freedom of choice and less maintenance headaches are huge wins for developers.</span></p>
<p><span style="font-weight: 400;">To wrap it up, a good CMS integration should:</span><span style="font-weight: 400;">&nbsp;</span></p>
<ul>
<li style="font-weight: 400;"><b>Decouple your website from the data</b><span style="font-weight: 400;">. Both should coexist without being directly connected, in the sense that changes in one end do not affect the other end.</span></li>
<li style="font-weight: 400;"><b>Allow easy integration</b><span style="font-weight: 400;">. A plain and simple API will do the job. Just call the API when you want to insert content from the CMS into your app.</span></li>
<li style="font-weight: 400;"><b>Have a reduced cost of change</b><span style="font-weight: 400;">. If you ever want to change the underlying technologies that power up your application, having a CMS should not impact the complexity of the change.</span></li>
<li style="font-weight: 400;"><b>Give you freedom of tech stack</b><span style="font-weight: 400;">. The CMS should be agnostic to whichever tech stack you decided to use in your project. They are separate entities and therefore should not interfere with each other apart from the API.</span></li>
</ul>
<h2 id="furtherreading"><span style="font-weight: 400;">Further Reading</span><span style="font-weight: 400;">&nbsp;</span></h2>
<p><span style="font-weight: 400;">In this article, we demonstrated how you can integrate ButterCMS with a <a href="/blog/best-practices-for-building-a-large-scale-react-application">React application</a>. There is also an extensive list of how to do the same with other platforms:</span></p>
<ul>
<li style="font-weight: 400;"><a href="/vuejs-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">Use ButterCMS with Vue.js</span></a></li>
<li style="font-weight: 400;"><a href="/angular-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">Use ButterCMS with Angular</span></a></li>
<li style="font-weight: 400;"><a href="/django-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">Use ButterCMS with Django</span></a></li>
<li style="font-weight: 400;"><a href="/golang-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">Use ButterCMS with Golang</span></a></li>
<li style="font-weight: 400;"><a href="/php-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">Use ButterCMS with PHP</span></a></li>
</ul>
<p><span style="font-weight: 400;">&nbsp;</span></p>
<p><a href="/api-first-cms/" target="_blank" rel="noopener"><span style="font-weight: 400;">And many others!</span></a></p>
<p></p>