- Published on
How to Build Your Own Blog(1): Architecture and Data Model
I'm planning to write a series of articles to share my experience of building this website. Hopefully, they will serve as a guide for you to build your own blog.
Key Decisions
When I first thought about creating a personal blog, I had to make several key decisions:
- Do I want a static or dynamic blog?
- Which programming language and framework should I use for the backend?
- What frontend framework should I choose?
- Where should I store my data?
- How do I deploy my website?
I decided to go with a dynamic blog because it offered more flexibility and opportunities for hands-on learning. For the backend, I chose Golang because I am a Golang developer, and since Gin is a popular Golang framework, it felt like a natural choice. I'm not as experienced in frontend development, so I asked ChatGPT for the most popular frontend framework, which turned out to be Next.js. For the CSS framework, after some research, I found Tailwind CSS to be the best fit. (I should say it's the best CSS framework!!!)
For data storage, I chose MongoDB because I didn’t want to deal with schema updates, and it offers a free tier (Mongdb Atlas). As for hosting, I selected DigitalOcean’s Droplet to host my website and used Docker Compose for deployment. (If they get more customers because of my article, they should send me credits.) The main reason for choosing DigitalOcean is its affordability. Additionally, it provides a static IP address, which is essential for connecting to the MongoDB Atlas cluster.
Architecture
The overall architecture looks like this:
There are four major components:
- Browser: The client-side interface.
- Web Server: Hosting the frontend.
- API: Backend service.
- Database: Storing blog posts.
Plugins like Google Analytics and Waline add extra functionality to the system.
The web server and API are stateless, allowing for horizontal scaling (though it’s probably not necessary at this point).
Only the web server is publicly accessible. The API and database should ideally be accessed only through the internal network. However, since I'm using MongoDB Atlas, the database is publicly accessible with some restrictions (of course, for security reasons).
Data Model
For the blog posts, I defined the following data model:
Post struct {
ID string `json:"id,omitempty"`
Slug string `json:"slug,omitempty"`
Title string `json:"title,omitempty"`
Author string `json:"author,omitempty"`
Content string `json:"content,omitempty"`
Summary string `json:"summary,omitempty"`
Tags []string `json:"tags,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
The only thing worth mentioning is the slug field.
What is a "slug"?
In web development, a slug refers to a part of a URL that identifies a specific page on a website in a way that is easy to read and interpret by both users and search engines. Slugs are typically derived from the page's title, and are lowercase and hyphenated.
For example, in the URL https://example.com/blog/how-to-learn-python
, the slug is how-to-learn-python
.
Key characteristics of slugs include:
- Human-readable: They are designed to be easily understood by people.
- SEO-friendly: They help with search engine optimization by making URLs more descriptive.
- Consistent: They follow a consistent pattern, often reflecting the title or main topic of the page.
(Answer from ChatGPT)
Generating Unique Slugs
When generating slugs, it is important to handle duplicates. For instance, both "Z’ink" and "Z-ink" would lead to the same slug: z-ink
. After generating a slug for a new post, we need to check if it already exists in the database.
If z-ink
is already in the database, we need a solution that keeps the slug user-friendly and close to the original title. A common approach is to append a number, such as z-ink-1
. However, what happens if z-ink-1
is also taken?
To solve this, we can find all slugs with z-ink
as the prefix. The database might contain entries like z-ink
, z-ink-1
, z-ink-2
, and z-ink-blog
. In this case, the next available slug would be z-ink-3
.
(If you don't want to use slug, you can use ID instead, which is also unique. Though, it's not human and SEO friendly.)