Consult With Simon

Blog Engine in Go

Considering simplicity, integration with the rest of the website using Go already, and experience with blog software, taking a custom approach was the best solution.

Engine design, integration, and post styling took less than a day to develop, and writing the actual blog posts will be more effort - the right kind of balance when it comes to custom solutions, with a strong focus on the desired outcome.

The blog design, which follows known concepts, is intentionally kept simple. The only novelty in this context was the use of Go. The blog features posts, tags, a tag cloud, and uses Markdown with a JSON metadata header as a storage format:

{...JSON...}
# Markdown

One nice thing about the Go JSON decoder is that it successfully parses a payload and then leaves the file descriptor intact for further use, in this case, the Markdown payload. The gotcha here is to jump to the correct position in the file after the JSON header before reading the second part:

// parse json at beginning of file
post := Post{}
dec := json.NewDecoder(f)
if err := dec.Decode(&post); err != nil {
    return nil, err
}

// set position after json
if _, err := f.Seek(dec.InputOffset(), io.SeekStart); err != nil {
    return nil, err
}

// use remaining data as body
b, err := io.ReadAll(f)
if err != nil {
    return nil, err
}

That is the basic building block of this blog engine, and everything else builds on top of it, with metadata for this very post like this:

{
    "Title": "Blog Engine in Go",
    "Description": "Example of a simple Go and Markdown-based blog engine.",
    "Date": "2024-10-03T12:46:01+02:00",
    "PublicAt": "2024-10-03T12:46:01+02:00",
    "Tags": ["blog", "go", "markdown", "json"]
}
...

On the Markdown side of this is the Blackfriday library used in a template filter to render HTML:

tmpl.Funcs(template.FuncMap{
    "markdown": func(args ...interface{}) template.HTML {
        return template.HTML(blackfriday.MarkdownCommon([]byte(fmt.Sprintf("%s", args...))))
    }
})

The tag cloud is based on this principle and groups the posts by tag, for example. Other features like publishing date and draft mode also get away with very little code.

Still pending is the addition of RSS/Atom feeds, which is a straightforward task with a sound library.

The flexibility and speed of developing a simple blog like this are worth the minimal investment as it effectively takes less time than integrating external solutions.

2024-10-03

Example of a simple Go and Markdown-based blog engine.

blog, go, markdown, json