I've been practicing Zettelkasten for the past five years and still haven't found anything better than Niklas Luhmann's method. The problem is that Obsidian doesn't support it out of the box, so I had to write a plugin for organizing notes as close to Luhmann's original method as possible.

I spent a couple of weeks digging through Luhmann's original archive before I understood how it actually works. Structurally, the archive resembles a table of contents, but with the difference that a note can be inserted at any point, adding nested chapters.

- 9/8
	- 9/8a
		- 9/8a1
		- 9/8a2
	- 9/8b
		- 9/8b1

Each note served simultaneously as an entry and a potential folder for child entries. In the paper-based system, this was achieved through a complex numbering scheme.

What Luhmann's archive might look like in Obsidian
What Luhmann's archive might look like in Obsidian

In essence, it is an analog of a modern file system — one that also supports symbolic links. This means each note can have multiple "parents."

To implement this in Obsidian, I had to create my own plugin — VirtFolder.

The same structure can be represented schematically like this:

VirtFolder

After installing the plugin from the Obsidian community store, you are greeted with a window labeled ROOT. You can right-click on it straight away to create a couple of notes. Notes without a parent folder are placed in the virtual Orphans folder. Top-level notes (those that have children but no parent) go into the ROOT folder.

The latest version of the plugin supports drag-and-drop for notes. You can also control the plugin entirely from the keyboard. To do so, assign hotkeys to all available commands: moving a note to a different folder, revealing the active note in the tree, and so on.

The physical location of notes on disk doesn't matter. The structure relies on YAML metadata. By default, the Folders field contains a link to the parent entry. The plugin scans all notes at startup, building an internal database. Whenever a note is added or removed, the database is updated and the tree view is rebuilt accordingly.

Solving naming conflicts

Obsidian stores notes as plain Markdown files on disk. This is convenient when you need to process them with scripts, but it creates a problem when names collide. For example, I create a note called TODO and attach it to the current project's folder. At some point I'll want to create a note with the same name for another project, but the file TODO.md already exists on disk! To solve this problem, VirtFolder supports the Unique note creator and Front Matter Title plugins.

The first plugin lets you create notes with unique names from a template file. It names notes by their creation timestamp, for example 202602151803.md, which eliminates naming conflicts. The second plugin displays the note's title from the title field in YAML. The tree will render fine without it, but it's more convenient when you can search for notes by their YAML title.

Settings

The plugin is highly configurable: YAML field names in any language, title display by file name or from YAML, note sort order within a folder, ignored folders (notes from which are excluded from the database), link format, and a delete confirmation prompt.

Conclusion

The sole purpose of my plugin is to help people like me organize a private knowledge base. I've tried many approaches, but this method is what finally made the Zettelkasten "click" — just as it was always promised.

With other approaches, problems start piling up once the number of notes exceeds a couple of hundred. VirtFolder's structure lets you organize a base of several thousand entries without losing a single one.

I'd love to hear your feedback and suggestions.