# my-old-man: Adventures in using mdoc(7) as the markup for this site

_Published: December 30, 2020_

*Update:* As of December 2021, I've moved to a
[new markup format](/blog/mdoc-to-nihdoc.html).
For a glimpse at what the format discussed looks like, here's
[the original post](/blog/my-old-man-orig.html).

       Uh oh,
       looks like,
       I'm seeing more of my old man(1) in me
           ~ Mac DeMarco (added (1) by me)

## Description

While Mac wasn't talking about good old roff-style man pages, I
felt his words were a fun description of my effort to move from a
markdown based templated site to a
[`mdoc(7)`](https://man.openbsd.org/mdoc.7) based site.

After pointing out that
[I really did](https://git.sr.ht/~akarle/alexkarle.com/commit/844441fce7ac5c0364b3fe1a217da6889cb937ba)
rewrite my site in `mdoc(7)`, you might be wondering why I would do this.
This blog post is intended to answer just that.

## Why

### For the learning experience

The single biggest motivator of the rewrite was that I like to use
this site as a playground for learning new (old) technology, and
`mdoc(7)` was on my list of tech to learn.

What better way to learn a new markup language than to port an
existing project to use it?

I had a blast transferring my old posts and coming up with a new
build system.

### For the look

I really enjoy a good [`man(1)`](https://man.openbsd.org/man.1) page.

You've probably heard it before, but I'll say it again: one of the
best parts of using OpenBSD is its concise and comprehensive man
pages in the base system.

There's a certain warm fuzzy feeling when you can learn something
both without internet access and with the knowledge that it is the
authoritative source.

I want my site to be a homage to good, well thought out, `man(1)`
pages.

### Keeping it all in base

As an OpenBSD nerd, I find a bit of joy in having a site which is
built, deployed, and served all via the base OpenBSD system.

By using [`mandoc(1)`](https://man.openbsd.org/mandoc.1) instead of
Markdown.pl, I can now build my site without any additional
dependencies.

Better yet, `mandoc(1)` is ported to the various Linux distros I use
day to day, and it is fast.

## How

If you read this far, I thought you might be interested to hear how
I'm deploying the content.

I'm a big fan of automation, so I've rigged up the site to deploy
on a push to the master branch.  Doing so involved two steps.

### Building the mdoc

I created a small Makefile that builds each HTML file from each man
page source.

The relevant bit is the implicit suffix rule to convert each `.7`
file to `.html`:

       SUFFIXES: .7 .html
       7.html:
               @echo "mandoc $<"
               @mandoc -Thtml -O 'man=%N.html;https://man.openbsd.org/%N.%S,style=style.css' $< \
                  | sed 's#</head>#<meta name="viewport" content="width=device-width,initial-scale=1">&# ' \
                  > $@

This looks crazy, but it's not too complex.  First, know that `$<` is
the source (the `<name>.7` page), and `$@` is the target (the
`<name>.html` page). The `@` prefix is a bit of magic to suppress
printing the command run (so that all the output shown on git-push
is just a single "mandoc" line for each file updated).

Moving on to the mandoc command, I use the html output of mandoc
via `-T,` with the `-O` switch specifying that linked man-page
references should look locally first, then to point to
man.openbsd.org.  This allows me to quickly reference OpenBSD base
tools and pages, while also using the terse `.Xr` macro for linking
individual site pages.

Finally, I use a `sed(1)` oneliner to splice in a <meta> viewport tag
for mobile devices.

And that's really it!  The rest is just listing the man pages I
want built, with a phony default target depending on the html pages
so that a `make` builds them all.

### Deploying via git hook

Since I'm self-hosting git on the same server as the website, it's
trivial to deploy when it receives a push by leveraging git hooks.

For the unfamiliar, git hooks are simply shell scripts that are
triggered by specific git actions. In this case, I used the
post-receive hook to publish after the refs were updated via a `git
push`.

More specifically, I added the following to `<git-dir>/hooks/post-receive:`

       echo "Deploying to to /var/www/htdocs... "
       WT=/var/www/htdocs
       git -C ${dir} --work-tree=${WT} checkout -f master
       make -C ${WT}
       echo "done"

So, on any push, it checks out the entire source tree into the
webserver's content area and rebuilds only the necessary HTML files
(thanks to `make(1)`).

If I had files I didn't want served, I would modify it to build
elsewhere and copy the contents to `/var/www`; however, I'm
publishing both the source for the site and the git history at
[https://git.alexkarle.com], so I don't see any harm to having the
README.md accessible from the root.

## See Also

- [githooks documentation](https://www.git-scm.com/docs/githooks)

[Back to blog](/blog)