Starting a TIL

While thinking about moving Soloist Systems to a personal blog, I came back around to the idea of the digital garden, a personal online space, similar to a blog, but with a focus on the ongoing, iterative process of learning and knowledge building. I want to leverage the way I have been using LogSeq to save personal notes about technologies and philosophy in a way that I can share to benefit others.

This led me to the concept of a TIL (today I learned…), which serves as a bite-sized learn-in-public piece of information I can push daily in the form of Markdown. HUGO strikes me as a perfect technology to build this. I want to put focus on the minimal styling and fast page loading. I might leverage technologies I have previously worked with on LinuxCreative.com, such as the search plugin I vendored. Additionally, this LogSeq plugin looked interesting upon a quick web search of others with similar ideas.

Here are some goals I have for the project:

Some unanswered questions:

TIL Homepage Idea

  1. Render a nice looking tag cloud sorted by tag count by default. The hugo creator has implemented this, so this is a good place to start.
  2. Include more data in the DOM to sort by with JavaScript (dropdown) – namely, by last modified (Gemini generated):
1---
2title: My TIL Entry
3date: 2024-08-01
4lastmod: 2025-08-06 # Manually set or update this value
5tags: ["hugo", "javascript", "frontend"]
6---
1enableGitInfo: true
2
3# prioritize git commit date
4frontmatter:
5lastmod:
6    - lastmod
7    - :git
8    - date
9    - publishDate
 1<input type="search" id="tagSearch" placeholder="Search tags...">
 2
 3<select id="sortTags">
 4    <option value="count">Sort by Count</option>
 5    <option value="recent">Sort by Most Recent</option>
 6</select>
 7
 8<div id="tagCloud">
 9    {{ range $.Site.Taxonomies.tags.ByCount.Reverse }}  
10        {{ $name := .Name }}
11        {{ $lastmod := "" }}
12        {{ with $.Site.GetPage (printf "/%s/%s" "tags" $name) }} 
13            {{ $lastmod = .Lastmod.Format "2006-01-02T15:04:05Z" }} 
14        {{ end }}
15        <a href="/tags/{{ $name | urlize }}/" 
16            class="tag-item" 
17            data-term="{{ $name }}" 
18            data-count="{{ .Count }}" 
19            data-lastmod="{{ $lastmod }}">
20            {{ $name }} ({{ .Count }})
21        </a>
22    {{ end }}
23</div>
 1document.addEventListener('DOMContentLoaded', () => {
 2    const tagCloudContainer = document.getElementById('tagCloud');
 3    const sortDropdown = document.getElementById('sortTags');
 4    // Get the search input
 5    const tagSearchInput = document.getElementById('tagSearch');
 6
 7    function sortAndRenderTags(sortBy) {
 8        const tags = Array.from(tagCloudContainer.children); 
 9        let sortedTags = [...tags]; 
10
11        if (sortBy === 'count') {
12            sortedTags.sort((a, b) => 
13                parseInt(b.dataset.count) - parseInt(a.dataset.count)
14            );
15        } else if (sortBy === 'recent') {
16            sortedTags.sort((a, b) => 
17                new Date(b.dataset.lastmod) - new Date(a.dataset.lastmod)
18            );
19        }
20        
21        sortedTags.forEach(tag => tagCloudContainer.appendChild(tag));
22    }
23
24    function filterTags(searchTerm) {
25        const tags = Array.from(tagCloudContainer.children);
26        const lowerCaseSearchTerm = searchTerm.toLowerCase();
27
28        // consider using tag.hidden instead for performance reasons
29        tags.forEach(tag => {
30            const tagName = tag.dataset.term.toLowerCase();
31            if (tagName.includes(lowerCaseSearchTerm)) { 
32                tag.style.display = 'inline-block';
33                // tag.hidden = false; 
34            } else {
35                tag.style.display = 'none';
36                // tag.hidden = true;
37            }
38        });
39    }
40
41    sortDropdown.addEventListener('change', (event) => {
42        sortAndRenderTags(event.target.value);
43    });
44
45    tagSearchInput.addEventListener('input', (event) => {
46        filterTags(event.target.value);
47    });
48
49    // Add the keydown event listener for the Enter key
50    tagSearchInput.addEventListener('keydown', (event) => {
51        if (event.key === 'Enter') {
52            // Prevent potential form submission if within a form.
53            event.preventDefault();
54            // Remove focus from the input field. 
55            event.target.blur();
56        }
57    });
58});

tags: hugoblogtildigital gardenlogseqnotes