Creating a blog using Obsidian and Hugo
#development #hugo #obsidianI’ve been a big advocate for using Obsidian for my notes lately. It allows me for distraction-free writing in easy markdown syntax and alongside that it has great features to organize the things I’m writing about.
Since, I like Obsidian so much, I thought to myself if it would be possible to use it for writing a blog. Turns out that it’s a pretty good solution.
Introducing Hugo, a static site generator that generates websites out of markdown files.
If you:
- are using Obsidian for writing down things;
- want a simple and low cost solution to host a blog;
- enjoy tinkering a little bit;
Then this setup might serve you as well as it serves me!
1. Preparation
There is a little bit of technical setup with this, but bare with me, once it’s done, it’s actually very simple to manage.
1.1 Creating a Hugo Site
First of all, I installed Hugo. Then created a new site:
hugo new site blog
And initialized a git repo:
cd blog
git init
1.2 Creating an Obsidian Vault
So now, inside of the Hugo site directory I created an Obsidian Vault. I called it vault.
Once done, this is how my directory structure looked:
blog
├── archetypes
├── assets
├── content
├── data
├── hugo.toml
├── i18n
├── layouts
├── static
├── themes
└── vault
2. Configuring Hugo
Now I configured Hugo to actually build and serve a website.
2.1 Adding a theme
For the Hugo website to look like a website from a get go, I needed a theme. I started with hugo-starter-theme. It’s very simple as a baseline to understand how Hugo themes even work and can easily be customized later on. If you prefer something else you can check out a hugo theme gallery and pick one you like.
git submodule add https://github.com/ericmurphyxyz/hugo-starter-theme.git themes/hugo-starter-theme
Then, I edited hugo.toml to enable the theme I just installed.
echo 'theme = "hugo-starter-theme"' >> hugo.toml
To check if it worked I executed:
hugo server
This started up a Hugo development server on http://localhost:1313. It indeed was working, the website (although very empty) was there!
3. Configuring Obsidian
After configuring Hugo, I started configuring Obsidian Vault to be more comfortable to use.
3.1 Creating a directory structure
I created a folder named posts to keep all of my blog posts in there, I also made a static folder for any of the static files (images, videos etc.).
3.2 Creating a blog post template
Obsidian’s built in templating function, makes it easy to define a format for your blog post. First, I created a folder called Templates after that I navigated to Templates > Template Folder Location inside of the options and set it to the folder I just made.
Once this is done, I created a following template inside of the folder:
---
title: "{{title}}"
date: "{{date}}T{{time:HH:mm:ssZ}}"
tags:
categories:
draft: true
---
This is a template for a blog post
This generates a simple blog post that has all the necessary front matter for Hugo to understand. You can add additional parameters here that can be used by Hugo in here as well, all easily settable from within Obsidian!
3.3 Creating a post
With that template ready to go I added my first note in the posts/ directory. I gave it a title Hello World and used a template to populate it. I unchecked the draft property and wrote some things inside. I also created _index file on the top level of the vault to serve as a homepage.
4. Putting it all together
Now that I configured both Hugo and Obsidian, I had to actually make them work together. This is where obsidian-export jumped in! This simple CLI tool is going to export the notes from Obsidian to Hugo.
4.1 Installing and configuring obsidian-export
So I first installed obsidian-export. After that I created .export-ignore file inside of my vault and propagated it with following contents:
Templates/
This is going to tell obsidian-export not to export the templates to the content folder. After that I run:
obsidian-export ./vault ./content
This exports the vault contents into the content folder, that Hugo uses to build a website.
4.2 Fixing Links in Hugo
There is one more thing that I had to changed before it all started to work together.
I created the following files in layouts/_default/_markup/:
render-link.html with following contents:
{{- $url := urls.Parse .Destination -}}
{{- $scheme := $url.Scheme -}}
<a href="
{{- if eq $scheme "" -}}
{{- if strings.HasSuffix $url.Path ".md" -}}
{{- relref .Page .Destination | safeURL -}}
{{- else -}}
{{- .Destination | safeURL -}}
{{- end -}}
{{- else -}}
{{- .Destination | safeURL -}}
{{- end -}}"
{{- with .Title }} title="{{ . | safeHTML }}"{{- end -}}>
{{- .Text | safeHTML -}}
</a>
render-image.html with following contents:
{{- $url := urls.Parse .Destination -}}
{{- $scheme := $url.Scheme -}}
<img src="
{{- if eq $scheme "" -}}
{{- if strings.HasSuffix $url.Path ".md" -}}
{{- relref .Page .Destination | safeURL -}}
{{- else -}}
{{- printf "/%s%s" .Page.File.Dir .Destination | safeURL -}}
{{- end -}}
{{- else -}}
{{- .Destination | safeURL -}}
{{- end -}}"
{{- with .Title }} title="{{ . | safeHTML }}"{{- end -}}
{{- with .Text }} alt="{{ . | safeHTML }}"
{{- end -}}
/>
This fixes image embeds and recursive links.
4.3 Building the website
After all of that setup we can finally run:
hugo build
This is going to prouduce public/ folder with the generated static site that you can serve using any web server!
5. Final Thoughts
This setup takes a little bit of tinkering and knowledge around command line, but once setup it’s really simple and painless to manage. You can read more about what Hugo can do in the documentation.
Where to go from here?
For example, you could deploy that static site using Codeberg Pages or write a Dockerfile to build a container that could run anywhere! Sky is the limit! More posts about it in the future.