Generating a Gopher site with Hugo

March 14, 2019 · 4 minute read

Posted in: hugo gopher retrocomputing

This blog is produced with hugo, a static site generator, and the articles are written in Markdown, a plain text markup format. Since the articles are fundamentally plain text, for some time I’ve been wanting to make them available over gopher, a simple protocol that was created around the same time as the first versions of the World Wide Web. I used gopher before I used the WWW in Lynx and Mosaic, and even after the web was dominant, I used GNOFN’s free dial-up gopher as my access point to the internet. Gopher is currently undergoing a renaissance, partly driven by disgust with the current state of the WWW, and there is a thriving community of phloggers, people writing blogs and serving them over gopher.

Hugo configuration

config.toml (site config file)

I created a custom output format by adding this to my config.toml:

  home = ["HTML", "gopher", "RSS"]
  section = ["HTML", "gopher", "RSS"]
  taxonomy = ["HTML", "gopher", "RSS"]
  taxonomyTerm = ["HTML", "gopher", "RSS"]
  page = ["HTML", "gopher"]

  mediaType = "text/plain"
  baseName = "gophermap"
  isPlainText = true
  protocol = "gopher://"
  noUgly = false

This says to keep generating HTML and RSS in the same places as the default configuration, but also generate gopher maps and plain text files for everything. The one caveat here: the gophermap for the home directory is going to be named ‘gophermap.txt’ rather than ‘gophermap’, and the gopher server will have to be configured accordingly.


I needed to make three templates in order to get the gopher output format to actually generate anything: one for the one page, one for list pages, and one for articles. If you copy and paste these, you will probably need to manually re-insert the tabs in the gophermap lines, because they will have gotten mangled by Markdown->HTML->browser.


!{{ .Title }}

{{ .RawContent }}

Site sections:
{{ range .Site.Menus.main }}
1{{ .Name }}	{{ .Identifier }}	{{ $.Site.Params.hostname }}	70
{{ end }}

Most recent articles
{{ range first 3 .Pages.ByPublishDate.Reverse }}
0{{ .Title }}	{{ with .OutputFormats.Get "gopher" -}}{{ .RelPermalink }}	{{ $.Site.Params.hostname }}	70 {{ end }}
{{ end }}


!{{ .Title }}

{{ .RawContent }}

{{ range .Pages.ByPublishDate.Reverse }}
0{{ .Title }}	{{ with .OutputFormats.Get "gopher" -}}{{ .RelPermalink }}	{{ $.Site.Params.hostname}}	70 {{ end }}
{{ end }}


# {{ .Title }}

{{ .Date.Format (.Site.Params.dateform | default "January 2006") }} · {{ .ReadingTime }} minute read
{{ if .Params.tags }}      
Posted in:  {{ range .Params.tags }}{{ . }} {{ end }}
{{ end }}
{{ .RawContent }}

Running hugo

I have to run hugo a separate time to generate my phlog, because it has to run with a different option from my blog. It needs the uglyURLs option set, while my blog needs it unset. That could be set in config.toml, but I use it on the command line.

Setting up the gopher server

I chose to use gophernicus as my gopher server, because it was easy to set up with systemd and seems to be popular. The only tweak to the default configuration was that it has to be started with -d gophermap.txt, so it knows to look for the gophermap in the file by that name (with the .txt extension).

Changing the way I write Markdown

In writing my blog, I’ve been used to soft-wrapping lines in my Markdown files. That is, each paragraph is a single line of text, and my editor (emacs) displays the long lines as paragraphs. This is nice for version-control purposes, as changes within a paragraph only change one line and don’t introduce irrelevant formatting changes. But gopher clients often don’t line-wrap, or don’t do it well, so it’s better for me to hard line wrap my source files at less than 80 characters.

I’ve also gotten used to the [title](link) style of links. I need to get back into the habit of footnote-style links, because they look better when reading the Markdown source as text.


So, my blog is now also available as a phlog! A lot of the existing stuff isn’t formatted that greatly on gopher, and I may or may not put in the effort to clean that up. But I was impressed with how little work it really took to make this gopher site.

Share on Mastodon | Follow on Mastodon