Blog Update 1

Update 2026-03-11: I noticed that I actually had way less go code in my current codebase than I originally thought since I overlooked that I included misc. tools that aren't required for the website to run. I fixed the counts.


Wow the very first blog update! :D

First let me dive into what has changed for you: the user.

Honestly...not that much.

  • The blog landing page and the post overview show posts now in a more compact form providing a better overview over posts.
  • Site loading should be even faster now. On my trusty old Thinkpad T480s with the site running on localhost I got the load times down to single digit miliseconds for all pages*. Realistically you would never notice this since network latency and browser rendering take longer than that :^)
  • The post list also got some neat filter options as a replacement for removing the tags and series page which should make for a better browsing experience since you're not jumping between pages now all the time.
  • The above point also compensates for the loss of full text search. I couldn't implement it in time. Sorry! You can use search engines' full text search instead. Just limit the site to this page by adding site:sebico.de to the search request :)

* I tested what would happen if I added caching just out of curiosity and turns out that site load times would go to 0.13 miliseconds and lower. I feel like theres no practical need for me to go that far but it was a fun experiment xD I have the code for you here in case you need a simple, crappy caching layer compatible with the go stdlib as a middleware of sorts.

I sadly did not get to implement another feature where I would show all pages available as a tree in a sidebar similar to file browsers in modern IDEs. Maybe I'll do that some day.

But mostly this change was to satisfy my need to make things simple and fast.

Stats #

Before I get to telling you how and what I did, I want to show you some stats:

$ fossil diff -v | diffstat
 blog/blog.go                               |  130 ++++----------------------------------
...
 web/web_test.go                            |   13 ---
 36 files changed, 393 insertions(+), 1574 deletions(-)

That's right! 1181 lines DELETED! Gone! Out of existence! Now the interesting part would probably also knowing how many lines of code this application has. After all, deleting 1k lines from a 300k loc project is not bad but not astounding either, right?

Let's count lines of code AFTER the change:

$ cloc --include-lang=go --exclude-dir=tools .
      51 text files.
      37 unique files.
      41 files ignored.

github.com/AlDanial/cloc v 2.06  T=0.02 s (1020.0 files/s, 67562.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                              17            180             59            887
-------------------------------------------------------------------------------
SUM:                            17            180             59            887
-------------------------------------------------------------------------------

And some lines for templates:

wc -l content/templates/*
     139 total

887 lines of pure go code AFTER the change (excluding tools not required for website functionality). So I basically deleted like more than half the codebase xD

What? Why? How? #

The short is 'simplify some pages' and 'remove sqlite'. I got rid of sqlite since I used it only for full text search and even though that is a neat feature it was really not worth having to handle all the stuff that comes with maintaining a database. If the need arises I'll add it back in the future, maybe not via a database but we'll see. I really like sqlite tho, don't get me wrong. I think it's an excellent database system that is really overlooked.

The other part was 'simplify some pages' and it consisted of replacing the standalone tags and series page for some filtes in the posts page. Basically instead of using primitive pages with links I leveraged query parameters to offer a similar experience. I once read a post that talked about URL parameters and how underrated they are. I absolutely agree but funnily enough I only remembered reading that post after already having made the decision to leverage URL params...oh well.

In total that meant:

  • removing the entire database code (-846 loc)
  • removing the handlers and templates for the tag and series pages (-261 loc)

So...a lot basically.

Cool things I learned #

You can call go templates like functions. I've added a template for creating html for a post list item that is used by both the blog overview and the post list:

{{ define "post-list-entry" }}
<div class="item">
  <b><a href="/blog/posts/{{.Slug}}">{{ .Title }}</a></b>
  <span class="details">, {{ .CreatedAt.Format "02. January 2006" }}
  {{ if not (eq .CreatedAt .UpdatedAt) }}
  (Update {{ .UpdatedAt.Format "02. January 2006" }})
  {{ end }}
  </span>
  <div>{{ .Description }}</div>
</div>
{{end}}

And I can call it like this:

{{ range .Posts }}
    {{template "post-list-entry" .}}
{{ end }}

Which is quite cool. I somehow didn't think you could do that but as it turns out :D

Also you can use $ in templates to refer to some special variable. In the select element in the tag filter I wanted the page to reflect the users choice. So I added an if statement in the for loop that checked this. But that meant that . now doesn't refer to the entity that was passed to the template but instead the current element of the for loop. But you could use $. to still access the struct passed to the template (see $.SelectedTag):

<select name="tag" optional>
  <option value="">Any</option>
  {{ range .Tags }}
  <option value="{{ . }}" {{if (eq . $.SelectedTag) }}selected{{end}}>{{.}}</option>
  {{ end }}
</select>

That's about it. If I remember something I might update this blog post.