How I publish on the peer-to-peer Web

Posted on Jan 04, 2018

I publish this website on dat:// and https://. As of January 4, 2018, my publishing workflow involves three tools:

  1. Hugo, a static site generator
  2. The Dat CLI, for publishing updates to the Dat network
  3. dathttpd, for syncing updates from the dat:// version of my website to the https:// version

1. Building my website

This website is a pretty standard static website operation. I use Hugo to generate the markup that composes its pages. I don’t have much to say about Hugo other than it works for me. Jekyll seems like a decent static site generator as well.

If you’re curious to learn more about how Hugo works, the source for this site is at Something worth mentioning is that I don’t use Hugo’s baseURL option and I set canonifyurls = false in my config.toml. This makes it possible to use relative URLs, so whether someone visits the site via dat:// or https://, internal links always follow that protocol choice. For example, an internal link to my blog looks like this:

<a href="/blog">Blog</a>

When I’m ready to publish an update, I run Hugo and it generates a new version of my website in the /public directory.

$ hugo

2. Publishing my website with Dat

I use the Dat CLI to publish and sync updates to my website. You can install dat with npm:

$ npm i -g dat

After generating my website with Hugo, I cd into the /public directory and run the dat command:

$ cd public
$ dat .

The first time I ran the dat command in /public, it created a Dat Archive and minted a new URL. Each subsequent time I run dat in /public, it syncs the updates to the existing URL: dat://6dff5cff6d3fba2bbf08b2b50a9c49e95206cf0e34b1a48619a0b9531d8eb256

3. HTTP mirroring

Currently dat:// is only supported in Beaker (Brave support to come this year), so I need my website to work over https:// too.

Further, dat:// URLs are long and difficult to remember, so it would be nice to be able to access the dat:// version of my site at a shortname like dat:// Luckily, Beaker supports this! Beaker piggybacks off of DNS authentication in combination with the /.well-known convention to enable dat:// shortnames. When you visit dat:// in Beaker, it sends a request to and expects to find a file that looks like this:


Because Beaker can trust the DNS resolution, Beaker can trust that dat:// should point to dat://6dff5cff6d3fba2bbf08b2b50a9c49e95206cf0e34b1a48619a0b9531d8eb256.


Paul and I built a tool called dathttpd that provides HTTP mirroring, sets up TLS with Let’s Encrypt, and configures dat:// shortnames.

To get started with dathttpd, you’ll need a server with Node.js and npm installed. Something like a Digital Ocean droplet or an EC2 instance will work. You should follow the complete dathttpd instructions if you decide to use it, but here’s a short list of tasks that are easy to forget:

  • Configure your DNS records to have A record that points to your server’s IP address
  • Make sure ports 80 (HTTP), 443 (HTTPS), and 3282 (Dat) are open on your server
  • Write a configuration file at ~/.dathttpd.yml. Here’s mine:
  http: 80
  https: 443
  agreeTos: true
    url: dat://6dff5cff6d3fba2bbf08b2b50a9c49e95206cf0e34b1a48619a0b9531d8eb256

After installing and configuring dathttpd and daemonizing the process (I use pm2), your server will do the following:

  • Remain active in the peer-to-peer swarm for the dat:// version of your site, so there will always be an active “seeder” hosting its files
  • Listen for updates to the dat:// version of your site, and sync them to the directory that composes the https:// version of your site
  • Serve the https:// version of your website


Here’s what I do to publish an update to my website:

  1. Type some new words on my blog
  2. Run hugo in the top-level directory of my website’s source
  3. cd into /public and run the dat command

That’s it! My server automatically syncs the updates using dat:// and the changes are propagated to both dat:// and within seconds.

Let me know if you try out this workflow! I’m @taravancil on Twitter and I hang out in #beakerbrowser on freenode. I’d love to hear how it goes for you, or offer a helping hand if you run into trouble.