Back to the talks Previous by track: rde Emacs introduction Next by track: justl: Driving recipes within Emacs Track: General

Linking headings (poor-man's Zettelkasten) and defining advanced task dependencies

Karl Voit (he/him, IRC: publicvoit,

In this talk, Karl Voit shares how he uses org-edna and org-super-links to manage dependencies and links betweentasks in Org Mode. Afterwards, he will handle questions over BigBlueButton.

The following image shows where the talk is in the schedule for Sun 2022-12-04. Solid lines show talks with Q&A via BigBlueButton. Dashed lines show talks with Q&A via IRC or Etherpad.

Format: 9-min talk followed by live Q&A (done)
Discuss on IRC: #emacsconf-gen

Times in different timezones:
Sunday, Dec 4 2022, ~10:40 AM - 10:50 AM EST (US/Eastern)
which is the same as:
Sunday, Dec 4 2022, ~9:40 AM - 9:50 AM CST (US/Central)
Sunday, Dec 4 2022, ~8:40 AM - 8:50 AM MST (US/Mountain)
Sunday, Dec 4 2022, ~7:40 AM - 7:50 AM PST (US/Pacific)
Sunday, Dec 4 2022, ~3:40 PM - 3:50 PM UTC
Sunday, Dec 4 2022, ~4:40 PM - 4:50 PM CET (Europe/Paris)
Sunday, Dec 4 2022, ~5:40 PM - 5:50 PM EET (Europe/Athens)
Sunday, Dec 4 2022, ~9:10 PM - 9:20 PM IST (Asia/Kolkata)
Sunday, Dec 4 2022, ~11:40 PM - 11:50 PM +08 (Asia/Singapore)
Monday, Dec 5 2022, ~12:40 AM - 12:50 AM JST (Asia/Tokyo)
Find out how to watch and participate


00:00.000 Introduction 00:18.680 Setting up the demo 01:42.680 Linking between headings 03:03.920 Link drawers 03:51.640 Bi-directional links 04:09.960 Projects 05:07.680 Dependencies 05:51.600 Jumping between dependencies 06:39.320 Closing the project 07:49.120 Task dependencies between files 08:15.640 Conclusion


02:04.360 Can you filter out blocked tasks? 03:07.720 Do you ever have any issues having so much meta-level information? 05:01.160 Bidirectional links 10:22.491 Does this change how you use TODO keywords NEXT, TODO, BLOCKED? 11:14.300 Is your PhD published? 12:32.466 Org Brain 13:38.841 Do you find that the links are fragile, hard to maintain? 14:19.383 Would it be of interest to make auto descriptions for links in Org? 15:24.960 Why not Org UUIDs for IDs? 16:19.360 Do you use anything for "What links here to this heading?"

Listen to just the audio:


As written in this blog article, Karl thinks that a full-blown Zettelkasten workflow is not always a perfect match for a given set of requirements.

To him, the most important aspect of the Zettelkasten method are the bi-directional links between arbitrary headings. If you want to use such links without the additional burden and benefit of a Zettelkasten implementation, you might want to learn how bi-directional links are able to help you here.

In this talk, you will see a demo how links are used in the author's setup for linking headings and defining advanced dependencies between todo headings.

You can find the self-contained demo file on It consists of various packages and some Elisp glue to create these methods:

  • Bi-directional links between headings:

    • org-super-links with org-super-links-org-ql and org-super-links-org-rifle
      • org-super-links-quick-insert-inline-link
      • org-super-links-quick-insert-drawer-link
    • org-linker
  • Advanced dependencies:

  • Search, completion and narrowing:

  • Adding CREATED properties for new headings: org-expiry (not necessary for any demo functionality)

More on bi-directional links and Karl's Org mode projects:

More Emacs-related articles by Karl



Questions and answers

  • Q: so the LINKS drawers holds so-called "backlinks"?
    • A: yes. You can customize the drawer name.
  • Q: does this configuration you use need packages outside elpa?
  • Q:Can you filter out blocked taskes on stuff like your agenda or a specific agenda view, When you want to know what you can do next?
    • A: Blocked tasks are never shown on the agenda by default. Whenever there is no scheduled timestamp attached to a heading, it's not visible on my agenda. If you use the dependencies as described in the demo, the timestamp is only marked if the previous one is canceled. So blocked tasks are not shown in this setup.
  • Q:The functionality seems quite nice but the markup seems pretty heavy in the property drawers.  Do you ever have any issues having so much meta-level information in the file?
    • A: As long as it doesn't need to be typed manually there's no real issue. The orgmode files tend to be large. I haven't felt it's bloated.
  • Q:Does this change how you use todo keywords "next, todo, blocked?", avoiding some or starting to use others
    • A: No. My keywords are NEXT, STARTED, WAITING, DONE, CANCELLED
  • Q:Org Brain has stuff like parent links and directional links, sibling links. If org roam else has nothing else intersting what about like the previous stuff?
    • A: My links are not "directed" most of the time. So I don't have the requirment for specific link types or directions. In short: I don't need semantic links so far. Following the KISS principle. I get the information from the context of the link.
  • Q: DO you find that the links are fragile, hard to maintain?
    • A: not really. sometimes I rename links and the link name is not updated, that require some fixes by hand
  • Q: PhD Thesis link
  • Q: why not org-id's UUIDs for IDs, and the preference for human-readable ones (and not just use CUSTOM_ID for those)?
    • Karl: I hate UUID because they're opaque, so I removed them.
      • I don't understand. There is a part for human to read description: [[UUID][A human readable description]]
      • Karl: this would not add any benefit from my personal point of view as longs as the human-readable ID is unique. So why not get rid of the UUID and use the humand readable link text?
        • A human readble link is fragile, e.g. space, non acsii characters. When unexpected things happen, it is hard to detect the change. Using human-readable link text release the stress, so the user could focus on the content. 
        • Karl: You should take a look at my Elisp function that generates the ID strings. No problem so far.
          • I found you write a blog about it: . I will read about it.
            • I found (defun my-generate-sanitized-alnum-dash-string(str) in the
            • way to generate your ID requires replace non-ASCII characters: ;;
            • Replace German Umlauts with 7-bit ASCII.
            • ;; Replace German Umlauts with 7-bit ASCII.
            • (str (replace-regexp-in-string "[Ä]" "Ae" str t))
            • (str (replace-regexp-in-string "[Ü]" "Ue" str t))
            • This is a very tedious work to do. I don't know if users come from
            • other non-ASCII characters would have to write their own replacement
            • regular expression.
  • Q. do you have/use anything for "what links here / to this heading", in a more occur/grep-style buffer and auto.?
    • A: not yet, I use org-occur in the buffer and get the result
  • Q: (totally tangential):  Do you navigate your files with the arrow keys or with C-{pnbf}?  I saw arrows on your key-cast.
  • Q: link to thesis please
  • Q: any way to do links by heading hierarchy?
  • Q: so the LINKS drawers holds so-called "backlinks"?
    • A: yes. You can customize the drawer name.
  • does this configuration you use need packages outside elpa?

Other discussions from IRC

  • Wow, this looks super organized
  • i have to admire embedding that much info into tasks (ie: blocked, next, etc), i never get that far. my headings are much more lightweight, i'd likely use a plain list if i could fold over the text below
  • Is there a specialized package for showing backlinks (org-mode) in a buffer, say based on IDs, in a normal occur buffer or even a grep/rg style thing?
  • i really like that both publicvoit's org-superlinks and hyperbole are both elisp and inside emacs, where org-roam is a hodgepodge of external tools (my impression)
    • isn't sqlite the only external dependency for org-roam though?
  • Speaker: Actually, to create the demo fully self-contained was most of the effort with this demo. By far.
  • Fashion:
    • that is a dapper looking fellow!
    • Really loved the ending publicvoit
    • haha the goodbye was epic
    • I am way underdressed for this conference it appears
    • oh! I backed up and see the shorts that publicvoit was wearing!
    • A fashion leder if you will
    • I was here for the fashion. Not dissapointed.


[00:00:00.000] Hello, my name is Karl Voit and I'm going to show you a little demo on how I'm working with links between arbitrary headings and how I define dependencies between tasks when I'm working with projects and so forth.

[00:00:18.680] For that purpose, I've created a repository that contains the files we are going to work with, with the overall setup and so forth. So you just have to download this repository and you're able to replay everything which you are going to see here. If you've downloaded the configuration of the demo, you see those files, and you start the Emacs with an empty configuration and link demo file, like that. So let me just briefly increase the font size. Setting up the demo is easy. I've done the key visualization, the webcam part, and I've started the Emacs and increased the font size. And the last thing and the most important thing you need to do here is executing the babel block, which consists of more or less dirty Elisp code that installs the necessary packages, functions, and bindings required in this demo. You need to acknowledge the execution with yes and return, and after a couple of seconds, everything is downloaded and set up nicely for your demo.

[00:01:42.680] The first demo is the demo where I'm going to show you how I'm working with links between arbitrary headings. It consists of two commands, org-super-links-quick-insert-inline-link, and the second one is org-super-links-quick-insert-drawer-link. So the difference is, the first one is an inline link, and the second one only depends on the drawers of the headings. So let's show you what I mean. If I'm inserting here the inline link to the second one, which I have to choose from the result set here, you see that there is this second heading link included here in the first heading. Let's open up the first and second heading. You see that I can jump this link to the second heading. The first heading as well as the second heading get human readable IDs, which I personally prefer. The second one gets a backheading in a link drawer, which was created automatically. So this is a method where I link arbitrary headings, and that's the main reason why I personally don't need any Zettelkasten-based method like Org Roam.

[00:03:03.920] The next command which I want to show you is the link between those drawers. So in order to link the third to the fourth, I need to look for the fourth. In this case, you do not see any inline link like here above, but you see the :PROPERTIES: drawers and the :LINKS: drawers in both headings. So there is a forward- and a back-link between those two headings, and if you see a links drawer you know that there are linked headings you can follow. I do find this method very very handy.

[00:03:51.640] Of course, this doesn't only work within one single Org mode file. It works between arbitrary Org mode files as long as they are part of your Org Mode agenda list. So that was the first heading with the bi-directional links.

[00:04:09.960] The second one is a little bit more complicated than that because I show you how I'm working with projects. Usually, I start the project by adding a "Why?" statement so that I remember why this project needs to be done in the first place. I do a brainstorming on the tasks that need to be done in the project as a simple list. With this handy command (C-c *), I'm converting it to a list of Org mode headings. Now let's add the NEXT keyword, which is my default to-do keyword, to the first heading. You notice that there is a CREATED property which is not relevant to the demo itself, but it's part of my setup. I really like those created headings because when I add arbitrary headings, this CREATED property is added automatically.

[00:05:07.680] So now I want to define a dependency between "Empty garage" and "Paint walls and floor." I do that by invoking my command here, and look for the "Paint walls" heading. In this dialogue, you may add a scheduled date and/or a deadline date and/or a to-do statement. For this demo I only choose the to-do keyword. You notice that there is this TRIGGER property added. That's default behavior of org-edna which is managing the dependencies, in my case. In the other one, there is this BLOCKER property.

[00:05:51.600] It's very handy to know that those IDs might be used for jumping between those dependencies again. Those two headings don't have to be necessarily in the very same Org Mode file. They may be scattered around your Org Mode agenda files all over the place. So continuing this definition of dependency between the second and the third one... I'm using the search "Bring back stuff"... the search functionality... I choose the NEXT keyword here, its dependency. The same holds true for the last two. "Is painted", for example. I'm going to use the NEXT keyword again.

[00:06:39.320] I tend to use the last task of any project to close the overall project. So if I show you this one, I'm using the dependency to "Garage" project, and this time I'm using the DONE keyword. Of course, the properties look like that all the time, so there is a trigger from the first task to the second one, and there is a blocker from the second one back to the first one, and when I'm actually doing the project, I may now mark the first task as DONE, and you notice that the second one automatically gets a next keyword. This happened, of course, for all those tasks. The neat thing is when I close the last one, the overall project gets its DONE keyword as well. So this is how I'm working with projects and dependencies.

[00:07:49.120] Most of the time, task dependencies are not even within the same Org Mode subheading, let's say. Also, I'm using dependencies between different Org Mode files. This is a very, very cool way of defining what to do next in a project, without looking for tasks that can't be done at that stage.

[00:08:15.640] You can have a look at the details of the demo by checking out the files in the repository. That's it for the demo, and therefore I thank you for your patience. I wish you good luck, and I hope that I could show you one or two tricks that you can add to your Org Mode setup in order to help you with your daily work. So bye from me, till next time.

Captioner: sachac

Questions or comments? Please e-mail

Back to the talks Previous by track: rde Emacs introduction Next by track: justl: Driving recipes within Emacs Track: General

CategoryOrgMode CategoryZettelkasten