Aggregations in Tiddlywiki (2021)


Author's note: The line of thinking in this post ultimately led me to develop Notedeck, so if you find this interesting, that might be something to check out!

I use Tiddlywiki for a lot of things, including notetaking, and often keeping logs on particular subjects. I have a daily worklog that is a holding area for any notes that don't go anywhere else, but I also have logs for my 1:1 meetings, and various other recurring "project" meetings so I can remember what was covered in prior meetings.

The obvious way to approach this is to have a note for each topic (worklog, 1:1 meeting, project, etc.) and then add a dated entry to each note. I tend to prefer short notes, though, so each is an small bundle of information that can be linked to from elsewhere. So the "one giant note" approach isn't that appealing. To improve my ability to skim over previous entries, I use aggregation notes to help. The notes use the $list widget to query for notes with a particular tag. For example, if I'm having a bunch of meetings with Fred, I'll have a note titled Fred, and then tag other notes with Fred, using titles like Fred/2021-08-21. Then, in the Fred note, I can type this monster:

<$list filter="[tag[Fred]!sort[title]limit[3]]">
    <h1><$view field="title"/></h1>
    <$transclude field="text" mode="block"/>

It may not be totally obvious, but this finds the three most recent notes tagged with Fred and creates a headline with the title for each, and then injects the body of the note below the title. In short, it aggregates the three most recent entries and displays them. Let's go piece-by-piece and see how this works.

The Filter

The $list widget returns a list of notes that pass the provided filter parameter. The filter is enclosed in brackets ([]), and has three elements:

  1. tag[Fred]: Selects all notes tagged with Fred.
  2. !sort[title]: Reverse sorts those notes by title. Because of how they are named (YYYY-MM-DD), a reverse sort provides a reverse chronological ordering.
  3. limit[3]: Returns only the first three notes.

The Template

$list is a widget that allows other widgets to be used inside it that reference each item it returns. It does this by setting the value of the current tiddler to the current item in the iteration. Within this iteration loop, the template above makes use of three widgets to render each item in the list: $link, $view, and $transclude.

$link simply renders a link to the tiddler (via its title field), and the contents of the $link tag determine how the link will appear. In the template above, the link should appear as an h1 heading displaying the title of the tiddler. The title of the tiddler is obtained by using the $view widget, which retrieves a specific field from the specified tiddler. By default, $view uses the value of currentTiddler, which is bound by the iteration loop. So this displays the title of the tiddler as a heading, and links it back to the source.

But I also want the actual *content* of the tiddler to be displayed as well. So the final piece of the template opens a span and uses the $transclude widget to inject the text field of currentTiddler into the span. mode=block is a very important option here, since that allows the text to be rendered as HTML rather than raw text, allowing for proper formatting, like paragraph breaks.

And that's it! This aggregation pattern is central to how I've taken notes for most of 2021 so far, and I plan to build more on top of it, like backlinks, and perhaps a UI to streamline things.