Architecture Behind Blog - 2024
December 08, 2024 | 4 min read
Revisiting how I designed this blog on 2020 to document how it works, along with its limitations and possible future improvements.
I started blogging using Medium. From a writer's perspective, I liked Medium for its simple writing tool, especially how easy it is to import images from Unsplash. I always wonder what it takes to host my own blog. So I started researching how to self host my own blog.
My first attempt at self-hosting my blog was using Ghost Open Source. I self-host a Ghost instance, use it as a CMS for me to write and manage the blog posts, then design and write my own frontend to show the blog writings, using Ghost APIs for communication. Being honest, the main reason I tried Ghost was its writing experience which is very similar to Medium. However, I feel like it's too overkill and complicated for my use case after running it for a while.
This finally leads me to using plain and simple Markdown files for blogging.
Markdown based architecture
The content of this blog is currently written in Markdown format and the frontend is built using Next.js. I decided to use Next.js only because I'm familiar with it. There are some scripts which will parse all the blog posts in different Markdown files and display it accordingly. Let's go through each pages.
Home page
The content on my home page is also based on Markdown. It's the exact same Markdown file shown on my Github. Whenever I make any changes in my Github profile, this web's home page will be automatically updated as well.
Blog page
This is where we get to the core blog functionality. I put all my blog posts under a /posts
folder in the codebase.
Each Markdown file counts as one blog post. Inside each Markdown file, there is always a YAML front-matter containing metadata such as title
, description
, createdAt
, tags
, and some SEO related metadata. For assets, I structure it under /public/assets/<post>
folders.
To make this all work, I'm using several libraries:
- fs - to read and interact with files
- gray-matter - to parse the metadata of each post Markdown file
- markdown-it - to parse and render Markdown file into HTML format
- reading-time - to show an estimate on how long it will take to read a post (similar to Medium)
- tailwindcss - for all the CSS and styling of the web
To show the list of posts available, simply iterate through all the files available under /posts
, read their metadata using gray-matter
, and render the needed information on page.
To render a post, first need to get the specific file. This is done by getting the slug
in URL which will correspond to the Markdown file name.
Once the file is found, simply parse and render the HTML with both gray-matter
and markdown-it
, while adding additional information such as reading time using reading-time
library.
Each components - headers (h1, h2, h3), title, text, paragraph, images, etc. have their own custom style in CSS format, created using tailwindcss
.
Writing posts
To write a post, I first need to create a Markdown file under /posts
folder and also a corresponding folder under /public/assets
for all the assets needed in the post. This could be automated through a simple bash script in the future.
Currently, I still write all this post using my default programming IDE VSCode, but will look into other Markdown editors in the future.
Since all the posts is located in my web project structure, I simply use Git to save drafts and keep track of any changes I've made in the writings.
Deployments
This web is hosted on Vercel. I've been using Vercel for most of my frontend projects due to its simplicity to setup and ease of integration with Github for CICD.
Any changes to my writings will be automatically deployed once I merge it into the main branch. Simple enough.
SEO
SEO is something that I know could be further improved. Right now, I just make sure that all pages have a clear meta title and description and the sitemap is always updated whenever there is a new blog post. This is one of those things that could be automated as well in the future.
I use Google Search Console to manage links and sitemaps of this web.
Analytics
Lastly, for analytics, I use Google Analytics with all the default tracking (pageview, clicks, etc.). Next.js's integration with Google Analytics is super easy to setup.
Recently, I've looked into Posthog as well, might consider using it to learn more about Posthog in the future.