Rem Kim - 2020-05-10
In previous blog I showed how to setup basic Next.js project. Here I will explain how to setup your own CMS and save blogs locally using Lambda functions.
It is obvious that you need some sort of storage to save your blogs. It could be good old MySQL or Postgres. It could be document storage like MongoDB, or something new and fancy like FaunaDB. In my case I didn't want to use any third party hosting/provider services to store my data and I also wanted to own data. So, I decided to save files locally and use Github as a data storage.
There are few things we will cover while building CMS.
I didn't want to write HTML for each blog to style it. So the easiest and right way to do it is to use markdown.
I used package react-markdown that allows you to render markdown input as HTML. Now since in my blog I use Chakra UI I had to pass renderer function in order for react-markdown package to know how to render each of markdown elements.
Full blog form code here
This form allows us to write our blog in textarea as a markdown and then preview it using React Markdown package. We will use the same package to render it in blog page.
We will be using Lambda functions which is Next.js API routes to save blog.
Sending POST request to /api/cms/blogs
will save file.
First of all we need to make sure that incoming request is POST
, then we check if we are in development environment, by running devonlyMiddleware
which I will describe later. After that we can proceed with saving file.
Here is example structure of the blog file
{
"title": "Newer draft",
"tldr": "Some tldr",
"tags": [],
"content": "",
"thumbnail": null,
"status": "draft",
"author": "Rem Kim",
"createdAt": "2020-04-15T02:32:45.034Z",
"updatedAt": "2020-04-22T21:19:19.791Z",
"slug": "newer-draft",
"id": 1586917965034
}
Those are the fields I find useful and need to be saved. For an ID i used current timestamp.
generateFilename
getSlug
and finally saveBlogFile
I used fileSystem.promises
in order to be able to use async/await syntax.
Now, in order to find or update blog by its ID, i've added another api route
api/cms/blogs/[id]
Click to see code
allFiles - This function will scan directory with blog files, reach each one and parse its content to JSON, then output array of blog objects.
writeJSONToFile and makeFilename
I promised we will comeback to this one. Like I said before I want to be able to use all that functionality locally when spinning up local development server. However on production those api functions should error out.
In order to do it I've added devonlyMiddleware
Now with those API routes, I can read/save/update blogs and github becomes my data storage.