Website... this website

You should start a website. It’s quite fun!


This article, titled “CSS is fun again”, put the OKLCH color space on my radar. It’s a color space, created in 2020, which covers capabilities of the most common, sRGB screens, but also the newer ones, like those using P3 or Rec. 2020 color spaces.

Oklab and OKLCH were created by Björn Ottosson, to fix issue in the CIE LAB and LCH color spaces. That matters if you’re curious why there’s so many abbreviations: CIE LAB (or Lab), Oklab, OKLCH. Let’s not even touch the topic of varying capitalization…

Oklab uses Cartesian coordinates to encode a point in its color space. OKLCH uses polar coordinates. That’s why an OKLCH encoded color, in CSS syntax, looks like so oklch(65.39% 0.3 10.2) - the first value being lightness (it’s polar coordinates, so imagine it’s moving on its vertical axis, often label Z), the second chroma (a bit of an arbitrary value that, for sRGB and P3, stays below 0.37 - that’s the radius from the cylinder’s center), the third hue (this maps to the angle, often labeled as the theta angle - this one can be between 0 and 360, which covers the entire cylinder).

If you’d like to know more about the math and history then you should check this article, by Evil Martians.

Let’s go back to the practical side of things. I’m using SASS for this website (well it’s SCSS to be more precise - there are two different syntaxes one can use). SASS extends CSS, through new functionality but it also adds a build step, where it translates it’s own syntax into the currently, widely supported CSS. It’s an additional dependency that, while useful, adds complexity. I’d like to drop SASS completely.

One of the features that SASS brought were variables. Those can be used like so:

$deep-red: #d30054;

.content {
  background: $deep-red;

CSS managed to catch up and nowadays it supports variables, albeit using a different syntax:

:root {
  --deep-red: #d30054;

.content {
  background: var(--deep-red);

Variables are just one feature. Another one was CSS selectors nesting. By now it’s also supported in the vanilla CSS. There’s way more to SASS, but I’m not the person to explain those features and their benefits - I just don’t use them.

I use a few color modification functions, like desature, darken, etc., that are still missing in plain CSS. SASS team can move quicker than W3C, the developer of the CSS technical specification, and the browsers’ teams. As soon as the CSS Color Module Level 5 gets finalized and gets implemented, in all major browsers, I will be able to fully drop SASS.

Here is an example of something you can do in SASS, right now:

$deep-red: oklch(55.39% 0.221 10.2)

$bright-red: scale-color($deep-red, $lightness: 20%);

Here is plain CSS, that does the same, which isn’t yet supported by Firefox:

:root {
  --deep-red: oklch(55.39% 0.221 10.2);
  --light-red: oklch(from var(--deep-red), calc(l + 20%) c h);

Here’s the link to check which browsers support the Relative Oklch colors.

I have moved my CSS file closer to plain CSS. One things that’s worth mentioning is that I might be excluding users with older versions of browsers installed. In order to address that I’d like to explore Lightning CSS. That might become my new dependency, but one that solves and issue I have ignored for quite a while now.


It’s been quite rewarding to improve this website here and there. My new, HTMX based comment system isn’t fully ready. The functionality is there but it’s lacking a good CSS. You might notice that the comments are visually very… basic.

Working on my comments system required some NGINX work. I had to prepare a config file which correctly redirects the traffic to my comments server. I have found bug in my configuration file for this website, which made not redirect to the That’s fixed now.

I have also experimented with HTML’s <picture> element. It allows you to implement a responsive images system - the browser chooses an appropriate image, from a provided list. The basic setup looks like this:

  <img src="small_img.webp"
       srcset="small_img.webp 400w, medium_img.webp 800w, big_img.webp 1200w"
       alt="this should be a responsive image"

The values 400w, 800w, 1200w are actually breakpoints for the browser of the viewport width. It’s not actually describing the image. For example, if the viewport size crosses 800px, load the big_img.webp. Between 800px and 400px it’ll use medium_img.webp and below 400px, the small_img.webp.

Before the changes I have recently implemented, the resolutions and proportions of the projects' thumbnails were all over the place. Now I used the small, medium and a big variant, for each project. All those variants share the same proportions and use predefined resolutions.

I don’t make three variants for each project thumbnail myself, but generate them. You can actually do that using Hugo’s image processing. I found that to be a bit too limited. I have decided to experiment with imagemagick. I’ll just share the most crucial part of my bash script, which generates the thumbnails.

gen_thumb() {
  local thumb=$1
  local prefix="sm_"
  local thumb_ext="webp"
  local output=$(dirname $thumb)/$prefix$(basename "${thumb%.*}").$thumb_ext
  local text_debug="SMALL, $thumb_ext"

  local width='400'
  convert_command+="convert $thumb -resize ${width}x -filter Lanczos"
  convert_command+=" -font Liberation-Mono-Bold"
  convert_command+=" -pointsize 32 -density 100 -gravity Center"
if [ $DEBUG = true ] ; then
  convert_command+=" -draw \"fill white text 0,0 '$text_debug'\""
  convert_command+=" -quality 98"
  convert_command+=" $output"

  eval $convert_command

This block repeats for medium and big thumbnail. I don’t store the thumbnail variants in the repository. I store a single image - the one I have used as a thumbnail before I have introduce the responsive images changes. I generate the small, medium and big variant when I build the website with Hugo.

When I was working on this it was very useful to put a clearly visible text, on the image, to easily identify which variant is the browser loading. That part of the convert command is behind a $DEBUG flag, since I don’t want that text to be present on the images I deploy to my web server.

If I run that bash function with a path of content/project/my_thumbnail.png, I’ll end with four files content/project/my_thumbnail.png (original, untouched), content/project/sm_my_thumbnail.webp, content/project/mid_my_thumbnail.webp and content/project/big_my_thumbnail.webp.

Since the thumbnails are generated, based on the original image’s name, that has to be taken into account by Hugo (I might actually simplify that because every project directory can have it’s own thumb.png file).

{{ $thumb_path := .Params.thumb }}
{{ $image := .Resources.GetMatch $thumb_path | default ( resources.Get "imgs/thumb.webp" ) }}
<!-- debug tool -->
<!-- {{ printf "%s" $image }} -->

{{ $smallPermalink := replace $image.Permalink (path.Base $image.Permalink) (printf "sm_%s%s" (path.BaseName $image.Permalink) ".webp") }}
{{ $mediumPermalink := replace $image.Permalink (path.Base $image.Permalink) (printf "mid_%s%s" (path.BaseName $image.Permalink) ".webp") }}
{{ $bigPermalink := replace $image.Permalink (path.Base $image.Permalink) (printf "big_%s%s" (path.BaseName $image.Permalink) ".webp") }}

<div class="project-card">
  <a href="{{ .Permalink }}">
    {{- with $image -}}
      <img src="{{ $smallPermalink }}"
           srcset="{{ $smallPermalink }} 400w, {{ $mediumPermalink }} 800w, {{ $bigPermalink }} 1200w"
    {{ end -}}
    <div class="projects-piece-banner">
          {{ .Title }}

This code grabs the thumbnail path, from the project’s file YAML header, and generates the small, medium and big paths, based on the naming convention of prefixing the original thumb’s name with sm_, mid_ and big_. This code actually fetches the original thumbnail as a resource via .Resources.GetMatch. That’s important if you want to process the image with Hugo’s image processing features, which I don’t do in this example. It’s also important because the resources that are not referenced in your code, won’t be transferred into the build directory. I don’t reference the sm_, mid_ and big_ variants as a resources, which means I have to generate those variants after running Hugo’s build command, in the build directory.

In the end the system works well. The width breakpoints might need some tuning. It definitely brings in some complexity but I also learned a lot, and that for me is the most important part. I want this website to be informational and technically optimized but in the end it has to be fun for me to develop and maintain. Maybe at some point this website will matter to an extent that someone will feel it necessary to tell me that my image responsive image system doesn’t work well.


I have turned off the Cactus comments system, on this website. I’ll soon be moving to my own comments system. For now the old comments should show up, without the ability to submit a comment.


Some time ago I’ve embedded a toot, from my main Mastodon account, at the top of the projects page. As you can see below, it wasn’t the best execution. It was embedded through the HTML’s iframe and it took all the space it could, mainly because of the link preview.


I have moved to a custom setup, where I pull my latest toot, into a JSON file, and embed it into website’s code, using Hugo.

import feedparser
import json
import sys

feed = feedparser.parse(MASTODON_LINK + '.rss')

# Just a way to look up what's in the entry.
# print(feed.entries[0])

toot_data = dict()
toot_data['summary'] = feed.entries[0].summary
toot_data['date'] = feed.entries[0].published
toot_data['base_url'] = feed.href
toot_data['mastodon'] = MASTODON_LINK

out_data = json.dumps(toot_data, indent=2)

It was trivial to pull the latest toot, thanks to the Mastodon’s RSS feed. I grab the latest toot, pick the relevant data and save it as a JSON string. I then output that string to a standard output, which I can easily pipe into a file.

python3 > data/toot.json

I have added a small piece of code in the theme/layouts/index.html which, if the data/toot.json exists, embeds that data into website’s code. The .Site.Data.toot searches for the toot file in the data directory. The actual toot contents are already HTML, so I embed it using Hugo’s safeHTML function.

{{ with .Site.Data.toot }}
<div class="toot-container">
  <p class="toot-header">
  <a href="{{- .mastodon -}}">{{- .mastodon -}}</a>
  <div class="toot-content">
    {{- safeHTML .summary -}}
{{ end }}

The result is way more subtle than the original.


There’s definitely space to improve it, but for now I’ll leave it at that.

I have also improved the CSS in quite a few places. I’m leveraging Hugo’s toCSS, to convert the SCSS stylesheet into CSS document. Previously I have used Python’s boussole to do that. It makes CI significantly slower to install boussole, since it has to compile the libSass. It also reloads the CSS whenever I modify the main.scss file. That wasn’t the case with the boussole setup.

One last thing I’d like to mention is that I have written my own comment system, using HTMX. I’d like to migrate to it soon. Since it’s extremely simple, it will be very easy to keep current comments - there aren’t many.


I’m not updating this project entry too often. Not surprisingly, working on my projects, content for this website and its form is not easy. In spite of that, it’s sometimes very calming to sit down and fight with the CSS a bit. Those last two days I managed to simplify the page’s layout - it’s less buggy and works better with mobile devices. I don’t feel like spending time on explaining those problems provides much value for anyone except for very unexperienced web developers. I’m sorry but this is not the place to learn advanced web development. If there is one thing that I might bestow upon you, after my latest work, it’d be to check the SASS’s ampersand operator.

I started using the ampersand operator and I quite like it:

a {
  color: $leftpane-bg;
  text-decoration: none;

  &:hover, &:focus {
    color: lighten(saturate($leftpane-bg, 20%), 10%);
    text-decoration: none;

One other things I have changed is styling for the comments section. Here is how it looked before.


Just several tweaks later it’s speaking the same design language as the rest of this website.


I’m using Cactus comments, which pulls its own CSS stylesheet. My own stylesheet then overrides classes’ parameters, thanks to CSS’s !important keyword.

Fixing comments’ elements took way too much time, but sometimes things just need to wait their turn. I have moments when maintaining a website frustrates me, but I try to remind myself that this is a learning experience. Nothing I make here gets to be perfect on the first try.

If you want a great final result, from the get go, spin up your website using one of the proven themes. Otherwise, be patient and let your space evolve with time.


This website has always been a project and currently it’s my longest running one (I’ve bought the domain on 25th of January, 2018). Feels only natural to create a project entry for it.

I’ve attempted to start a website/blog several times. It took a while to find a setup that I enjoy maintaining. After bouncing between Content Management Systems, I’ve found the static website generators. Currently I’m using Hugo - probably the most popular static website generator. It took a bit of time to learn it and I’m still learning anytime I come back to improve this website.

This is how the website looks on the 28th of November, 2021:

The red pane is quite distracting...
The red pane is quite distracting...

Consider this to be an archive for this website. This theme has been written by me but it’s soon time to move to something new. I always wanted to have a website which I designed and wrote. This is the space that I fully own and I want it to reflect my sensibilities. This look was inspired by terminal windows, which for me translated to monospaced fonts, limited color palette, text on a grid, minimalism etc. While I’m proud of it, I feel like it has run its course. I haven’t even started working on a new theme but redesigning this website has been in the back of my head for a long while now.

The contemporary web design doesn’t focus on something that I value - performance. This one is difficult for me because on one hand I really want this website to be lightweight and fast but on the other hand I’m a sucker for pretty things. I don’t want your browser to pull megabytes of data while navigating this website but having a 3D model of a PCB, embedded in an article, feels nice. Does it add proportional amount of value compared to the performance hit? Difficult to say. Do I like it there? Yes.

While this website is very minimalistic, I don’t want to be dogmatic about this. Some of the designs that I’d like to try in future might be less restrained but performance will always be on the top of my priorities list.

I won’t talk much about content here but one thing that those past few years of writing has taught me is the importance of clear writing and how difficult it is to achieve. English isn’t my first language and I have never been a great writer. I’m still not and I don’t think I’ll ever be, but I do see improvement. I notice that mostly when I go back to a piece I’ve written some time ago and I find it difficult to understand and follow. It doesn’t happen nearly as often as it should but I do rewrite content on this website. I’ve never thought I would learn to value writing skills as much as I do right now.