Decap CMS: Unified Management for Multiple GitHub Repositories

Chirag Jain
VLEAD-Tech
Published in
5 min readJul 25, 2023

Introduction

Decap CMS ( previously Netlify CMS ) is a powerful content management system that allows content creators to edit Markdown files stored in GitHub repositories. However, using the conventional config.yml approach, it becomes challenging to dynamically manage multiple repositories under different organizations without modifying the configuration file for each new repository. In this blog, we will explore the challenges posed by the static config.yml method and propose a dynamic solution that leverages JSON configuration and vanilla JavaScript.

Decap CMS Documentation

TL;DR

Decap CMS is a robust content management system that enables editing of GitHub repository Markdown files. However, the static config.yml approach poses challenges for managing multiple repositories under various organizations.

To overcome this, we propose a dynamic solution using JSON configuration and vanilla JavaScript. By creating an HTML form to accept organization and repository names, we pass these as URL parameters to the Decap CMS admin page. JavaScript logic then injects these values into the JSON configuration object, allowing efficient management of experiments across repositories without manual editing. With the JSON configuration object ready, we use CMS.init({ config }) to initialize Decap CMS with the dynamically generated settings.

This ensures that Decap CMS is configured to work with the specified GitHub repository and organization, allowing content creators to seamlessly edit Markdown files without manual intervention.

Assumption

Before we delve into the implementation details, we assume that the user has already set up a GitHub OAuth app and obtained the necessary credentials. This OAuth app should be configured to work with the application being deployed on Netlify.

Challenges with the config.yml approach

  1. Static Configuration: The config.yml approach requires hardcoding the repository and organization details, making it difficult to adapt to different repositories without manual modification.
  2. Limited Flexibility: The inability to update the configuration at runtime restricts the system’s potential to scale and support multiple repositories efficiently.

The Dynamic Solution

To overcome the challenges of the static config.yml approach, we will implement a dynamic solution using JSON configuration. The process involves creating an HTML form on the landing page to accept the organization and repository names. The values from the form will be passed as URL parameters to the Decap CMS admin page, where JavaScript logic will extract these parameters and inject them into the JSON configuration object.

Step-by-Step Implementation

1. Set Up Landing Page (index.html)

Create a new HTML file named index.html and include the following code:

<!DOCTYPE html>
<html>
<head>
<title>Content Development Tool</title>
<!-- Additional head content (stylesheets, scripts, etc.) can be added here -->
</head>
<body>
<h1>Welcome to the Content Development Tool</h1>
<form id="configForm">
<label for="org">Organization:</label>
<input type="text" id="org" required>
<label for="repo">Repository:</label>
<input type="text" id="repo" required>
<button type="submit">Proceed to Content Editor</button>
</form>

<script>
document.getElementById("configForm").onsubmit = function (e) {
e.preventDefault();
const org = document.getElementById("org").value;
const repo = document.getElementById("repo").value;
window.location.href = `admin/index.html?org=${org}&repo=${repo}`;
};
</script>
</body>
</html>

Explanation:

  • The form element with the ID “configForm” allows users to enter the organization and repository names.
  • When the form is submitted, the onsubmit event triggers a JavaScript function.
  • The e.preventDefault() prevents the default form submission behavior to allow us to handle the form data ourselves.
  • We use document.getElementById to get the values entered by the user in the "org" and "repo" input fields.
  • The window.location.href property is used to redirect the user to the admin page (admin/index.html) with the organization and repository names as URL parameters.

2. Set Up Admin Page (admin/index.html):

Create a new folder named admin and within it, create a new HTML file named index.html. Include the following code:

<!DOCTYPE html>
<html>
<head>
<title>Content Editor</title>
<!-- Additional head content (stylesheets, scripts, etc.) can be added here -->
</head>
<body>
<!-- Include the Decap CMS script -->
<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>

<script>
// JavaScript logic to extract URL parameters and dynamically update CMS configuration
const urlParams = new URLSearchParams(window.location.search);
const org = urlParams.get('org');
const repo = urlParams.get('repo');

const config = {
backend: {
name: 'github',
repo: `${org}/${repo}`,
branch: 'master',
},
media_folder: 'static/assets',
public_folder: '/assets',
collections: [
// Example collection for blog posts
{
name: 'blog',
label: 'Blog',
folder: 'content/blog',
create: true,
fields: [
{ name: 'title', label: 'Title', widget: 'string' },
{ name: 'date', label: 'Date', widget: 'datetime' },
{ name: 'author', label: 'Author', widget: 'string' },
{ name: 'body', label: 'Body', widget: 'markdown' },
],
},
// Add more collections for different content types as needed
],
};

// Initialize Decap CMS with the dynamic configuration
CMS.init({ config });
</script>
</body>
</html>

Explanation:

  • We include the Decap CMS script using a script tag from the provided CDN link to enable the CMS functionality on this page.
  • The JavaScript logic begins by extracting the URL parameters using URLSearchParams and the window.location.search property.
  • We retrieve the organization and repository names from the URL using urlParams.get('org') and urlParams.get('repo'), respectively.
  • The config object is created with the specified backend settings for GitHub. We dynamically update the repo property by combining the organization and repository names entered by the user.
  • We also define the media_folder and public_folder options to specify where media files are stored and accessed.
  • You can add additional Decap CMS configuration options to this object based on your requirements.
  • Finally, we call CMS.init({ config }) to initialize Decap CMS with the dynamically generated configuration.

Use Case

The source code for all experiments in Virtual Labs is stored in a Git repository. This version control system allows for efficient tracking of changes made to the experiments, enabling collaboration among multiple contributors. Each experiment in Virtual Labs follows a predefined template, including components like Aim, Procedure, Theory, etc. These templates are stored as Markdown files within the ./experiment folder. Markdown is a lightweight markup language, making it easy to edit and format the experiment content.

To implement the centralized solution, a dynamic JSON configuration approach with Netlify CMS is adopted. This JSON configuration file contains essential settings for Netlify CMS, such as the GitHub repository details, collections, and fields for the different experiment components. The JSON configuration defines collections for each experiment component, like Aim, Procedure, Theory, etc. Within each collection, fields are specified to capture the content for that particular component. For instance, the “Aim” collection may have a single “text” field to enter the aim of the experiment.With the dynamic JSON configuration in place, educators, administrators, and contributors can easily manage experiment content through the Netlify CMS interface. They can add, modify, or remove experiments, as well as update individual components, all in real-time.

Conclusion

By using JSON configuration, we have successfully eliminated the need to manually update the config.yml file, making the content development tool dynamically adaptable to different GitHub repositories under various organizations. This centralized approach allows content creators to efficiently manage multiple repositories without hassle, streamlining the content creation process.

With the added collections and fields, the content development tool is now capable of managing various types of content across multiple GitHub repositories efficiently. This powerful and dynamic setup empowers content creators to focus on generating valuable content without worrying about technical configurations, ultimately fostering creativity and collaboration within your organization.

--

--