What is CMS Integration
Consider the following scenario: You have a fully-functional website, and you want to add a blog to it. The problem: you haven’t previously accounted for this, and you start wondering what the best solution may be that won’t require a major rewrite of your working app.
Perhaps your website is instead still under development, but all solutions for adding blogging functionality seem difficult to fit in your current stack.
Sound familiar?
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, without having to resort to a complex monolithic solution like WordPress. 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.
In other words, CMS integration is how to add CMS capabilities into an existing website. 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.
Historical Challenges of CMS Integration
Traditional CMS solutions, like WordPress, have historically evolved into whole solutions controlling everything for your app or website. It means that your app will most likely live as a “monolith”, a single unit of technology that is supposed to control the entirety of your website.
This might be fine until it isn’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.
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’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.
The Subdomain Approach
A way to circumvent the constraints imposed by a monolith solution is to move your blog to a different subdomain, such as blog.example.com. 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.
While this works there are some caveats with this approach:
- SEO. The main issue is that setting up your blog under a subdomain can negatively impact your SEO. For content that depends on organic searches, this is very undesirable.
- UI consistency. You will be tasked with the extra work of maintaining a consistent UI for two separate apps, so you don’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.
- Multiple apps overhead. Instead of one, you will have two applications to maintain. In the long run, this may cause a lot of inconvenience.
The Subdirectory Approach
An alternative to subdomains is to use subdirectories. In fact, subdirectories mitigate the major issues presented by subdomains. First, they are SEO friendly. 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.
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’t want to foster.
What Then?
Both approaches have in common a considerable integration effort. Moreover, you don’t fully decouple your app from the CMS, meaning that they coexist in a clunky way. A truly good solution should neutralize integration risks and have minimal impact on the current architecture, especially from a DevOps perspective. This is something a headless CMS enables you to do.
CMS Integration: A Conceptual Overview
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.
Content as Data
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?
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.
Traditional CMS solutions already perform these operations, but only for internal consumption. WordPress will save your content in the database and retrieve it when necessary, 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.
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 your content being managed as regular data, fetched from Butter’s servers and rendered as you wish, without changing the architecture of your app.
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. Butter currently supports all major languages, so you can throw it at your app today and start blogging at once.
In the next section, we will see how it works in practice by adding a blog into a regular website.
CMS Integration In More Detail
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 React but as I mentioned earlier, you can work with your favorite stack. Go ahead and check all available APIs in the ButterCMS website if you haven’t done that before.
In our example, let us assume that we have an existing website and our goal is to add a blog into it. Here’s how it looks like before we add any Butter.
There is nothing fancy on the site right now. It’s just a regular website with some dummy content. You can follow along this tutorial by checking this GitHub repo. This project was bootstrapped with Create React App. For simplicity I’ll omit CSS changes but the main file can be inspected here.
Adding the Router
Let’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 React Router. In your app directory open the terminal and type:
$ yarn react-router-dom
Or alternatively:
$ npm i --save react-router-dom
To simplify the code, I’ll break our home down into three different components. Here is how App.js
looks like:
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 (
<div className="container">
<Header />
<Home />
<Footer />
</div>
);
}
}
export default App;
Now, we want to be able to render either Home
or the list of blog posts. We will then replace Home
with the router and make sure that the main
element is common to all routes:
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';
class App extends Component {
render() {
return (
<div className="container">
<Router>
<Header />
<main>
<Switch>
<Route exact path="/" component={Home} />
</Switch>
</main>
<Footer />
</Router>
</div>
);
}
}
Save and check your progress by running npm
start and going to http://localhost:3000. You will see that your app loads normally but if you change the URL to http://localhost:3000/blog an empty space will be rendered. Let’s fix that!
Adding the Blog Page
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 Blog.js
, adding this code:
import React from 'react';
const Blog = () => {
return (
<div>
<h1>Blog</h1>
</div>
);
}
export default Blog;
Now it’s time to make our router aware of this new page. In App.js
:
<main>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/blog" component={Blog} />
</Switch>
</main>
We need a way to allow users to visit the blog page without needing to manually change the URL. Let’s fix that in Header.js
:
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => (
<header>
<nav>
<div className="logo">
<Link to="/">
Fine Coffee <span role="img" aria-label="Coffee">☕</span>
</Link>
</div>
<ul className="menu">
<li><Link to="/blog">Blog</Link></li>
<li><a href="tel:">Call Us</a></li>
</ul>
</nav>
</header>
);
export default Header;
And that’s it! Our integration is complete with minimum effort.
The full code for this tutorial is available on GitHub. There is also a live example if you are curious about the end result.
Conclusion
The web is continuously evolving resulting in obtrusive solutions that don’t play along with other technologies being pushed aside. Integration and maintainability are major concerns that need to be addressed with responsibility.
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.
To wrap it up, a good CMS integration should:
- Decouple your website from the data. Both should coexist without being directly connected, in the sense that changes in one end do not affect the other end.
- Allow easy integration. 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.
- Have a reduced cost of change. 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.
- Give you freedom of tech stack. 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.
Further Reading
In this article, we demonstrated how you can integrate ButterCMS with a React application. There is also an extensive list of how to do the same with other platforms:
- Use ButterCMS with Vue.js
- Use ButterCMS with Angular
- Use ButterCMS with Django
- Use ButterCMS with Golang
- Use ButterCMS with PHP
Top comments (0)