Today was a productive day. I started work on drydock (edit: now superseded by spacedock!)—the custom build–system–slash–static–site–generator that will end up powering Foxspace.

I was initially going to write it in Python, but decided to go with Rust in the end, for multiple reasons. Primarily, I wanted to minimize deployment headaches—I’m a version chaser, and managing updates between the distro package manager, pyenv, and poetry gets tiresome quick. With Rust I can run one command to install rustup and then all I need to do is a quick cargo run.

I did most of the groundwork for preprocessing the Obsidian vault; [[wikilinks]] in my notes get resolved and translated into <a href="...">html links</a>, and I can do various operations on them like building a connectivity graph or finding isolated notes.

The important steps until I can deploy the new Foxspace are:

  • Processing the notes to HTML. Half of this already works, thanks to markdown-rs, but I need to supplement the raw content of the notes with extra metadata:
    • Descriptions (note to self: I can combine meta description with OpenGraph description by using <meta name="description" property="og:description">), lifted from the YAML front matter or—if there’s none—generated somehow from the body text of the note.
    • canonicals with .html–less paths (so e.g. this note should have a <link rel="canonical" href=".../transient/2023-05-18">); duplicated in the OpenGraph og:url property.
    • Open Graph properties. Other than the official reference (linked above), this repo has some stellar examples.
      • Include head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"
      • og:title, duplicating <title>
      • og:description, see above
      • og:url, duplicating the canonical link
      • og:site_name: "Foxspace"
      • og:image—the first image from the note where applicable, otherwise the Foxspace logo.
      • og:image:alt—the alt-text of the first image from the note where applicable, otherwise an appropriate alt-text for the Foxspace logo.
      • og:type"website" for the home page, but "article" for individual notes:
        • article:author: "Fox"
        • article:published_time and article:modified_time where applicable
        • article:tags populated from Obsidian tags
        • article:section, maybe?
    • A list of backlinks with contexts. Much like Andy Matuschak’s notes, every page should have a list of links leading to it at the bottom, with some context surrounding the link. Getting the surrounding text for a link might be a surprisingly difficult problem to solve, since it’d necessitate stripping the HTML.
    • Context for outgoing links, perhaps, so we can have previews like in Andy Matuschak’s notes?
  • Generating the connectivity graphs for notes and tags, imitating Obsidian’s UI. These would probably need to be dumped to JSON and read by Javascript on the page, but I’d like to look into a JS-free solution too. Quartz uses d3.js. I’d like to make the edges thicker based on the link count.
  • Generating tag pages.
  • Syntax highlighting for code blocks. syntect seems to be the way to go.
  • Handling internal non–wiki links properly. I’m really not quite sure what the code currently does with them.
  • Better code documentation. I don’t think there are any docstrings in drydock at the moment, and I bet in a week I won’t be able to remember anything about how it works.
  • Some form of linting. I’d like to get warned if I use features drydock doesn’t support yet, rather than having it spit out bad markup. Off the top of my head, some useful lints would be:
    • Dead internal links (but at the same time, I might want to leave them dead and distinguish them visually (as redlinks?) as a stylistic choice).
    • Dead embeds
    • No date and modified in the front matter—maybe require explicitly using date: for notes that shouldn’t have a publication date.
  • An option to omit selected notes (seedlings) from publishing.
  • An option to omit selected directories (templates) from publishing.
  • Generating an RSS feed.

…And that’s just the backend part! The frontend is going to be its own pile of headaches:

  • It has to work without Javascript as well as possible. Ideally, even animations for page switching would be pure CSS.
  • It has to have no pageloads. Unless running with Javascript disabled, clicking on an internal link should move the previous note out of focus (but still visible) and smoothly bring the new one in view. The browser history and back and forward buttons should still work as expected.
  • Links should have previews. I’ll have to see if it’s possible to do this without JS (which would necessitate generating previews at build time) or if I’ll have to just fetch them asynchronously (which would let me avoid generating them in Rust–space).
  • The aforementioned d3.js graphs need to be at the bottom of the page for navigation.

It’s going to take quite a bit of work. I’m going to go play some Far Cry 6 now.