Back to One Word Domains

Building A Lightweight Blogging CMS In 10 Lines of Code

Published November 2, 2020 by Steven Tey

All Posts

Ever since launching One Word Domains five months ago, I've been wanting to set up a blog where I could:

  1. Document my build process
  2. Write about some of the coolest programming tips and tricks that I learned in the process (this blog post is one of them)
  3. Share some insights on the domain industry - i.e. what are some of the top naming conventions in Silicon Valley

However, I quickly ran into a dilemma when trying to find a suitable blogging CMS (content management system) for my needs:

What I was looking for was a simple and free static-site solution that was easy to customize + integrates well with my existing stack (Heroku, Flask, PostgreSQL, Python, HTML/CSS, JavaScript, jQuery).

I decided to consult my friend Linus, who recommended the Python-Markdown library - which is the same framework that Pelican (the Python version of Hugo) uses.

Intrigued, I began researching the origins of the Python-Markdown library, and that's when I came across this blog post by James Harding. 10 lines of code later, I've successfully set up my very own Markdown-powered static site for the One Word Domains Blog.

Here's how everything went down, step by step:

Requirements

First, I imported the Flask-FlatPages and Markdown libraries:

import markdown
from flask_flatpages import FlatPages

...and declared them in my requirements.txt file:

Flask-FlatPages==0.7.1
Markdown==3.2.1

Folder Structure

Since I already had an existing Flask app up and running, all I did next was add a /posts folder at the root directory, a separate folder called blog-images under the /static/assets folder, and a few template files in the /templates folder. Here's a rough overview on how my folders were structured:

  ├──app.py
  ├──posts
  │     └──post1.md
  │     └──post2.md
  ├──templates
  │     └──blog.html
  │     └──post.html
  └──static
        └──assets
        │       └──blog-images
        └──script
        └──styles

Define FlatPages ENV Variables

Before I started setting up the Flask routes for my blog, I defined the ENV variables for FlatPages in my app.py file, right after initiating the Flask app:

FLATPAGES_EXTENSION = '.md'
FLATPAGES_ROOT = ''
POST_DIR = 'posts'

flatpages = FlatPages(app)
app.config.from_object(__name__)

Here, I defined FLATPAGES_ROOT as '' because the folder containing all my markdown files, posts, is located in the root directory – which is why POST_DIR is defined as 'post'.

Flask Routes

Here are the 10 lines of code that I mentioned earlier – which I inserted into my app.py file:

@app.route("/blog")
def blog():
    posts = [p for p in flatpages if p.path.startswith('posts')]
    posts.sort(key=lambda item:dt.strptime(item['date'], "%B %d, %Y"), reverse=True)
    return render_template("blog.html", posts=posts)

@app.route("/blog/<permalink>")
def blog_post(permalink):
    path = '{}/{}'.format('posts', permalink)
    post = flatpages.get_or_404(path)
    return render_template('post.html', post=post)

I know, I couldn't believe it either.

10 lines of Python code was all I needed to get the One Word Domains Blog up and running.

Let's dive deeper into the lines of code above and see what each one of them does:

Markdown Format

Let's take a look at the format of a given Markdown file, say, the one for this blog post, for example:

title: Building A Lightweight Blogging CMS In 10 Lines of Code
subtitle: This is the full story of how The One Word Domains blog was built - with 10 lines of Python code, the Flask-Flatpages library, and a bunch of Markdown files.
date: November 2, 2020
image: post2-thumbnail.png
permalink: markdown-flask-lightweight-cms

Ever since launching One Word Domains five months ago... (content)

As you can see, each Markdown file has the following attributes:

HTML Templates

Here's a rough outline of my blog.html template:

{% for post in posts %}
<a href="/blog/{{ post.permalink }}">
   <img src="/static/assets/blog-images/{{ post.image }}"/>
   <h1>{{ post.title }}</h1> 
   <p>{{ post.date }}</p>
   <p>{{ post.subtitle }}</p>
</a>
{% endfor %}

This code will iterate across all the Markdown files in the /posts folder that I set up earlier and auto-generate previews for each and every one of them.

And here's the one for my post.html file:

<img src="/static/assets/blog-images/{{ post.image }}"/>
<h1>{{ post.title }}</h1> 
<p>{{ post.date }}</p>
{{ post.html|safe }}

Compile and Run

If everything went well, your blog should be live at 127.0.0.1:5000/blog once you run $ python app.py in your terminal. Yay!

Or, if you're like me and you run into a bunch of errors in your first few attempts - don't give up! Debug your code by pasting the error messages into Google and clicking on the first Stackoverflow post that pops up.

Good luck!

Bonus: Typora

I first started editing my Markdown files in Sublime, which was rather mechanical and cumbersome.

Then, everything changed when the fire nation attacked I discovered this free tool, Typora (or at least, "free during beta", as stated on their site). The intuitive and seamless writing experience that Typora provides is unparalleled, and while **this is not an ad, I highly recommend trying it out.



Join The Newsletter

Join others and get early access whenever we find new one-word domains

Notify me
Thank you!