When we redesigned our website, we wanted to create a solution that would allow us to focus on creating content rather than managing the infrastructure. To achieve this, we decided to replace our existing content management system (CMS) with Netlify CMS (now known as Decap CMS), which is a git-based CMS that does not require us to manage the API infrastructure. However, this decision brought several challenges, and we ultimately decided to remove Netlify CMS from our website’s architecture.
In this article, we will discuss the migration process, the challenges we faced, and our decision to roll back away from Netlify CMS.
💡 Despite the rebranding to Decap CMS, we will continue to refer to the CMS as Netlify CMS for clarity since that was the name it had when we were working with it. More information on this change can be found here.
Initially, our company website had the following technology and infrastructure:
Our infrastructure was as follows:
Three main reasons inspired the desire to migrate from the above architecture:
The existing setup did not require a lot of money, but we could still lower costs by changing the design. Since our website does not change much in a short time, the current design was too complicated for our mostly static content.
Plus, the original architecture had multiple parts that cost money: database, headless CMS, front-end, and file storage.
Initially, the local setup was using data from the deployed infrastructure. This structure led to an unclear separation between the production environment and the development environment. Consequently, dependency issues arose during the development process; such as the setup not working when internet was unavailable locally.
Although it was technically feasible to set up a multi-environment Strapi CMS deployment that would meet all of our requirements, we decided against it as it would have added further complexity to our development process, which seemed counterintuitive.
Our initial setup had a three-tier architecture, which can be a lot for a company website. Consequently, we were motivated to move towards a simpler architecture. Eventually, we settled on migrating to a JAMstack architecture.
The JAMstack architecture leverages Javascript, APIs and Markup to create fast and secure websites in the following way:
The following diagram illustrates our implementation of the JAMstack architecture:
The above setup had the following major components:
During the migration process, we had the following objectives:
These goals were achieved through the following steps:
In this step, we had to transform our content data into a form that can be represented in markdown files.
For instance, our MongoDB database returned articles’ documents as follows:
1[ 2 { 3 "_id": { "$oid": "638a0438fc13ae38050000bc" }, 4 "title": "First Article", 5 "category": "Balanced Analysis", 6 "published": "12/25/2021", 7 "author": { 8 "name": "John Doe", 9 "title": "Software Developer", 10 "link": "https://johndoe.com" 11 }, 12 "body": "Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem. Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat. Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede. Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl. Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum. In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo. Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis. Sed ante. Vivamus tortor. Duis mattis egestas metus. Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh. Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros. Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat. In congue. Etiam justo. Etiam pretium iaculis justo. In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus. Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi. Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus. Phasellus in felis. Donec semper sapien a libero. Nam dui. Proin leo odio, porttitor id, consequat in, consequat ut, nulla." 13 } 14]
Creating a markdown file for this article would result in:
1--- 2title: First Article 3category: Balanced Analysis 4published: 25-12-2021 5author: 6 name: John Doe 7 title: Software Developer 8 link: https://johndoe.com 9--- 10 11Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem. Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat. Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede. Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl. Duis bibendum, felis sed interdum venenatis, turpis enim blandit mi, in porttitor pede justo eu massa. Donec dapibus. Duis at velit eu est congue elementum. In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo. Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis. Sed ante. Vivamus tortor. Duis mattis egestas metus. Aenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh. Quisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros. Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat. In congue. Etiam justo. Etiam pretium iaculis justo. In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus. Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi. Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus. Phasellus in felis. Donec semper sapien a libero. Nam dui. Proin leo odio, porttitor id, consequat in, consequat ut, nulla.
The set of key/value pairs at the beginning of the markdown file provide more information of the article itself. This data is referred to as frontmatter; which is useful when performing queries at the GraphQL data layer. The actual body of the article follows the frontmatter section.
Afterwards, we moved the markdown files into the GitHub repository, depending on the content type. For instance, blog posts were moved into
1netlify/blog
.
In this step, we laid the foundation for Netlify CMS use in our application. This process entailed:
1config.yml
file to handle Netlify CMS configuration settings.For the content type settings, we derived standard properties from the data we obtained from our database. For example, for our blog posts, we concluded that the following properties are standard:
Therefore, the blog section of our
1config.yml
file was as follows:
1collections: 2 - name: "blog" 3 label: "Blog" 4 folder: "netlify/blog" 5 create: true 6 fields: 7 - { label: "Title", name: "title", widget: "string" } 8 - { 9 label: "Category", 10 name: "category", 11 widget: "select", 12 options: 13 [ 14 "Tutorial", 15 "Architecture Breakdowns", 16 "Balanced Analysis", 17 "Deep Dive", 18 ], 19 } 20 - label: "Author" 21 name: "author" 22 widget: "object" 23 fields: 24 [ 25 { label: "Author Name", name: "name", widget: "string" }, 26 { label: "Author Title", name: "title", widget: "string" }, 27 { label: "Author Link", name: "link", widget: "string" }, 28 ] 29 - { label: "Publication Date", name: "date", widget: "date" } 30 - { label: "Body", name: "body", widget: "markdown" }
In this section, we specified the property and its corresponding widget to edit it. More information on the
1config.yml
can be viewed in the Netlify CMS docs here.
Since we were hosting our website on Netlify CMS, our changes were continuously deployed when we were making commits and merging with our main branch. Considering that the new setup was git-based and used markdown files, the changes we implemented were reflected in real-time.
However, since we chose to use Netlify's built-in authentication service for the CMS, we had to do additional configuration. The steps we followed can be found here.
Despite the attractive promises of JAMStack and Netlify CMS, the reality fell short of expectations. In the migration process, we encountered difficulties that snowballed into larger obstacles.
During our migration process, we had to convert each content type data into markdown files, which was tedious. Since this was the first iteration of our content in markdown, the shape of our data was constantly evolving as we tried to find what worked.
For example, for our blog articles, if we wanted to introduce a “Last Edited” property, we would first have to edit the
1config.yml
file, then proceed to the individual markdown files and add the relevant data to each blog article markdown file.
Possible Workaround
Regarding this issue, our only option at the time was to manually edit the files.
The community has discussed creating a package that reads migration files and applies the changes to
1config.yml
. This package would also ensure existing data follows the new changes. For more information, see this open issue.
Netlify CMS sits in an awkward spot between providers like Contentful and more customizable solutions like Strapi CMS or custom-built content management systems. It relies on YAML-based configurations with limited options, combining the drawbacks of both. Additionally, at the time, Netlify CMS was not flexible enough to build a framework which would make configuration easier. Some of the challenges we experienced during configuration were as follows:
1config.yml
file proved to be quite challenging.1config.yml
file got longer. This made it harder to maintain. Additionally, the lack of YAML schema made it more challenging to validate the contents of the config file.Possible Workaround
At the time, there was no official implementation of a UI that edits Netlify CMS settings. However, community projects such as this exist to meet this need.
As we had mentioned previously, one of the goals that we wanted to achieve is to help our engineers work more productively on a day-to-day basis by making sure they had an independent sandbox they could work from without external dependencies or similar limitations.
In the Netlify CMS setup, the development and production environment are closely coupled. By default, changes made either locally or on the published site fetch and commit files in the remote repository, as specified here. Consequently, it is difficult to separate changes made locally and the modifications made in production.
Since we wanted a better local development experience, Netlify CMS came up short in this regard. However, we tried some countermeasures to curb this issue.
Possible Workaround
To deal with this issue, we followed the doc’s recommendation to run a proxy server in the local environment and configure Netlify CMS to use it in the local development environment. The latter would allow us to change the content locally without interfering with the hosted repository.
This approach had its drawbacks. Firstly, it was in beta, so it could occasionally crash and publish to the remote repository. Secondly, Editorial Workflow couldn't be enabled. Without this feature, we had much less control over the publishing process. We couldn't save drafts or require an approval stage before publishing to production.
Since Netlify CMS is a self-contained React app, it brings about its share of dependency issues when updates are made to the packages it uses. In our case, updating React versions in Gatsby brought about build failures and installation errors in Netlify CMS. The open issues section of the repository reveals that this issue is prevalent and recurring whenever there is a new version of React.
Furthermore, the close coupling between Netlify CMS and the Gatsby-built website had led to a lack of clear separation between the two, and any errors in Netlify CMS builds would cause the website build to fail.
Possible Workaround
Running
1npm install —legacy-peer-deps
in the installation process allows us to ignore the dependency issues that arise. However, this countermeasure has a downside. Overlooking dependency issues can lead to breaking changes in our application.
Prior to choosing Netlify CMS, we conducted a thorough investigation of the various CMS options available. At the time, Netlify CMS had a high number of stars on Github and was frequently mentioned in technical blogs as a top choice for a headless CMS. However, in the exploration phase, we missed the following red flags:
Considering that Netlify CMS (now known as Decap CMS) has transitioned to new stewardship, it is worthwhile to observe whether this change will have a positive impact on its future trajectory.
One of the key things we learned from this experience was the importance of being more careful when selecting an open source solution. Although Netlify CMS appeared to be a good fit initially, it ultimately did not meet our objectives.
Currently, we use Markdown files as our data source and make edits directly to them. We are still investigating other CMS options that might better suit our needs.
Balanced Analysis
Explore various perspectives surrounding the controversial issue of the value of certificates in the tech community. Get an in-depth rundown of the pitfalls that arise from the use of professional certificates and how to use certificates optimally.
Tutorial
Learn why you should containerize you gatsby application using docker and how to do so with easy to follow steps regardless of the Operating System you are using.
Architecture Breakdowns
Explore the principles that create scalable styling architecture in react and learn practices that can achieve this desired architecture.
Tutorial
Learn how to seed data into MongoDB using docker and docker compose and use the generated data in a React application, through step-by-step instructions.