(DIR) Josip Tišljar Mataušić (9A3SFZ)
Published on: 2026-05-30
Gopher is an old protocol for sure, but being old, it's also very
minimal, making it perfect for browsing on low-bandwidth connections.
However, it doesn't use HTML, instead, it uses its own, also very
minimal, format called Gophermap.
Gophermap structure
!This is a title
sA link to an Audio file TAB /audio.mp3 TAB gopher.radioz.org TAB 70
||---------------------| |--------| |---------------| |--|
| Visible text Destination path Destination host Port
|
Tells the client what file type to expect - a sound file
iOrdinarry text (not a link) TAB /this TAB can.be.anything TAB 9258
||-------------------------| |------------------------------------|
| Visible text Ignored, but still required
|
Denotes plain text, as oppose to a link
As you can see, this is quite different from HTML. Even if I
converted all of my markdown posts to Gophermaps there was no way I
was going to maintain two versions of every article!
Therefore, I decided to make a program that will read existing posts,
automatically convert them to Gophermaps, generate the Latest and
Related sections, add the date of publication and everything else.
My goal was to have the same level of automation for Gopher as I have
for the Web, so that publishing to Gopher doesn't become a chore.
Furthermore, I wanted to be able to substitute <script> tags, which I
often use to integrate various calculators to posts, with server-side
PHP scripts that will provide the same kind of functionality on
Gopher.
This all led me to create a complex stack of scripts to achieve
exactly what I wanted. Some of them are written by me, some of them
are not.
Markdown --> Gophermap
I only found one program[1] that can convert markdown directly to a
gophermap in a reliable way, however, I wasn't satisfied with how it
handled converting inline links to footnote links. After many more
searches that yielded nothing, an idea struck: Okay, there are no
good markdown to gophermap converters, but what about markdown to
gemtext converters?
(HTM) 1: https://github.com/theobori/lueur
For those unfamiliar, Gemtext is another "hypertext" format. It's
similar to gophermaps in terms of features. (the main difference
being that Gemtext also supports subtitles and code blocks).
I found exactly what I wanted, md2gemini[2] nicely converted inline
links to footnotes. Now I just had to write a simple script that can
convert gemtext to gophermap. This is a lot simpler than writing a
script that deals with markdown directly. I completed the task in a
couple of hours.
(HTM) 2: https://github.com/makew0rld/md2gemini
If you want to use the script yourself here it is[3]. It's built so
that you can pipe output from md2gemini directly to it:
(HTM) 3: https://git.radioz.org/pisoj/gemtext2gophermap
md2gemini -l paragraph -f -a -p my-post.md | ./gemtext2gophermap -
gophermap
As per the readme, this script also handles injecting gopher specific
content into the final gophermap.
Generating Latest and Related sections
Now that I figured out how to convert markdown posts to gophermaps,
it was time for making another script that would put all of that
together. This was hard because there is no static-site generator for
Gopher. It also didn't help that I chose to write the script in Bash
for some, yet undiscovered, reason.
A list of all the things the script had to do:
- Extract metadata from the header of a markdown file
- Put the title, author, date of publication, date of last update and
- a list of other languages at the beginning of every post
- Convert paths that Astro normally handles (like ../../assets) to
- the ones Gopher can handle
- Figure out which posts should have a link in the main menu
- Generate Latest, Related and Featured sections at the end of every
- post
If you want to take a look at the strange regexes I used to parse
markdown and yaml, as well as everything else mentioned in the list
the script is here[4].
(TXT) 4: /process-file.sh
At the end, I used a Makefile to streamline the process of installing
md2gemini and gemtext2gophermap, as well as to run the aforementioned
script on every post.
Supporting multiple domains
I still do not have the ability to BGP peer on Hamnet so I'm stuck
with addresses they give me through vpn.hamnet.network. This means
that I need two separate domains, one pointing to Internet addresses
and another one pointing to Hamnet addresses of the server.
Doing this on the Web is easy, you just have a link like /about and
the browser will preserve the domain. On Gopher, however, every link
needs to specify a domain and a port, even if those do not change.
Luckily, my server of choice[5] automatically adds the domain and
port at the end of every line. This means that I can leave it up to
the server to decide which domain a link will point to.
(HTM) 5: https://github.com/gophernicus/gophernicus
But how can the server know which domain a client uses? There is no
Host header in Gopher. - Simple, not only are the domains different,
but IP addresses are as well, so I can have one server instance
configured for the Internet domain and bound to the Internet IPs and
another instance configured for the Hamnet domain and bound to Hamnet
IPs.
Of course, this is only possible if your server has multiple IP
addresses, if it doesn't, well, you're out of luck. (Yet another
reason to push for IPv6)
Accessing RadioZ via Gopher
To access Gopher, you need a Gopher client. Common ones include:
- Lagrange[6] (Win/Mac/Linux/Android/iOS)
- Kristall[7] (Win/Mac/Linux/BSD)
- Gopher Browser[8] (Windows)
- Gophie[9] (Win/Mac/Linux)
- Bombadillo[10] (Linux/BSD) (no-GUI)
(HTM) 6: https://gmi.skyjake.fi/lagrange/
(HTM) 7: https://kristall.random-projects.net/
(HTM) 8: https://www.jaruzel.com/gopher/gopher-client-browser-for-windows/
(HTM) 9: https://gophie.org/
(HTM) 10: https://bombadillo.colorfield.space/
You can also use a Gopher to Web proxy[11].
(HTM) 11: https://portal.mozz.us/
--------------------------------------------------------------------------------
In any case, these are the URLs:
(DIR) gopher://gopher.radioz.org
(DIR) gopher://hamnet.gopher.radioz.org
Related
(DIR) 2026-04-27 Test your HAMNET IPv6 setup
Latest
(DIR) 2026-05-06 Easy IPv4 to IPv6 proxy
(DIR) 2026-04-27 Test your HAMNET IPv6 setup
(DIR) 2026-03-29 IPv6 on HAMNET with 6to4
(DIR) 2026-03-22 AMPRNet IPIP with systemd-networkd
--------------------------------------------------------------------------------
(DIR) Home
(DIR) Logbook