An Independent Blog using Hugo and Dat

Everyone should have a button on their computer that reads “make a new website”. This is one of the things that the Dat project is working on with the Beaker browser: Making it easy to self-publish content on the web without using centralized infrastructure services from the likes of Google and Amazon.

As I create this blog using Hugo, a static site generator, I thought it should be pretty easy to make it available on Dat. This post will show how to do just that using Hugo and the Dat command line tool. If you are publishing your Blog using the Jekyll static site generator, see this tutorial by Paul Frazee on how to use Beaker browser directly to publish that.


Preface: What’s a static site generator – and what is peer to peer?!

Hugo Static Site Generator

Many blogs are published using software like Wordpress, which runs on a server using a database that holds all of the blog content. In order to let you view a site on that blog, the server generates the HTML for the site on the go and sends it to your browser for viewing.

Hugo on the other hand generates the HTML for all pages in advance. So when somebody wants to look at one of them, the server just sends the readymade HTML bits without generating anything visitor-specific.

The stack of prepared pages that Hugo makes is much easier to distribute in a peer to peer network than the complex Wordpress server.

Dat peer-to-peer network

Peer to peer means that we are the cloud now. Instead of trusting the cloud with your stuff and hoping it will pass it on to other peeps, who want to look your stuff, we can just be the cloud ourselves.

Everyone who visits your site creates a copy of that prepared stack of pages directly from your computer and passes them on if anybody else wants to look at them. Dat makes sure that nobody tampers with the files before passing them on.

1: Create a second target for Hugo’s build process

Let’s get started. So usually Hugo just generates a folder named public, filled with nice static files that I can copy to a public webserver reachable via But now I want it to generate a second set of files with some small changes that will then be available via dat.

To do this, I create a new config file in the project root directory, next to my existing ./config.toml, I call it config-dat.toml.

publishDir = 'public-dat'

This config item defines a new folder public-dat. Now I run

$ hugo --config config.toml,config-dat.toml

to combine my old config with this new one that defines a specific output folder.

2: Make it dat

I can now go to the new output folder and make it a dat. Install the dat command line tool and then run:

$ cd public-dat
$ dat share
dat v13.10.0
Created new dat in /Users/pv/projects/va2018/public-dat/.dat
Sharing dat: 189 files (52 MB)

0 connections | Download 0 B/s Upload 0 B/s

Watching for file updates

I have a dat blog now! Use Beaker browser and go to the address given in the output of dat share and test it. After writing new content in the future and generating the updated site with hugo, changes can be synced by running dat sync in the public-dat directory.

3: Fix base url

You will notice that some URLs on your site still point to the old http version of the site. To fix this, I put the new dat URL into ./dat-config.toml, generate the site again with hugo and publish it on dat.

baseURL = "dat://dce23f011185c7cf536b161e6fb0ab39277ac089e7f5814a6d253327a3db96a5/"
publishDir = 'public-dat'

But the problem is only half-fixed now. Relative URLs now point to the new dat URL, but absolute URLs are broken. They point to a URL that ends with #ZgotmplZ. This is because Hugo only allows linking to http, https and mailto links and therefore replaces all dat:// links with this ZgotmplZ thingy. Damn!

Fixing this is a bit more complicated, but not too bad either. I just need to change all sections of my template files to mark absolute URLs as safe, so Hugo doesn’t “protect” me anymore from using dat.

4: Change template to allow dat:// URLs

Hugo’s template engine uses the .Permalink command to insert a permanent URL link to a given context into the generated HTML. Let’s see which template files use this pattern.

$ grep -rn 'themes/hyde-hyde/layouts/' -e '\.Permalink'
themes/hyde-hyde/layouts//index.html:9:        <h1 class="post-title"><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
themes/hyde-hyde/layouts//partials/list_content.html:6:            <a href="{{ .Permalink }}">{{ .Title }}</a>

It’s just two files. After going to index.html:9 and partials/list_content.html:6 and changing .Permalink to .Permalink | safeURL, these URLs are marked as safe and not filtered anymore when running hugo again.

5: Make a script to generate and sync new content to dat

To make uploading new content to dat easier, I created a small shell script that runs hugo and dat for me. This is placed in in the project root:

hugo --config config.toml,config-dat.toml
cd public-dat
dat sync

6: Increase availability by pinning to

The site is now available through dat as long as dat is running on my computer and sharing my blog’s files. To make it available permanently, I can either ask people to pin my blog in their beaker browser after visiting (see screenshot below) or pin it on

After signing up for an account, I can input my blog’s dat address to make it available permanently.

And that’s it. You now have made your blog available on dat. Keep seeding!