Org-roam and anki

I see in the screenshot on that someone is creating their Anki flashcards in org-roam.

Any tips on what packages and workflow is being used to build the Anki deck from org-roam files?

That would be anki-editor:

1 Like

Nice, thanks for that! I’ve set it up and posted my notes here.

I’ve just started using this, but found it very useful.

One enhancement I made was to automatically add the file the card lives in to the back of the card. I made the file name a link, using a customer org-protocol handler, so that if I’m reviewing on my computer I can instantly go to the context of the card, which is very useful.

Here’s my code:

;; org-protocol support for opening a file - needed for ‘my-anki-editor-backlink’.
 '("org-open-file" :protocol "open-file" :function org-protocol-open-file))
(defun org-protocol-open-file (fname)
  "Process an org-protocol://open-file?url= style URL with FNAME.
Change a filename by mapping URLs to local filenames as set
in `org-protocol-project-alist'.
The location for a browser's bookmark should look like this:
  javascript:location.href = \\='org-protocol://open-source?url=\\=' + \\
  ;; As we enter this function for a match on our protocol, the return value
  ;; defaults to nil.
  (let ((f (org-protocol-sanitize-uri
            (plist-get (org-protocol-parse-parameters fname nil '(:file))
(defadvice! my-anki-editor-backlink (fn &rest r)
  "Add links from Anki cards back to the file that generated them."
  :around #'anki-editor--build-fields
  (require 'url-util)
  (let ((fields (apply fn r)))
        (((and fields))
         (note-type (org-entry-get nil anki-editor-prop-note-type))
          (when-let ((f (buffer-file-name)))
            (abbreviate-file-name f)))
           ((string= note-type "Basic") "Back")
           ((string= note-type "Basic (and reversed card)") "Note")
           ((string= note-type "Cloze") "Extra")
           ((string= note-type "Cloze with typed text") "Extra")
           (t nil)))
         (field (assoc field-name fields)))
      (setf (alist-get field-name fields nil nil #'equal)
            (concat (cdr field)
                    (format "<div><hr><p>Source: <a href=\"org-protocol://open-file?file=%s\">%s</p></div>"
                            (url-hexify-string current-file)
                            (org-html-encode-plain-text current-file)))))

That’s very cool. This code didn’t work me though, unfortunately.

Wouldn’t it be even easier to use the Note ID as a link between the two? I can get it from the Anki Browser and when I search my org-roam directory it brings me not only to the file, but directly to the note. Plus, it doesn’t add any boilerplate to my cards.

Is there a way of displaying Anki’s Note IDs on the cards, like it does with tags? Or even copy it to clipboard with a keybinding?

Once I have the ID, I can jump to it using a tiny function like this:

(defun qw/find-anki-note (x)
  (interactive "sNote ID: ")
  (consult-ripgrep "~/roam/" x))