Use SB to implement Zettelkasten

Hello community,
I would like to share my usage of SB as a Zettelkasten. To whomever doesn't know, Zettelkasten (or slipbox notes) is a system of atomic note with rich links.

Overview

During the day, I could capture some thoughts using quick notes (labeled as memo).

When I sit down with the Zettelkasten, I go to the central page, where I can see a list of my quick notes. I decide if I want to transform them into a new Zettel. If so, I can go over the list of all zettels in the same page to find a existing note that feels most connected to the thought.

If I could find one, I go to the selected Zettel. If not, I will find a index page whose topic is closest to this note. If I still couldn't find one, I add a new index page.

Now, with an entry point fixed, I create a new Zettel using template. The Zettel template would record the nid of the parent Zettel or index, I need only to add a new letter/number to give my new Zettel a unique nid. I also give my Zettel a readable title.

After I write down my new Zettel, I use silver-search to search for keywords and see if I could add any links. I could also go back to the central page to view the list of all Zettels to find connection.

When I read a Zettel, I could:

  • Navigate to its parent or children, using the query in the bottom.
  • Navigate to any link I added manually
  • Navigate to any mention, using the Linked Mentions

Details

I have two kinds of notes in my Zettelkasten, zettel and zettel-index. The first one is an atomic note, and the second one serves as an entry point. I have a central page linked to all Zettel-index's.

The hub

This one has a query for all zettel-index, a query for all zettel, a query for random three memo (my version of quick notes) so I can process them whenever I have time.

Anatomy of Zettel

Zettel/a summurization

I use nid to order the notes, so I can use title freely. I put all of them under a folder.

Frontmatter

Each Zettel is tagged with zettel and has a unique nid in the frontmatter.

tags: zettel other-tags
nid: c1.2d4a1

Body

Whatever I write.

Breadcrumb

The alphanumeric nid allows me to query the parent and children of a note. In this example, the parent is c1.2d4a, and the children could be c1.2d4a1c. I have the following script in the bottom of each Zettel. They are inserted using a page template, so I can modify them manually if necessary.

${template.each(query[[
  from  p = index.tag('zettel')
  where p.nid == string.sub(editor.getCurrentPageMeta().nid,1,-2)
]], template.new [==[ **Prev** ${nid} [[${ref}]]]==])
}
${"**Next**: \n" .. (some(template.each(query[[
  from  p = index.tag('zettel')
  where p.nid:startsWith(editor.getCurrentPageMeta().nid)
    and p.ref != editor.getCurrentPageMeta().ref
  order by p.nid asc
]], template.new [==[ - ${nid} [[${ref}]]
]==]))  or  "_No Follow Up Yet_")
}

The template

With a template for the templates it's fairly easy to write this:

---
tags: "meta/template/page"
## Uncomment any of the single-commented lines to set options
#############################################################
## Offer a suggested name when triggered
suggestedName: "Zettel/${editor.getSelection().text}"
## Whether or not to confirm the suggestedName or go there directly
confirmName: true
## To open a page if it already exists rather than create it fresh
openIfExists: true
## To trigger the page template with a custom command
command: Create Zettel
## To trigger the page template with a custom key
key: "Ctrl-q z"
#mac: "Cmd-Alt-q"
## To prefill frontmatter
frontmatter: |
  tags: zettel 
  nid: ${editor.getCurrentPageMeta().nid} 
## To manage the order in which the page templates appear
#priority: 10
---
|^|

---
${"$"}{some(template.each(query[[
  from  p = index.tag('zettel')
  where p.nid == string.sub(editor.getCurrentPageMeta().nid,1,-2)
]], template.new [==[ **Prev** ${"$"}{nid} [[${"$"}{ref}]]]==]))  or   "**Category**:\n" ..
template.each(query[[
  from  p = index.tag('zettel-index')
  where p.nid
  and not table.includes(p.itags, "top-cat")
  and editor.getCurrentPageMeta().nid:startsWith(p.nid) 
]], templates.pageItem)
}
${"$"}{"**Next**: \n" .. (some(template.each(query[[
  from  p = index.tag('zettel')
  where p.nid:startsWith(editor.getCurrentPageMeta().nid)
    and p.ref != editor.getCurrentPageMeta().ref
  order by p.nid asc
]], template.new [==[ - ${"$"}{nid} [[${"$"}{ref}]]
]==]))  or  "_No Follow Up Yet_")
}

I want to point to the code

suggestedName: "Zettel/${editor.getSelection().text}"

This allows me to write a long note first, then add [[]] to ideas that I think need a new Zettel, then select the text to pass it to the title of the new Zettel. I plan to tinker this a little more to make the process more smooth.

Anatomy of Zettel-index

Frontmatter

tags: zettel-index, other-tags
nid: c1

Body

I put "starting point of a train of thoughts" here. I do this manually.

Bottom

In the nid of a zettel, the code before dot is its category. So for example, c1 is the nid of, say, Computer Science -> Algorithm Philosophy. This allows me to query all notes under the same category. I do this with the following function (modified from this post).


templates.fullPageZettel = template.new[=[- **[[${ref}|${nid}]]** ${string.sub(ref,8,-1)}
]=]

templates.fullPageZettelSnippet = template.new[=[- **[[${ref}|${nid}]]** **${string.sub(ref,8,-1)}**
   - ${markdown.extractSnippet(space.readPage(ref))}
]=]

function widgets.linkedZettel(nid)
  local notes = query[[
    from p = index.tag "zettel" 
    where p.tag == "page"   
      and p.nid:startsWith(nid)
    order by p.nid asc
  ]]
  if some(notes) then
    return widget.markdownBlock("# Notes in this category \n" .. template.each(notes, templates.fullPageZettel))
  end
end

event.listen {
  name = "hooks:renderBottomWidgets",
  run = function(e)
    local page = editor.getCurrentPage()
    local meta = editor.getCurrentPageMeta()
    if not page or not meta then
      return
    end
    if table.includes(meta.tags, "zettel-index") and meta.nid then
      return widgets.linkedZettel(meta.nid)
    end
  end
}

I started with the snippet templaete but soon learned that the preview took too much place. So I setteled with only nid and title.

Conclusion

I really think SB is a greate note-taking tool with its powerful query function and space-lua.

4 Likes