Author’s Note: I’m currently in the process of migrating old blog posts to this new system. That may mean some links, syntax highlighting, and other details are broken or missing temporarily. Sorry for the inconvenience!

In the past several blog posts, we’ve focused on web technologies with an eye toward making the site look a little bit nicer, a little bit prettier. The goal is to build this site up from scratch into something we can be proud of.

Today, however, I want to work on a tool that won’t improve the appearance of the site at all. In fact, it will add a little bit of overhead. It won’t make things more readible, it won’t express any fancy artistic flair. It will, however, make it easier for us to write things. Today, we’re going to integrate Markdown.

What is Markdown?

Remember when we talked about HTML? We discussed how HTML was a markup language. It gave us ways to annotate the text. Markdown does that too! (Yeah, Markdown is a markup language. There are two hard problems in computer science: naming things, cache invalidation, and off-by-one errors).

So Markdown is just another way for us to format text. For the most common types of markup, it’s much more lightweight and easy to read. Take a look at the plain text version of this post for yourself to see how:

  • emphasis
  • links
  • and lists work

Contrast that with typing out <strong>tons of HTML tags</strong>, and you can see why this might have some appeal. HTML is a great language for annotating a document (in excruciating detail, no less), but Markdown is much more pleasant to write in.

So, for the sole purpose of saving my pinkies (please, not another Shift+Angle Bracket!), we’re going to start supporting Markdown.

Let’s get transpiling

Your browser won’t process Markdown files by default (unless you’re in the distant future, maybe, and browser makers are investing their time on weird things). So while I’m writing this article in Markdown, we’ll need to convert it to HTML for actual publication.

Time for some transpiling – which sounds terrifying, but I promise, it’s not. Transpiling is the process of taking code in one language and converting it to another. In this case, Markdown to HTML. It should take something like:


And convert it into:

<a href="https//">Markdown</a>

Since I have Markdown installed on my machine already, I have a command-line tool to do exactly this:

$ markdown ./ > ./to.html

But what about the CSS and all that?

Markdown doesn’t have some CSS variation for styling Markdown documents. And there are plenty of fancy HTML tags that don’t exist as part of the Markdown language. So how do we style the page? Or specify the page’s title that shows up on your browser tab?

Pleasantly enough, most Markdown processors actually let you just drop in HTML where you need it! So while I can use Markdown to write the simple stuff, I’ve dropped the following HTML and CSS into the top of my Markdown file:

<!DOCTYPE html>
<html lang="en">
<title>Moving Toward Markdown</title>
<meta charset="utf-8">
<meta name=viewport content="width=device-width, initial-scale=1">
html {
  background: #666;
  overflow-x: hidden;
body {
  background: #fff;
  margin: 10px auto;
  max-width: 960px;
  overflow-x: hidden;
  padding: 5px 10px;
  width: 90%;

Then at the end of the file, I can drop in a closing body tag and html tag (</body></html>), and we should be all set! Now when I run markdown moving-toward-markdown.html, it leaves the HTML markup alone, but still converts all the Markdown.

Automating the process

There’s just one problem though. We’ve already talked about how I want to push up the updates to these posts in as close to real-time as possible. If I have to manually run $ markdown > out.html just to publish a working blog post, that’s going to add some delays. Better yet would be to improve the automatic site publisher!

When I go to write, I spin up a small script in the background:

rsync -ru --del .
filewatcher -s '**/*' 'rsync -ru --del .'

This clears the screen, pulls down the latest posts from the site (in case my local machine isn’t up-to-date), and then starts watching for file changes. If any files change, it immediately pushes them out, where you can view them in close to real-time (I generally keep the posts I’m actively working on under the /notes folder).

But let’s look at that final line. It runs filewatcher, which is a command that – as you might have guessed – watches files. The first quotes tell it the pattern of files to watch for (in this case, any files nested at any level in the current folder), and the second quotes tell us the command to run when it detects a file change.

Let’s actually extract part into its own script, making our watcher look like this:

rsync -ru --del .
filewatcher -s '**/*' './'

Now we need to create a file, which will be run any time a file change is detected. Filewatcher also sets an environmental variable called $FILENAME, so we can do different things based on which file changes. This way, we can detect Markdown files specifically, and automatically compile them before pushing our files out. Let’s look at the code:

case "${FILENAME##*\.}" in
    markdown $FILENAME > "${FILENAME%.*}.html"
rsync -ru --del .

Bash is…not the most pleasant of languages. But we can do a case analysis on the file extension of the file that changed (“.md”, “.html”, “.txt”, etc). If the file is “.md”, then we run markdown on that filename, directing its output to the same file, except with an HTML extension.

So in the case of this post, each time I save ./notes/ (the filename where I’m writing the draft), the filewatcher detects the change, and since the file ends in .md, it runs markdown ./notes/ > ./notes/moving-toward-markdown.html. Then, regardless of what file changed, it runs rsync, which pushes any changes up to the site itself.


So there we are - we’re now able to write posts in good ol’ Markdown! A much more convenient way to write (nobody likes having to write <p> opening and closing paragraph tags </p> over and over again). One thing worth noticing here is that we have now introduced a very formal “build step” to our blogging process. We’re no-longer making something that the browser can simply render without that transpile step. As we move foward, we’ll see that introducing this build step opens up the door to far more than a few saved keystrokes.

To be continued!

←Previous Post | Next Post→