Org-Roam

An Emacs library that recreates Roam (software that implements a Zettelkasten-like system) using org-mode.

All notes are stored as individual files addressed by {timestamp}-{underscore_separated_title} and can be backlinked to create a graph of notes which can be generated using graphviz.

Read the docs

See also:

NOTE: Many things have changed about org-roam in v2. Code snippets and issues are likely out of date.

Problems with org-roam

  • Auto completion is finicky (case sensitive, not fuzzy matching)
  • Can’t search for content in the body of notes when adding backlinks
  • Synchronizing between mobile and desktop is difficult e.g. Beorg on iOS can’t support a template that doesn’t have a title (org-roam’s template just has a #+TITLE tag)
  • You can’t export to HTML in a built in way (looks like you need to use ox-hugo with a config header in each note which is ugly)
  • Buffers don’t wrap text by default
  • Distinguishes between backlinks and ‘cite backlinks’ which is confusing
  • Automatically changes the file name if you change the title (these should be decoupled if you plan to publish notes)

org-roam v2

V2 is less portable than v1 now that links use `org-id`.

DONE Integrating org-roam [8/8]

DONE Use helm-rg for fuzzy full text searching notes

Add a keymap entry for it when in org-roam

  • Add an action to insert a file link to the highlighted result Use helm-add-action-to-source to add the action. See github.
  • Add link anchor words into it (maybe from title?)
(use-package helm-rg
  :ensure t
  :config
  ;; Add actions for inserting org file link from selected match
  (defun insert-org-mode-link-from-helm-result (candidate)
    (interactive)
    (with-helm-current-buffer
      (insert (format "[[file:%s][%s]]"
                      (plist-get candidate :file)
                      ;; Extract the title from the file name
                      (subst-char-in-string
                       ?_ ?\s
                       (first
                        (split-string
                         (first
                          (last
                           (split-string (plist-get candidate :file) "\\-")))
                         "\\.")))))))

  (helm-add-action-to-source "Insert org-mode link"
                             'insert-org-mode-link-from-helm-result
                             helm-rg-process-source))

DONE Toggle truncate lines in org-roam buffers

Make org-mode always use wrapped lines (setq org-startup-truncated nil)

DONE Set up exporting to html

  • Use ox-hugo to export to md and generate html using hugo Add #+HUGO_BASE_DIR: ~/Projects/zettel and #+HUGO_SECTION: ./ to the front matter of each note
  • Update the capture template to include hugo tags
  • Write a fn to batch export org files from a directory (since each note is it’s own file)

https://github.com/alexkehayias/emacs.d/blob/master/init.el#L715

DONE Cloud backup

  • iCloud is nice since all my devices could use it without any additional software, but you can’t symlink directories so an app can’t use the same data directory as another. This makes it difficult to use multiple apps as an input source to zettel notes.
  • Dropbox does sketchy things to desktops and used to cause random CPU spikes that would eat through laptop battery life. Not sure how much that’s changed.
  • Github might work, but once the number of files increases that might become unwieldy.
  • Decided to use icloud for now for syncing a file between Beorg to be processed into notes. On desktop, will use github to backup the exported notes until I can figure out something better for the underlying org mode files.

DONE Ignore any notes from hugo export that are tagged as private

https://github.com/alexkehayias/emacs.d/blob/master/init.el#L715

https://github.com/alexkehayias/emacs.d/blob/master/init.el#L715

DONE Update org-roam journal template to include private

(setq org-roam-dailies-capture-templates
      (quote (("d" "Default" plain (function org-roam--capture-get-point)
               "%?"
               :file-name "%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--journal\" (current-time) t)"
               :head "#+HUGO_BASE_DIR: ~/Projects/zettel\n#+HUGO_SECTION: ./\n#+TITLE: %<%Y-%m-%d>\n#+ROAM_ALIAS:\n#+ROAM_TAGS: private\n"
               :unnarrowed t))))