How I developed a markdown blog in Go and HTMX
What's the M in HTML? Mark..up? Not for me.
Why md, why go?
First of all, if you just want to download and use the blogging platform (or to read along with code), you can find it on GitHub.
When I wanted a blog, I was first looking for an easy, straightforward way to do so. Web wise, I am most familiar with PHP and Go. I missed the ‘NodeJS’ and ‘React’ craze (whatever those frameworks are), but I know looking at projects or tutorials related to those frameworks / stacks make me sick in my mouth, it feels so different to my PHP / Wordpress days. But that’s a skill diff with me, I’m sure they are good frameworks.
I was part of the jQuery nation, I’m somewhat (pleasantly) surprised to see it still around in 2023!
Enter HTMX. Having a background with PHP, HTMX feels just like my pleasant memories of PHP, but better because Go :).
The first thing I turned to was Wordpress, but honestly, it wouldn’t be a fun challenge, it’s full of bugs and dodgy plugins, and I REALLY can’t be bothered with writing some HTML, setting it up in the Wordpress format, creating databases, managing the back end, blah blah blah.
Outside of using Go for API routing for writing command-and-control servers, I’m unfamiliar with how ‘modern web development’ works, all this templating, routing for your website doesn’t make sense to me. As much as I hate to admit it, Wordpress was a great solution to building large, scalable websites.
Markdown is a beautiful way of writing, especially blogging, without the faff of having to write in HTML because come on, who does that?! Lucky for me, the wonderful Go community have developed markdown to HTML libraries, such as markdown.
I’m actually excited to build this. Lets Go!
Setting up
I’ll cover the basics in case you are new to go, but there are some really good resources on learning Go routing and API routing online, a long time ago I actually used TechWithTim, he has a really good video on Gin.
- Download Go
- Install Go
- Add Go to your $PATH
- Add Go extension to your IDE / editor of choice.
- Verify Go is correctly installed by running the command: go version
Set up your code-space
The next step is to create a folder for where your project will live, and then set up version control (recommend git).
Next, initialise the repository as a go module with:
This is a time now to add some files to your **.gitignore**, here is what I recommend:
*.exe *.exe~ *.dll *.so *.dylib *.test *.out
vendor/
go.work
If you are on Mac you might also want to include:
.DSStore ..DS_Store **/.DSStore **/..DS_Store
Next, we will create our folders, we want the following (from the perspective of the project root):
/markdown /static css images webfonts /templates
Finally, lets pull down the libraries we need, in this case we are using:
1. Gin
2. markdown
So, run these commands:
go get -u github.com/gin-gonic/gin go get -u go get -u github.com/gomarkdown/markdown
## Markdown structure
Lets talk about how we want to use some in-file tagging so that we can set various attributes for our blog posts / pages.
Our markdown files will follow this format:
Title: Page title Slug: page-slug Parent: What is this a subpage of Order: 1 Description: A subtitle / strap-line for the page which appears below the main title. MetaDescription: SEO description of page. MetaPropertyTitle: SEO page title for Social Media links MetaPropertyDescription: SEO page description for Social Media links
MetaOgURL: URL of the page
Below the --- we will have our page content, written in markdown. We will be able to use a mixture of HTML and markdown, so for those cases where markdown doesn't fully cut it, don't worry I got you covered.
By convention, I will save the markdown file in the **/markdown** folder as the same name as the slug, so for example this would be called: **page-slug.md**.
## HTML templating
Next, using some beautiful HTMX we are going to create the following pages (go and make these now):
/templates/header.html /templates/index.html /templates/layout.html /templates/sidebar.html /templates/sidebar-right.html
[Here](https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go) is a nice write-up on templates in Go if you are unfamiliar. it would be worth a read. But the TL;DR I can come up with for you is templating allows you to glue .html pages together, and include variable data which is generated by the Go webserver on the page, contained in blocks of:
{{ // your code }}
If you are familiar with PHP, this is very much like the below tags:
<?php // your code ?>
Just before we create our html pages, in **main.go** we want to define some **structs** to hold data which we will be referencing in a html template.
So in **main.go**, do the following:
package main
type BlogPost struct { Title string Slug string Parent string Content template.HTML Description string Order int Headers []string // for page h2’s MetaDescription string MetaPropertyTitle string MetaPropertyDescription string MetaOgURL string }
type SidebarData struct { Categories []Category }
type Category struct { Name string Pages []BlogPost Order int }
func main() {
}
Now, lets start off with **index.html**, this will be routed specifically for the home page:
{{ template “header.html” . }}
{{ template "sidebar.html" dict "Categories" .SidebarData.Categories "CurrentSlug" .CurrentSlug }}
<main class="main-content">
<h1>{{ .Title }}</h1>
<p class="description">{{ .Description }}</p>
<hr />
{{ .Content }}
{{ template "footer.html" }}
</main>
{{ template "sidebar-right.html" . }}
</div>