Adding Decap CMS
Adding Posts to the Blog
The process of adding posts to the blog using Hugo is actually very simple, and by itself is just fine as is. The full process is creating a post on the local development server using
hugo new content posts/post-name.md
Then editing using your preferred text editor neovim btw
, then push it into
the GitHub repository when you’re done. After that, if you are running the site
on Cloudflare pages, Netlify, or something similar, the site is built automatically,
once the site is rebuilt can take a few minutes, depending on the size of the site
your work is on the live site with no extra work needed. So unless you don’t
like editing the page files, or new articles on a local text editor, or the process
of pushing the updates to git worries you, there isn’t any real need for a CMS.
So why did I decide to add Decap?
Aside from the practice it gave in setting it up, I do have good reasons for doing so.
As of now, my computer set up is very stationary, if I travel and don’t have time to set everything up, I can’t use my system. Which, of course, means should I go on a vacation for a few days/weeks I won’t have the ability to add anything new here. Now, since this is a personal project, and isn’t meant to be anything more than that for the foreseeable future, having constant access to updating the site is not of critical importance. I decided to set up the CMS regardless because I find adding to site, and managing everything very fun.
If you are interested in setting up decapcms on your own site, read the decapcms official docs
First steps
The first thing I needed to do was find out if it is even possible to run decap without Netlify on my own servers. That was quick and easy to find out the answer to, you can add it to your project by running,
yarn add decap-cms-app --save
npm should be similar. With that you need to add the admin page. You’ll have to make sure that you put all the extra files for the cms page in their own directory, the cms page takes over whatever page it is added onto, so if it gets added on top of an existing page, the old page won’t be accessible until you move the CMS.
Setting up the config file
The first thing you need is the backend for the cms page, the docs mostly go over using git-gateway, since they are setting it up with Netlify. Since I am using Cloudflare Pages to host my site, I need it set up a little differently
backend:
name: github
branch: main
repo: # Your repository
base_url: # Here you are going to put the OAuth Server you set up
So, what is this doing? This part of the config file tells decap-cms what backend
system is going to be used, in our case GitHub, and the branch you want it to update.
The last two keys are where we differ from the standard docs on the official site
other than my branch being main instead of master, but it means the same thing
You’ll set repo to be the GitHub repo your site files are stored on, using the
GitHub backend, it isn’t connected automatically like when you are using Netlify
to set it up. The base_url is where you specify the authentication server you
set up so that you can log in to the admin panel when it is all set up. I’ll go
over that later on.
The default publishing process for the cms is to push straight to production, or branch it was set to update, with no process for reviewing or editing. For a personal project, or for most people, that default is perfectly fine as is, but if you want you can set
publish_mode: editorial_workflow
This will give you three stages for each article
- Drafts
- In Review
- Ready after the article reaches the Ready stage, it can be published. This doesn’t totally prevent you from pushing an article all the way through to ready, but it does help you organize them if you need your articles to run through that process.
The final most important portion of the config file, at least so far as I have learned yet, is collections. This is where you tell decap what it can edit, where it’s allowed to create new content, where the files are located or what directory the new files should be saved to, and how the pages should be edited.
Collections has a few important keys we’ll need to add,
- name: the name this for this collection, it’s used in the paths for the files
for example name: "posts" would result in base_dir/posts/post-file.md
- label: This is what shows up on the CMS page
- create: true/false or leave empty for false, allows decap to create new files
- fields: This is how you’ll tell decap how you want the pages to be set up, or how they are currently set up. You need this to match the way your theme has framed the pages if you plan on keeping things looking cohesive. Fields is set up similarly to collections, each portion you add is given a label to name it in the UI, a name, a default value if needed, and the widget that this section uses. There are quite a few more tags, so check the official docs
The name tag in fields is a little different from the name tag in collections, in that it instead will connect to the tags that are placed in each page, so if you have the title tag at the top of your page and you add it into the CMS field, that field should now edit the value assigned to the title in your page. Here is a small example of how you can enable editing and creating posts on your site
collections:
- name: "posts"
label: "Posts"
folder: "content/posts" # I forgot to mention, you can also set it to one file, or a whole folder using the folder/file tags
create: true # So you can create posts inside the webpage
fields: # Now we set the structure for the pages, make sure you check how your theme builds pages, and set each fields name to match the tags set by your theme
- {label: "Title", name: "title", widget: "string"} # This sets it to display Title in the UI, says that is going to be set to a tag named title, and says the input type is string
- {label: "Publish Date", name: "date", widget: "datetime"} # If you timestamp posts, this will auto set the time to your current time, and if you want it to be set when you post, there's a now button that sets the time again
- {label: "Body", name: "body", widget: "markdown"} # And this is what gives you that rich text editor with an option to edit in markdown, here you'll write the body of the page
And this is the simplest way to set it up to create and edit posts, the folder tag tells it to save the new posts to content/posts, and that it will find older posts there. Exactly how your new post will look after being created will depend on the theme you chose, but it’ll give you a title a timestamp and the body. I would recommend adding the standard tags your theme uses to keep things consistent, but at it’s simplest this is all you need. There are plenty of cool widgets for you to use, so check out the docs and see which ones work best for you. More advanced users also have the ability to create custom widgets, I haven’t needed that, so I won’t cover it here.
Here’s the full config file if you were following along
backend:
name: github
branch: main
repo: # Your repository
base_url: # Here you are going to put the OAuth Server you set up
publish_mode: editorial_workflow
collections:
- name: "posts"
label: "Posts"
folder: "content/posts" # I forgot to mention, you can also set it to one file, or a whole folder using the folder/file tags
create: true # So you can create posts inside the webpage
fields: # Now we set the structure for the pages, make sure you check how your theme builds pages, and set each fields name to match the tags set by your theme
- {label: "Title", name: "title", widget: "string"} # This sets it to display Title in the UI, says that is going to be set to a tag named title, and says the input type is string
- {label: "Publish Date", name: "date", widget: "datetime"} # If you timestamp posts, this will auto set the time to your current time, and if you want it to be set when you post, there's a now button that sets the time again
- {label: "Body", name: "body", widget: "markdown"} # And this is what gives you that rich text editor with an option to edit in markdown, here you'll write the body of the page
Now the complicated part
After you set up the config file to be the way you want, or before the order doesn’t actually matter, you’ll need to set up the authorization server to allow access to the CMS panel. Now, if you used Netlify to set up your site it’s going to be done for you, but in our case, we need to do it ourselves.
The easiest way, and the way I did it, is using the server example made by Tyler Gaw, the only downside is that you need to use a separate hosting provider, glitch, to run everything. Fortunately, it hasn’t cost me anything, and it is really fast. Go to his glitch server, and remix it to get your own version. Click the .env file, it has the environment variables you need to set for this to work.
- CLIENT_ID
- CLIENT_SECRET You’ll get the values you need in the next step.
After you have the server, go to GitHub developer settings, and add a new OAuth app. Here’s a link, set the Application Name and description to whatever you want, but the Homepage has to be the URL of the glitch server, and the Application callback URL has to be set to the glitch server /callback.
After you create the OAuth app, it’ll give you the client_id, and let you generate the client secret. All you need to do is set the CLIENT_ID and CLIENT_SECRET variables in the glitch server to the same values and you are done with the server set up.
Now, if you remember earlier on in the article when we first set up the admin config file, we had a key value under backend called base_url, the last thing you’ll need to do is set that to the glitch server we just set up to finish up with the config file.
Finally, the last step
All you need is to put these two files in the directory holding your admin panel
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex" />
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
<title>Content Manager</title>
</head>
<body>
<!-- Include the script that builds the page and powers Decap CMS -->
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>
admin.js
import CMS from 'decap-cms-app'
// Initialize the CMS object
CMS.init()
// Now the registry is available via the CMS object.
CMS.registerPreviewTemplate('my-template', MyTemplate)
Well, in retrospect, admin.js actually doesn’t appear to be doing anything, but I have it there, so try loading Decap-CMS without it only using the index.html.
But that is all you really need to run Decap-CMS without Netlify, and it’s how I have my decap running. Once again, if you are interested in doing this yourself, go ahead and check these resources out, these are what I used to write this and set things up
- Decap official docs - GitHub backend
- Tyler Gaw This is really what made this work, at the very least it would have taken me a lot longer without it.