Building a Blog with Astro and NetlifyCMS

For work, I have been trying to learn a bit more about some of our own tooling and so I wanted to explore a bit more about how NetlifyCMS worked. I knew I wanted a light tool to compliment it with and so I thought why not some good Astro!

Prerequisites

This assumes you have:

  • Familiarity with JavaScript
  • Installed Node (Version used v16.18.0)
  • Uses NetlifyCMS (Version used 2.15.57)
  • Uses Astro (Version used 0.20.12)

Starting up the project

While you can use some of the other templates, I chose to go for the minimal starter:

mkdir astro-cms-blog
cd astro-cms-blog
npm init astro -- --template minimal

This will create a folder for you and then initialize the astro project with the minimal amount of setup! I found this was really useful so I didn't have to tear anything out like I would have for the other starters.

Adding NetlifyCMS

Netlify offers its own Content Management System called NetlifyCMS. There are two major files that the CMS needs from your production build in order to be all setup:

  1. admin/config.yml - A configuration YAML file. This is where you describe what data structure the CMS should have
  2. admin/index.html - An index.html file. This is what will render our admin dashboard for the CMS

You can add a folder called admin to our public folder and inside include config.yml. This is where you can describe how you want to organize the elements in the CMS, where the posts are stored, and where images might go.

I took the basic structure of what netlifycms.org had on it already and just plopped it in.

# public/admin/config.yml
backend:
name: git-gateway
branch: main # NOTE this relates to your GitHub branch
publish_mode: editorial_workflow
local_backend: true # allows for you to locally mess with your CMS
media_folder: "public/images/uploads" # Media files will be stored in the repo under public/images/uploads
public_folder: "/images/uploads" # The src attribute for uploaded media will begin with /images/uploads
editor:
preview: false # we're going to hide the preview editor
collections:
- name: "blog" # Used in routes, e.g., /admin/collections/blog
label: "Blog" # Used in the UI
folder: "src/pages/blog" # The path to the folder where the documents are stored
create: true # Allow users to create new documents in this collection
slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md
fields: # The fields for each document, usually in front matter
- {label: "Title", name: "title", widget: "string"}
- {label: "Publish Date", name: "date", widget: "datetime"}
- {label: "Featured Image", name: "thumbnail", widget: "image"}
- {label: "Body", name: "body", widget: "markdown"}

This sets up all the backend work, we still need to be sure to add in the admin/index.html. Let's setup the integration we'll need for NetlifyCMS client side.

Astro allows for file-based routing, so you can create a file in your src/pages file in the same path structure as you want the route to live in order to make it live. Since we want a admin/index.html, we need to create an index.astro file under a new admin folder under our src/pages:

<!-- In src/pages/admin/index.astro -->
---
---
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/admin/config.yml" rel="cms-config-url" type="text/yaml" />
<title>Content Manager</title>
</head>
<body>
<!-- Include the script that builds the page and powers Netlify CMS -->
<script src="https://unpkg.com/[email protected]^2.0.0/dist/netlify-cms.js"></script>
</body>

Astro components (denoted with the .astro file extension) allows us to write import statements in the frontmatter (the content between the two ---) or other JavaScript.

We will want to make sure to add a link tag on this page so when the page deploys, it can find the configuration file. But the most important script is adding the NetlifyCMS! This will make sure we can access the content and perform updates, deletes, and whatnot.

Lastly, in our `src/pages/index.astro, we'll want to be sure to add in a script tag for us to integrate with Netlify Identity. This is helpful for when you're signing up later on when everything is deployed. Fortunately, this is only necessary when it is live and locally we're able to login without this.

<!-- inside src/pages/index.astro -->
---
// ... frontmatter
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
<script type="text/javascript" src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</head>
<body>
<!-- Body stuff -->
</body>
</html>

Adding a renderer

This is a small aside. If you were to try to run our project right now npm run dev, it would compile fine. However, if you go to your CMS site (http://localhost:3000/admin), you'll see an error more than likely saying:

Error: Can't determine the renderer for NetlifyCMS. Include a hint similar to when multiple renderers are included in your Astro config.

This is because it cannot tell what type of component it is trying to process (React, Preact, Vue, Svelte) and to fix this, we need to go diving into our astro.config.mjs and set the renderer. By default you have a few renderers installed as of 0.20 of Astro. I chose to use Preact since it is close to React and was already pre-installed.

// In astro.config.mjs
export default /** @type {import('astro').AstroUserConfig} */ ({
renderers: ['@astrojs/renderer-preact'],
});

And this is all the stuff we need to make sure at a bare minimum to have the CMS running and letting us create content!

Running the CMS

To run the CMS locally, you will want two terminals. One terminal will be running our astro server through: npm run dev. And the second server will be used to allow for us to have a proxy server for the CMS to run through using npx netlify-cms-proxy-server. You won't need to worry about the proxy server when you go to deploy your site, this is just helpful for local development.

With both of those running, you should be able to log in successfully in at http://localhost:3000/admin and be able to create a blog post. Now when you go and publish your blog post this will produce a markdown file under src/pages/blog/. This is configurable under the public/config.yml if you'd like for it go elsewhere or have any other attributes.

If you go and publish your first blog post, you'll be able to find it rendered in the a URL pattern of: http://localhost:3000/blog/YYYY-MM-DD-title. Congrats on making your first blog post working!

Conclusion

This is just the tip of the iceberg you can get away with for Astro and the NetlifyCMS. If you wanted a bit of direction, here are some ways to keep going: