Building Evergreen Markdown Notes
Some of the more traditional approaches to taking digital notes work quite well in 99% of cases - I think most of the tools on the market are doing a marvelous job. But I often caught myself needing something more, specifically for notes that I wanted to write once and frequently refer to later (e.g. details about specific projects that don’t change often). Dedicated note applications are great for in-flux notes that need handwriting, exploration, random images, but are a bit unwieldy when it comes to managing content in a highly-structured manner. Clearly, my time building docs.microsoft.com1 had an influence on my authoring preferences - I needed Markdown.
I’ve already been a heavy user of Hugo2, so I thought I could re-purpose it for knowledge management, because why not. Lucky for me, someone much more skilled and knowledgeable than myself has already crafted the perfect theme for this - Docsy3. This theme structures all raw Markdown notes in a way that makes it look like you’re reading a technical documentation website (which, I can only assume, was the original intent of the theme).
Just like I did with DocFX back in the day, I wrapped the entire thing in a Docker container, and the Dockerfile ended up being much shorter than I originally anticipated:
FROM ubuntu:20.10
SHELL ["/bin/bash", "-c"]
EXPOSE 1900
RUN apt-get update \
&& apt-get install nodejs --yes \
&& apt-get install npm --yes \
&& apt-get install wget --yes \
&& apt-get install socat --yes \
&& apt-get install git --yes \
&& mkdir hugotools \
&& cd hugotools \
&& wget https://github.com/gohugoio/hugo/releases/download/v0.79.1/hugo_extended_0.79.1_Linux-64bit.deb \
&& yes | dpkg -i hugo*.deb \
&& hugo version \
&& mkdir site \
&& cd site \
&& hugo new site . \
&& rm -rf content \
&& rm -rf config.toml \
&& npm install -D --save autoprefixer \
&& npm install -D --save postcss-cli \
&& git clone --recurse-submodules --depth 1 https://github.com/google/docsy.git themes/docsy \
&& echo -e "socat TCP-LISTEN:1900,fork,reuseaddr TCP:localhost:1313 &\n cd hugotools/site\nhugo server --buildDrafts" >> build_notes.sh
ENTRYPOINT ["sh", "/hugotools/site/build_notes.sh"]
You can always get the most up-to-date script from the GitHub repository.
So what’s going on behind all this spaghetti of bash
commands? Not a lot, actually.
- Installing required Node.js dependencies.
- Downloading and installing the latest release of Hugo4.
- Initializing a new site folder inside the container.
- Removing placeholder configuration and content.
- Installing
npm
dependencies that are required for Docsy. - Cloning Docsy in a local themes folder.
- Creating an entrypoint script on the fly that creates a port binding and builds the site.
That’s it. To build the container, run the following command in the folder with the Dockerfile:
docker build .
Once built, you can bootstrap a new container based on the newly-created image:
docker run -it -p 1900:1900 -v /D/content:/hugotools/site/content -v /D/config.toml:/hugotools/site/config.toml <YOUR_IMAGE_HASH>
This last command maps the exposed port to a local port, and then mounts two items - the directory with content (all Markdown files), and the existing Docsy configuration file, that you can model after the one in their example repository.
One caveat, and this is a problem that I need to still figure out how to solve - on Windows, live file updates are not caught by Hugo, so you need to re-build the notes every time the container starts. This is not a problem with mounted directories and files on macOS and Linux. But other than this - it’s a reliable and scalable solution to managing notes in Markdown with a good theme that renders the content for you like a full-blown documentation site.
You can check out the video I put together for a quick overview:
-
This is one of the biggest technical documentation sites on the planet. I’ve worked on it a bit short of 5 years. ↩︎
-
Among other things, this is the engine my blog is running on. ↩︎
-
Can be downloaded here: https://www.docsy.dev/ ↩︎
-
You can always grab it here: https://github.com/gohugoio/hugo/tags ↩︎