Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Zetteldesk.el a Revision and Outlining tool built on top of Org-Roam

Table of Contents


Zetteldesk.el exposes a workflow where you select buffers and org-roam nodes from a completion menu and filter generic functions such as switch-to-buffer and org-roam-node-find to show only the things you selected. Then it allows you to insert their contents in a seperate buffer and make an outline of the topic in question. Quoting the one and only Sonke Ahrens, the “desktop” is an essential part of academic endeavours such as writing a paper (I would personally generalize this further as an essential part of any type of revision work).

After a while, you will have developed ideas far enough to decide on a topic to write about. Your topic is now based on what you have, not based on an unfounded idea about what the literature you are about to read might provide. Look through the connections and collect all the relevant notes on this topic (most of the relevant notes will already be in partial order), copy them onto your “desktop” and bring them in order. Look for what is missing and what is redundant. Don’t wait until you have everything together. Rather, try ideas out and give yourself enough time to go back to reading and note-taking to improve your ideas, arguments and their structure.

  • Sonke Ahrens. How to Take Smart Notes : One Simple Technique to Boost Writing, Learning and Thinking–for Students, Academics and Nonfiction Book Writers. Pg. 31

This package attempts to port this desktop concept to emacs and org-roam as it seemed very useful to me and I would say it’s at least a “good enough” implementation.

If this sounds interesting to you, a small tutorial of the package can be found here, detailed documentation of the package can be found in the Wiki and the most interesting part of the Wiki (at least in my opinion) is the description of my workflow with the package in the Sample Workflow section. Unfortunately, while this idea is mentioned in the book, it is never deeply discussed so I improvised a bit to make something I like, and I think you might find it helpful. Lastly, I want to mention that I recently gave a talk in EmacsConf 2022 which included a small demo of using zetteldesk.el for organizing literature notes for scientific writing which might be interesting to watch.


This package is on MELPA so just install it with M-x package-install. All its extensions are also finally on MELPA as well!

However, for other installation methods there is installing from source (for instructions on how to do that, refer to

Or installing the package using straight.el with the following snippet

(use-package zetteldesk
  :straight (zetteldesk
             :type git :host github
             :repo "Vidianos-Giannitsis/zetteldesk.el")

Using Doom Emacs

To install in a Doom configuration, you can also put the following declaration in your packages.el

;; ~/.doom.d/packages.el
(package! zetteldesk
  :recipe (:host github :repo "Vidianos-Giannitsis/zetteldesk.el"))

Do note that if you want to install any of the extensions, they are separate packages, so this recipe won’t install them. You need either separate package! calls or this snippet

(package! zetteldesk
  :recipe (:host github :repo "Vidianos-Giannitsis/zetteldesk.el" :files ("*.el")))

Sample Config

For those of you who are not so much the reading types and just want a working config, which you can explore later I will leave a config that sets everything up here. I have tried to make the keybinding hydra as self explanatory as possible, and if you check function docstrings you should be able to understand what this does, but for a better idea, you should (in my opinion) check Getting Started and the Wiki. But then again, I like reading docs, so if you don’t, you may not agree.

This assumes you have installed and setup org-roam (I would be surprised if you are checking this out without having setup org-roam though, this is mostly an org-roam extension with some other things on the side) and that you have installed Hydra and Pretty-Hydra, as the package’s default keybindings are made with a hydra using the pretty-hydra-define macro (which I find the most visually appealing way to write macros).

They are all on Melpa so you shouldn’t have trouble finding them.

Install zetteldesk and zetteldesk-kb from MELPA and then add this snippet.

(require 'zetteldesk)
(zetteldesk-mode 1)
(setq zetteldesk-kb-hydra-prefix (kbd "C-c z"))
(require 'zetteldesk-kb)

After setting these, just press C-c z (or any other keybinding you want if you change the value of zetteldesk-kb-hydra-prefix) and explore the hydra.

Doom Emacs Configuration

If you are having problems with Doom Emacs, feel free to check out this issue.

Sample full config

This package has a few extensions to it which enhance its features. These are by no means necessary and that’s why the above example doesn’t list them. This is the sample config that assumes you use all the add-ons. They are explained more in the next section of the config. This is the one I use personally.

(require 'zetteldesk)
(zetteldesk-mode 1)
(require 'zetteldesk-kb-complete)
(require 'zetteldesk-ref)
(require 'zetteldesk-info)
(require 'zetteldesk-remark)

Optional Extensions for zetteldesk.el

Zetteldesk.el has 4 optional extensions. They are seperate packages because most of them are outside the scope of the general package and introduce unnecessary dependencies.

zetteldesk-kb.el creates a hydra with which I created the default keybindings of the package. It has dependencies on hydra and pretty-hydra as I like the look of hydras generated with the pretty-hydra-define macro and decided to use them as the default of the package. You are free to not use them, but they are a helpful “starter” kit. There is also zetteldesk-kb-complete.el, which is an enhancement of this including keybindings for all the other extensions. I use all the extensions so its helpful to have a keybindings extension that includes all extensions. MELPA:

zetteldesk-info.el, originally part of zetteldesk.el is an extension to use the features of zetteldesk.el with the Info documentation viewer built-in to Emacs. Its in my opinion a very helpful extension and does not introduce any dependencies, but its a case where its features are really outside the scope of zetteldesk.el MELPA:

zetteldesk-ref.el is an extension for handling literature notes better. I make these with org-roam-bibtex and org-noter and it felt annoying to not have proper filtering and insertion functions (for what these mean, do read on). It relies on bibtex-completion, meaning either helm-bibtex or ivy-bibtex. If you manage your bibliography with Citar however, fear not, as the extension zetteldesk-ref-citar.el has been implemented for using this extension of zetteldesk with Citar as its backend. The Citar implementation is not yet on MELPA however. MELPA:

zetteldesk-remark is an extension for integration between zetteldesk.el and org-remark. Org-remark is a package for creating margin notes in your org documents. Due to limitations of both packages, I had to write some functions to smooth out the integration of the two. This extension includes those functions. MELPA:

These are documented in the wiki, so feel free to check them out with more detail.


Keybindings in Emacs are a long discussion. I firmly believe that emacs is a tool which you can mold to your liking, and the fact that you can completely change all its keybindings with ease to those you like is a big part of that. I personally prefer evil style keybindings with Space as the global leader key. Someone else might like defaults, be inspired by defaults but change them a bit, or any other random thing. However, it is true that default keybindings in packages significantly lower the entry point and help with learning the package easier.

For this reason, I have defined a set of hydras for the package’s defaults, in the extension zetteldesk-kb.el, but they must be installed separately. I like hydras for this kind of job as they allow large descriptions and are very convenient to use. They are defined with the pretty-hydra-define macro as I like how it looks. These keybindings are to an extent inspired by my personal keybindings, but due to their different nature (of trying to fit all of them in a single hydra) they are not identical. However I consider them very usable for the purposes of the package.

The main hydra that contains all the keybindings is zetteldesk-main-hydra, while I have defined 3 more supplementary hydras, zetteldesk-add-hydra, zetteldesk-remove-hydra and zetteldesk-insert-hydra which are called from the main hydra. The main hydra is called with “C-c .” by default. I dislike that keybinding personally, I recommend “C-c z”, but its against keybinding conventions to do that and Emacs says I should use C-c followed by a punctuation symbol. The above sample config did actually set it to “C-c z”. However, you are free to (and recommended to) customize the value of the variable zetteldesk-hydra-prefix to a proper keybinding expression (using kbd) to override that so that it follows the logic of the rest of your config. If you however use zetteldesk-kb-complete.el, the extension that has the keybindings for all the extensions (which I use personally), it does have “C-c z” as the default. That package is not planned to be released on MELPA and is for the convenience of myself and anyone else who might be interested in it, so it doesn’t really need to follow that convention. If you use it, you should be aware it does that.

Getting Started

First things first, once you have the package in your load-path, you need to require and activate the global minor-mode zetteldesk-mode. This mode does some background work to create a buffer named zetteldesk-scratch. This essentially acts as your desktop. This is where you put everything really.

So a sample config would be

(require 'zetteldesk)
(zetteldesk-mode 1)

Then, I have prepared a few demos of the main features of the package, for you to look at to get an idea. For more detailed documentation, check the Wiki of the package and the function docstrings. This is a short showcase of the main features.

But first, here is a list of the main features of the package as seen below, to get a top-level look at what the package provides:

  1. Add/Remove Buffers or Org-Roam Nodes from the zetteldesk with various conveniences besides simple selection, such as selecting all backlinks of an org-roam node
  2. Use the contents of the zetteldesk to view filtered versions of core functions such as org-roam-node-find, org-roam-node-insert and switch-to-buffer
  3. Insert the contents of an org-roam node in the zetteldesk-scratch buffer, leaving a link to the node in the current buffer. The selection is filtered to nodes in the zetteldesk
  4. Save specific parts of a manual inside the Info program to seamlessly jump between specific info nodes, even if unrelated. Furthermore, have the ability to insert the Info node to the zetteldesk-scratch.
  5. Insert the contents of an org-file to the zetteldesk-scratch as supplementary material to org-roam nodes. Again, the selection is filtered to org files (but not org-roam nodes) in the zetteldesk.
  6. Insert links to specific pages of a pdf, with a selection menu of only zetteldesk pdfs
  7. A special behaviour for inserting reference nodes (nodes which are associated with a bibtex entry) as they have very different formatting than your typical org-roam node.
  8. Integrating the zetteldesk-scratch buffer with org-remark so you can freely take margin notes from it albeit it not being associated with a buffer.
  9. Save the current state of your zetteldesk to a file and be able to restore it in future sessions
  10. Save the current zetteldesk-scratch buffer to a file and create a fresh one, inactivating it
  11. Restore inactive zetteldesk-scratch buffers from the current session

    Feature number 4, referring to info buffers is one of the first things I made as I found it to be an interesting challenge. However, later on I decided to split it up from the main file, into the zetteldesk-info.el file. Since this is not the main feature of the package and its code follows a different model from the rest it made sense to do so, although I highly recommend it personally.

    Features 7 and 8 come in optional packages contained in this repository. They are not primary features of the package and they were created at a later time, however, they were added here for reference and because I find them very useful personally. Since this is a Getting Started which I do not want to keep too long, these will be explained very briefly here. If you check the wiki, there will be ample info for these there.

    Features 9-11 were implemented for the main package but a while after the rest, due to a suggestion.

    Let’s look at them step-by-step

First, we can look at how you add or remove an org-roam node from the zetteldesk. This is shown in the gifs below

You typically start with zetteldesk-add-backlinks-to-desktop which is for bulk adding of nodes, adding a node and all its backlinks as its very helpful to add everything related to a subject and them some things that were missed can be added with zetteldesk-add-node-to-desktop or some things that in the end don’t belong there can be removed with zetteldesk-remove-node-from-desktop. For bulk removing zetteldesk-remove-backlinks-from-desktop is the main function you use. The other thing displayed here is the filtered version of org-roam-node-find, zetteldesk-node-find which filters to show only files in the zetteldesk.

With this, you can start working on your desktop. Unfortunately, I can’t show you any real examples I have, as all my lesson nodes are in Greek which is illegible for most. So for demonstration purposes I will show you the process of dropping a note in your desktop, namely the zetteldesk-scratch buffer.

The first function shown is zetteldesk-insert-node-contents-without-link, which prompts for a node and inserts its contents to the zetteldesk-scratch. It specifies its without a link, as the one I primarily use zetteldesk-insert-node-contents also inserts an ID link to that node in the scratch buffer. My typical workflow (described shortly here) includes me writing an outline of the subject, linking every subject I mention. These links are inserted with this function so their contents are added to the scratch. There is also zetteldesk-switch-to-scratch-buffer to open the scratch buffer in a split with the current buffer. The version that doesn’t insert a link zetteldesk-insert-node-contents-without-link (shown in the gif) does that by default, but the original zetteldesk-insert-node-contents doesn’t do that by default, so this function is generally useful.

If you are not done with everything you wanted to do, fear not, as you can save the state of your current zetteldesk-desktop and restore it in a future session. Saving a desktop can be done with the function zetteldesk-save-state and restoring it is with the function zetteldesk-restore-desktop. To be able to restore it between sessions, it needs to write to an elisp file on your load path (as to not tinker with your init.el). The location of that file is controlled by the variable zetteldesk-saved-state-file and is by default “~/.emacs.d/libs/zetteldesk-saves.el”. For this feature to work, that needs to be in your load path. Below are two demonstrative gifs on saving a zetteldesk-desktop and restoring it.

But the state of the zetteldesk-desktop variable is not the only one you may want to save state and restore later. The state of the zetteldesk-scratch buffer you tried so hard to organize is another thing you may want to save. There is write-file to store this, but in cases where you want to work with multiple desktops, its not a good idea to not have a buffer with the name *zetteldesk-desktop*. For this reason, when you want to store your work and create a new desktop as well, there is the wrapper function zetteldesk-create-new-scratch which runs these 2 things. Here is a gif demonstrating this.

As you can see, this also prompts you for a name to give to the scratch besides the file name. This is to allow for another feature of the package, which is the ability to have multiple scratches in one session. This was proposed to me at issue #11 and I do find it logical so I implemented it. This identifier is used in a similar function to restoring the zetteldesk-desktop to identify each scratch with a name, for a better view when prompting for which scratch to activate. Restoring an inactive desktop is as simple as calling a function. In the case that you have an empty scratch or you don’t want to save its contents, you should restore it with zetteldesk-delete-active-scratch-and-switch. If you want to both save the current and restore an active one, run zetteldesk-store-active-scratch-and-switch. It might help you understand if you see a gif of this behaviour.

Another thing I want to showcase is how this package interfaces with the Info program, the built-in documentation viewer of Emacs. Info buffers are unique in the way that there aren’t multiple. There is a single persistent buffer for Info. So besides the use of info buffers in the zetteldesk, for its own purposes, it needs to define a way to save the info buffers you want to be viewing. And also as this package defines a lot of filter functions, it needs a way to allow you to select a single info node and jump to it (which is done through a completing-read). This is in my opinion useful even on its own. Check the gif below for a demonstation of the feature.

The function that does the adding is zetteldesk-info-add-info-node-to-desktop (and of course there is an equivalent zetteldesk-info-remove-info-node-from-desktop), while the filter function is zetteldesk-info-goto-node. Furthermore, I wouldn’t consider this complete, if you couldn’t insert a node you want to the zetteldesk-scratch besides switching to it in the info buffer. This is also possible with zetteldesk-info-insert-contents, which is demonstrated here

Besides the contents, it also drops a link so you can read the node in its context (in the info buffer).

And of course, as I already had all the backbone, it was very easy to add similar functionalities expanding to all emacs buffers. The functions zetteldesk-add-to-desktop and zetteldesk-remove-from-desktop are what you expect them to be. Choose a buffer and add it to the zetteldesk. The filter function for these is zetteldesk-switch-to-buffer. Below is a demonstrative gif of how the filtered switch-to-buffer looks.

Last thing I consider super useful to showcase, is how the system handles references you want to insert to the zetteldesk besides the aforementioned org-roam files and info buffers.

Things I would consider perfectly reasonable ways to distribute information are org-mode files outside org-roam, pdf, rich text formats like MS Office and web pages. Actually, rich-text formats don’t interface well with emacs, so I recommend converting them to pdf, and I don’t have something for web pages as org-roam-protocol already does the work for me. It captures an org-roam file and I just add the org-roam file.

Through zetteldesk-insert-org-file-contents you can insert all your org mode files to the zetteldesk-scratch. It follows a similar logic to zetteldesk-insert-node-contents with a major difference that it can handle headings, as most org files use them (the org-roam one doesn’t as its more rare to see org-roam files with headings, as they are typically small files). For pdfs, you have the equivalent zetteldesk-insert-link-to-pdf. This doesn’t insert a pdf, as obviously that wouldn’t be practical, but a link to it. The cool thing is that the link can point to a specific page in the pdf. But that’s enough talking, I will let the gif do the rest

Note that the above functions filter to only show the appropriate files (org files that are not in org-roam or pdfs respectively) and that if they are in the zetteldesk.

Now, as promised, I will give you a very brief description of the optional extensions. Actually zetteldesk-info.el was already explained above (this is because it was originally part of the main package) and there is not much to say about zetteldesk-kb.el besides what was mentioned in Keybindings .

For zetteldesk-ref.el the most important functions I would say are zetteldesk-ref-find-ref-node, zetteldesk-ref-ivy-bibtex-with-notes (or zetteldesk-ref-helm-bibtex-with-notes) and zetteldesk-ref-insert-ref-node-contents. This extension follows the model of zetteldesk.el very closely. It defines some predicates, makes filters and defines a special insertion behaviour. You can think of the first 2 as combinations of filters between ivy-bibtex-with-notes and zetteldesk-node-find, implemented with the org-roam UI in zetteldesk-ref-find-ref-node and with the ivy-bibtex-with-notes one in zetteldesk-ref-ivy-bibtex-with-notes, while you can think of zetteldesk-insert-ref-node-contents as an inbetween of implementations between zetteldesk-insert-org-contents and zetteldesk-insert-node-contents.

If you prefer citar as your backend a lot of the functions have the same name, but are prefixed with zetteldesk-ref-citar instead of zetteldesk-ref. The only difference is the equivalent to zetteldesk-ref-ivy-bibtex-with-notes (using the bibliography manager’s UI for the selection) is named zetteldesk-ref-citar-open-notes following the naming of citar-open-notes on which it is based.

For zetteldesk-remark.el, go in *zetteldesk-scratch*, mark a section and run zetteldesk-remark-mark. There’s a lot of technical details behind this (which I explain in the wiki) but if you want to test it, zetteldesk-remark-mark essentially does all the magic.

For visual demonstrations of these, and many more details on them, check their wiki sections.

Background of the Package

So if you reached up to here, you are probably interested in this. So you can check out the background story of this package. This is how I concieved the package and everything leading up to the release. I find it interesting to read something like this as it gives a good description and use case for this, in an organic manner. Note that its rather lengthy and unfiltered though.

So, I was rereading the excellent book “How to Take Smart Notes” by Sonke Ahrens (around like 8-9 months after picking the workflow up) to have a more detailed look in some details I might have ignored starting out. And there was one useful thing I had missed. Specifically, this

After a while, you will have developed ideas far enough to decide on a topic to write about. Your topic is now based on what you have, not based on an unfounded idea about what the literature you are about to read might provide. Look through the connections and collect all the relevant notes on this topic (most of the relevant notes will already be in partial order), copy them onto your “desktop”[6] and bring them in order. Look for what is missing and what is redundant. Don’t wait until you have everything together. Rather, try ideas out and give yourself enough time to go back to reading and note-taking to improve your ideas, arguments and their structure.

[6] In the program Zettelkasten, the desktop is where you can bring notes into project-specific order. Each project should have its own desktop. If you use pen and paper, use your actual desktop.

So, its essentially a way to sort your thoughts on a subject in one place, trying to form a digital version of your actual desktop, where you can spread all your nodes on a subject. Now wouldn’t having this be handy. But there was no way I was going to not use emacs, even if it didn’t have this. A better solution would definitely be to write this in emacs. That is really the emacs mentality.

Thus begun my planning of all this. I was originally gonna call this zettelkasten-desktop.el, but that one was quite large, so I just shortened it to zetteldesk.el.

This started out really slowly with me thinking how I was gonna implement that idea and how it was all gonna pan out. I started with thinking of existing solutions for something similar. For example, I considered customising perspective.el to suit my needs as that had the ability of creating “perspectives” in which you can only view certain buffers. I quickly dropped that in favour of writing something from scratch. I felt that if I do it from scratch it would work out better as I would be more knowledgeable of what I am doing. Also, it was less work, because if I tried to customise a pre-existing package to suit my needs I would need to really go deep into learning what it does. I already had to do this for org-roam to write my addons to it, and as I am not a developer, have limited knowledge of elisp and also limited time to work on this, I thought it would be better if I wrote something from scratch using vanilla emacs and org-roam. Maybe I was wrong, but its fine, this has been working well so far for me.

First thing I looked at was what kind of predicate I was gonna define and with what criteria I was going to filter things. I tried to follow a rather simple idea to do this and not overcomplicate things. Essentially, I define a buffer-local variable and give it a default value. Then I define the predicate function that shows when a buffer is part of the zettelkasten desktop. A buffer will be part of the desktop only if the value of that variable in the buffer is not equal to the default. I started planning out things by filtering buffers like this, but as I was going to use this with org-roam nodes as well, and for viewing nodes you are doing them a misservice if you do not use the commands defined from org-roam for traversing the database, I ported everything over to work with nodes as well learning a lot about the insides of org-roam in the process. There are probably a million other ways to make a simple user-friendly predicate, but changing the value of a buffer local variable seemed fairly easy to me so I went for it.

When this was happening, I was in the second semester during which I took notes with org-roam and the zettelkasten method. I was proud to say that I had digitalised mostly everything I had notes for and had developed a good workflow for working with these notes (if anyone’s interested on the workflow, some parts of it are described over on the part of my literate emacs config concerning Org-roam which you can find here and I might mention some things to explain some design choices and some functions I have defined). But after some time, the exam period was starting. Having worked on some of my intial ideas for this during the christmas holidays, I was done with the basic filter functions for switch-to-buffer and org-roam-node-find filtered down to only show the buffers/nodes I selected. I was really happy with them, but I didn’t really know how to continue after that. Then, I realised two important things

  1. My zettelkasten, having grown a lot more since the only other exam period I had used it in, was a bit harder to navigate so that I could do my revision in it.
  2. The ideas I was considering with the zetteldesk, might be able to help with that.

    So I started thinking how I could combine these two. Having ran out of ideas for things to do, I thought trying to automate my revision process would be a fun puzzle. I had also not implemented the original idea, not having an idea of how I was gonna do it, but I said lets move on and I will think of something. I defined a new way of adding files to the zetteldesk besides a single buffer or a single node. That was to add a node and all its backlinks. As someone who works with big index files to sort their topics, this was very helpful, as I could add the majority of notes on a subject with a single command. Being able to have an org-roam-node-find function that shows only the nodes I am interested in, combined with org-roam UI, graphing that, was already a powerful tool. But there was basically no automation, nor had I achieved my original idea yet. All I had was a makeshift tool to filter my switch-to-buffer and org-roam-node-find to specific things. That was useful, but I wasn’t really satisfied, I had to keep going. While doing revision for the first lesson, I noted down everything I did in a seperate file and was then thinking how I could automate it.

    Slowly, things started coming together. I crafted a workflow which significantly eased revision for university and also managed to implement, at least as best I could, my original vision. Then I experimented a bit more. If this came out good, which it was looking to be so, I could use it for more general purpose studying. Therefore, I needed to handle org-files that were outside the org-roam directory, material handed in pdf form, web content and I even setup a way to handle Info buffers (as I read a lot of documentation through those and I figured it might be a good idea). I have used this for every exam of my current semester as of writing this (February 2022) and it has worked wonders to help me revise everything. Obviously, this is only good revision if the notes themselves are good, but having spent quite a bit of time during the semester trying to understand the topics and make good notes about them, I didn’t fear about that part. And the system’s automation works to help the process of reviewing only the notes I want in a lot of way.

    And as in the buffer that puts all of this together, I sort things with headings, I thought that maybe this could also be used as an outliner tool. I will look at how people do those and implement some stuff specifically for that, but for now, its not here. I think it might be usable for that purpose though anyways.

    This is where we currently are. Another big thing I want to do, is to play around a bit with org-remark. I believe that in such tool, the ability to highlight things and add margin notes to it might be really useful. In general I do not really use this right now, so it will take some time to do that, but I look forward to it. I also add small things to it in a rather regular basis, whenever I feel something is missing. The development of this, is very closely connected with my studying, so if I find something I can improve I will try to do so.

Related Work & Thank yous

In any kind of work you do, its a good practice to cite your sources of inspiration, and how your work differentiates itself from others. Furthermore, its also a good practice to say thanks to the people that helped, either directly or indirectly to make this what it is. So here’s mine

Of course this list couldn’t start with anything other than the exceptional book How to Take Smart Notes by Sonke Ahrens. This book is one of the best books I have read. It is an excellent introduction to the idea of the Zettelkasten and quotes from that book was what sparked the original thoughts. Its definitely my #1 source of inspiration. In that book, a slip-box program is recommended. Trusting the author, I decided to check it out, even though I was certain I was gonna use emacs for my zettelkasten. This program is honestly pretty decent and the idea of the desktop was borrowed from its implementation in that program, as it was mentioned in the book. Furthermore its Outliner is a pretty good looking thing. Another thing that gave me inspiration is the book How to Make a Complete Map of Every Thought you Think, which had some pivotal ideas for my workflow.

And this list wouldn’t be complete without a mention to the packages that all of this was built on. I honestly can’t thank jethro and every one else associated with org-roam enough for creating such an amazing product. Org-roam is in my opinion of the best packages out there for Emacs and I use it every day. That’s also why this package is built on top of it. I find it hard to imagine going back to not using this package. But besides org-roam, this package uses a lot of other Emacs packages to feel more complete. For example, as mentioned above, the keybindings are using the pretty-hydra package. I definitely own abo-abo a thanks for making hydra, one of (at least in my opinion) easiest to use and most convenient packages for managing your keybindings. Then the pretty-hydra macro is just a cherry on-top which makes hydras look even better.

Then for the other extensions of the package, they are all based on a seperate package and create better integration of it with zetteldesk.el. I absolutely love the Info program built-in to emacs for reading documentation and that’s why zetteldesk-info.el is a thing. Furthermore, due to my studies, its essential that I read scientific articles. Packages such as Ivy-Bibtex and Org-Roam-Bibtex make my life so much easier and a better integration of these and zetteldesk is what zetteldesk-ref.el is trying to achieve. Lastly, from the inception of this package, I was looking more into org-remark for integrating it with this package. I will be honest, I don’t use that package so often myself, but its definitely great and I think the creation of zetteldesk-remark.el which integrates it with the zetteldesk will make me use it a lot more.

With that long list of indirect thank yous, we can move to people who have helped me. This was originally no one, because I made this myself on my free time. But due to the magic of open source community projects, I now have more friends (yayyy). @jlcolbert on github, has helped me with adding doom emacs related sections, small fixes and in general has been very helpful to me. @jdoggz helped me fix the graininess that the demonstrative gifs had in the beginning. The gifs were too large, but also grainy when viewed on firefox. He helped me get better quality gifs so its easier for everyone to follow. To be honest, if you used a chromium browser it wasn’t even that bad, but holy was it a problem on firefox. So I am definitely grateful for him doing some of the research on the subject for me.

Furthermore I wouldn’t be able to get the knowledge to get here without a few people. The two main thank yous I would have to give are David Wilson from System Crafters on Youtube and the FSF for publishing the excellent book “An Introduction to Emacs Lisp” which helped me learn the language. Lastly, I would also like to thank r/emacs on reddit. Reddit is infamous for not having a very good community. A lot of people disregard it as a rather bad social media with little use. But r/emacs, is truly a great community. Whenever I can’t find an answer to a problem myself, I am certain that if I go to r/emacs and ask, someone will be able to help me, as people have in the past. Not to mention that I have gotten a lot of suggestions for this package from r/emacs, and to an extent its community helped me make this into what it is. So to everyone there, thanks for making this community what it is, its great!

Finally, for some similar projects and how this one differentiates itself. This is definitely a non-exhaustive list as I don’t know much of emacs. But for what I know, here is some similar work.

  • zk is a zettelkasten implementation for emacs that relies on a lot of low-level functions for its functionality. It has a feature called zk-desktop which is conceptually rather similar to what I have done. However, this is a solution of its own, completely independent of org-roam, while I wanted a solution to handle my org-roam repository
  • Delve is conceptually a rather similar package to this. Its built on top of org-roam and its got the idea of gathering nodes in a seperate buffer where you can play around with each seperately, a concept rather similar to that of zetteldesk. The main difference between the two is how their system is implemented. Zetteldesk is a package made in mind with filter functions to view only parts of your zettelkasten, but view them with the same UI Org-Roam uses, while Delve seems to have its own way of doing things, with not so many similarities to the UIs Org-Roam exposes. Both have their advantages and disadvantages, so use whichever one you like. The only other major difference I could notice is that zetteldesk has behaviours for handling supplementary materials such as pdfs and info nodes, while Delve seems to handle only nodes.
  • Bufler is a package made for playing around more with your buffers more. Zetteldesk also has similar functionality, but its not its core focus, so obviously I would consider it inferior in this regard. I just added the buffer stuff as it made sense conceptually to me to do more than org-roam nodes.


Zetteldesk.el is an emacs library built on top of org-roam with the purpose of easier revision on various subjects and a better outliner tool for emacs







No packages published