đł How I Publish My Zettelkasten
Assumed Audience: In writing this piece, I assume you have enough interest in publishing your own notes online that youâre looking for a detailed step-by-step of how I do things. I also assume that your interest is primarily on the âhowâ and less on the âwhyâ.
If you visit person-al.github.io, youâll see a slice of my personal Zettelkasten (or the slip-box). Itâs a note-taking method I use that focuses primarily on small, atomic notes that you build on and connect slowly over time into larger and more complex projects. By publishing even the smaller notes online, my goal is to lower the barrier to conversation and learning for myself.
Because I use Obsidian for my notes, Obsidian Publish is a built-in option I could use. However, I wanted to experiment with my own system first. The instructions that follow work for anyone who has local markdown notes. Hereâs the rough outline of how my system works:
Now, letâs walk through it:
set-up steps
Set up is pretty easy and took 3 steps:
- Set up a Github Pages account with a basic website and theme.
- Create a folder in your vault that contains everything you want published
- Set up obdye
1. set up Github Pages
Github Pages is just one option for hosting your blog. You can use something completely different and follow all the other steps in this post if youâd prefer. The steps further down assume:
- that your blog posts exist in markdown in a folder on your computer, and
- that you use jekyll or hugo to generate your site. If youâre not using jekyll or hugo, all of these steps except obyde will work without modification. With minor modifications, obyde should work as well.
I wonât go into details on how I set up my Github Page, the most up-to-date instructions will be here. For my blog, I went with the no-style-please theme, as I wanted a theme as simple and Craigslist-like as possible. Youâll notice that I copied the styleâs css into the project so I could customize it. The biggest modification I made was to remove their dark-mode support from the css file and import water.css for dark-mode instead. No-style-please implements dark-mode itself by inverting all the colors except image colors. This worked well 99% of the time, exceptâŚemoji colors would get inverted. While I could have tried to fix it, it didnât feel worth it. My goal was simplicity, not dependency elimination. Water provides a more aesthetically pleasing dark-mode as it is, which felt worthwhile.
2. set up your folder
Unless you want 100% of your vault published at all times, youâll want to set up a specific folder in your vault that contains blog posts. Name the folder however youâd like and I recommend adding two subfolders: one for drafts and one for assets. This is optional, but Iâve found it useful to have everything meant for publishing in one place.
3. set up obyde
Obyde is the secret sauce holding my blog together and I highly recommend it if youâre using markdown and jekyll/hugo. khalednassar, the developer, responds quickly and amenably to questions, pull requests, and bug reports. They deserve major kudos for this tool.
Obyde takes a markdown file with frontmatter in one folder and converts it to a jekyll blog post file in another folder. The instructions for setup are here. Note that under the usage section where it describes the config file, youâll want to list the assets sub-folder in your vault and list your drafts folder under excluded_subdirectories
.
What Iâve done is keep the obyde config file in my GithubPages repo, but add it to my .gitignore
. The benefit is that all of the code related to my blog is in one place (the GithubPages repo), but the relative path to my vault and specific folder names in my vault are not published on the internet.
Now youâre ready to publish!
publishing steps
- Create a note with all the metadata needed for Jekyll and store in my blog folder
- Run obyde script to convert vault files into blog posts
- Push changes to blog to GitHub
1. create your note
Create a note in the blog subfolder of your vault. It can really look like anything at all, the only requirement is that it have the date frontmatter so that obyde can convert it to a jekyll-style post file. This is the only change youâd need to make in order to use obyde without using jekyll or hugo. Youâd either need to modify how obyde sets the post title to avoid needing the date frontmatter or, more reasonably, just add the date frontmatter regardless of whether your blog system needs it or not. Once youâve made a few blog posts this way and have a better sense of what matters to you, consider using templates.
2. run obyde
Running obyde the standard way is a one-line command. However, Iâve created a script to run obyde against my vault. So once Iâve finished making my note and putting it in my blog older, I just need to run the script. Part of the Zettelkasten approach means that my posts get updated and modified constantly, so just running obydeâs default script isnât enough. Youâll notice in the script that I delete all my posts and then run obyde so that it catches all the changes in my vault. Because my blog is also a github repo, I can use regular git tools like git status
or git add -p
to see whatâs changed in already-published posts and make sure those changes are what I expected.
Once youâve run the obyde script, you should see a bunch of posts in your blogâs posts folder. Take a look and make sure everything is as you expect it to be.
3. push to Github
The beauty of Github Page is that updating anything about your blog is a push away. Commit and push your changes and your blog will rebuild within minutes.
Congrats! Youâve just published your Obsidian vault. Now go forth and create away! After youâve made a few posts, feel free to come back and check out the âextra goodiesâ below where I discuss how handle intermediate use-cases like templates, hiding private notes, and connecting with the decentralized web.
Have fun posting!
extra goodies
Once youâve made a few posts, youâll probably need one or more of the following goodies:
templates are your friend
While the date is the only required field in your postâs frontmatter, you likely have others that matter to you. The layout, the category, tags, etc. From that perspective, templates are your friend. Whether itâs Obsidianâs built-in template tool or the Templater plugin or your own third-party template system, I recommend setting up a template so consistent blog post formatting is only a hot-key away. My template looks something like this:
---
layout: post
category: đ¨ď¸|â|đ°|đą|đł|đ˛
title: "<% tp.file.title %>"
date: <% tp.file.creation_date("YYYY-MM-DD") %>
---
Youâll notice that it sets required jekyll metadata like the layout and the date, as well as optional metadata that matters to me, like a list of categories for me to choose from.
The reason I add the title to the metadata is because of a difference in how jekyll titles notes vs. your computer. In Zettelkasten, your note title is often the thesis of the note. Youâll see this in my blog with lengthy post titles like đ° recognition matters - human beings need to feel understood. Itâs almost what youâd expect from a blog title but significantly more specific and more likely to use punctuation. Jekyll, however, doesnât support punctuation in file titles. Which means if my file name is đ° Iâm struggling with a piece about business writers.md, jekyll will rename that to i-m-struggling-with...
, which will then get converted to the title âI m struggling withâŚâ, with a weird space where the apostrophe should be. I get around this by adding the title
metadata to the frontmatter automatically. That way jekyll never accidentally skips punctuation. The downside is that every time I change the title of a published blog post, I have to update the title
frontmatter as well. But itâs worth it for me.
Template or no, just make sure you have the date
frontmatter as obyde needs it to convert your file to a jekyll-compatible blog post.
hiding parts of notes
Sometimes, you want to publish a note without publishing all of a note. Maybe you reference a person or a place that youâd prefer not to publicize, or maybe you just have a way of formatting things in your vault that will confuse public readers. Take, for example, a post like đ¨ď¸ A dog always bit deepest on the veterinary hand. In my case, itâs just a simple quote, but in someone elseâs vault it might be accompanied by an MLA citation or a longer journal entry. This is where obydeâs find-and-replace feature shines.1
Find-and-replace works exactly how it says on the tin. I use it liberally. My actual post template looks something like this:
---
layout: post
category: đ¨ď¸|â|đ°|đą|đł|đ˛
title: "<% tp.file.title %>"
date: <% tp.file.creation_date("YYYY-MM-DD") %>
find: ["find\\:\\n(- .*\\n)+","replace\\:\\n(- .*\\n)+","LEAVE_OUT\\:.*($|\\n)","tags-for-github"]
replace: ["","","","tags"]
tags-for-github:
---
A few things to notice:
- I use the list format instead of the âevery lineâ format. This is marginally worse than the every line format in that itâs much harder to count and match the
find
line elements with thereplace
line elements. But itâs marginally better in that it compresses that long list above to 4 lines instead of 10 lines. - I remove the find and replace lines themselves from the published piece. Because whatâs the point in changing things if Iâm going to publish exactly what changed lol. Youâll also notice here how regexes can be used. If you donât know what regexes are, suffice it to say that
find\\:\\n(- .*\\n)+
is telling obyde âI want you to find a line that starts withfind:
and is followed by a series of bullet points after it. And then remove all of that.â2 - An example of removing things: any line that begins with
LEAVE_OUT:
will not be put in the final blog post by obyde. That allows me to say, mention my mother in a relevant note while preventing such a mention from making it to the world wide web. - An example of reformatting: I donât use Obsidianâs tags for categorizing. But I do want to use tags in jekyll. So instead of putting
tags
in my frontmatter, which Obsidian would pick up on and use, I instead havetags-for-github
, which obyde smart-converts totags
when making the final blog post.
It takes some understanding of regexes to properly use the find-replace feature, but I highly recommend using it if you want to keep one vault and publish only a segment of it. The alternative, of course, is to have a separate vault that gets published. In that case, find-replace is unnecessary.
joining the IndieWeb
By posting a blog, youâre already part of IndieWeb! IndieWeb is a decentralized consortium of personally-owned blogs. Itâs a community dedicated to helping you own and manage your content.
Corporate silos like Facebook and Twitter benefit from their proprietary formatting and following systems. Facebook knows exactly how to notify you when someone likes a post you follow, etc. With the independent web, there are some standards folks use to bring some of those benefits to a decentralized publishing ecosystem. Thatâs where the IndieWeb shines. I recommend going through the list of tools to see which make sense for you. Iâve made it through Level 2, which means I finished getting webmention reception support working! I donât yet display webmentions on the site, but perhaps thatâs something I can work on soon.
Info:
-
Find-and-replace came about from me needing to optionally hide or reformat parts of my notes as described above. I made it work, put it in a pull request, and khalednassar kindly reviewed it and merged it in. If youâre not a developer, this is kind of like if khalednassar had written a 10-chapter novel in a public place with a note that said âplease add to thisâ. And then I came along with a new chapter and said âYo, check this out, it fits right between chapters 4 and 5.â And then khalednassar had to proof-read my addition and make sure the new version of the novel was still cohesive and worth reading. On the one hand, the whole beauty of public Github repos is that someone can come add new functionality to your work. But on the other hand, managing code suggestions from other people is hard and much kudos to khalednassar for being open to it. ↩
-
This regex isnât perfect. If one of the items in the find-replace list spans more than one line, this regex canât catch that. I havenât figured out what to do about that yetâŚÂ ↩
Every post on this blog is a work in progress. Phrasing may be less than ideal, ideas may not yet be fully thought through. Thank you for watching me grow.
