About This Website

This website is a log of my adventures in programming, computer science, and math.
This website is where I share what I’ve learned.
This website is where I express my aesthetic preferences in web design.

To contact me, email hello at kosalab.dev.


Colophon

Jotdown for parsing djot
Tree-sitter for syntax highlighting
MiniJinja for HTML templating
KaTeX for math typesetting
QuickJS to run KaTeX in-process

Fonts

Five different fonts are used on-and-off throughout the whole site.

Let me explain.

The body text uses the increasingly popular and ostensibly overused Inter. Specifically, I’m using version ≥4.0 of Inter, which not only provides a variable font but also ⭐ true italics ⭐. I love how clean it makes websites look, although I do have a few items on my wishlist (namely proper old style numerals and small caps support).

The vintage personality that Bricolage Grotesque brings to display text wonderfully contrasts the modern look and feel of Inter. Another free and open source font, it lacks true italics or other fancy OpenType features, but as a font for headings it is Good Enough™.

Iosevka is my preferred monospace font. Although I am blessed with n > 1 monitors today, I still greatly appreciate the 0.5em wide glyphs allowing me to fit more columns within the width of my terminal. I do not use nor like programming ligatures, so I have those turned off. To save on bandwidth, I chose not to use italics or obliques, and restrict font weight to the default 400.

The remaining two fonts are actually variants of the same font — Source Hans Sans. The variants are for Chinese and Japanese glyphs respectively, which are both used on the site. Due to Han Unification [1], I have to separately specify whether my bones are or , which is only mildly annoying in practice. I do subset font files to reduce bandwidth [2], but the extra HTTP requests are unavoidable.

  1. A good rundown of the problem can be found at Your Code Displays Japanese Wrong, which is how I first became aware of the problem.

  2. Uncompressed, each variant of Source Hans Sans in the woff2 format is ≈14MB in size. That’s way over my threshold for page weight, and what motivated me to really look into automatic font-subsetting for my site.

Semantic HTML

The HTML generated from the djot that I write should be as semantic as possible. For example, quotations are wrapped in <figure> elements the citation in a <figcaption>.

The reason that the rich were so rich, Vimes reasoned, was because they managed to spend less money. Take boots, for example.

A really good pair of leather boots cost fifty dollars. But an affordable pair of boots, which were sort of OK for a season or two and then leaked like hell when the cardboard gave out, cost about ten dollars.

But the thing was that good boots lasted for years and years. A man who could afford fifty dollars had a pair of boots that’d still be keeping his feet dry in ten years’ time, while a poor man who could only afford cheap boots would have spent a hundred dollars on boots in the same time and would still have wet feet.

Terry Pratchett, Men at Arms: The Play

Some posts make heavy use of LaTeX\LaTeX, which is rendered into HTML for aesthetics and MathML for accessibility. The rendering is done entirely at static site generation time [3]. This increases page size but avoids the need for client-side rendering, which is an acceptable tradeoff to me.

  1. I would like to not use any Javascript libraries, but AFAIK the only viable options for quality and accessibility today are MathJax and KaTeX. Thankfully, I can embed QuickJS into my site generator, then use it to run katex.min.js, passing any found math to renderToString.

The probability density function for a Gaussian distribution with mean μ\mu and variance σ2\sigma^2 is

n(x;μ,σ)=1σ2πe12σ2(xμ)2,{<x<<μ<σ>0 n(x; \mu, \sigma) = \frac{ 1 } { \sigma\sqrt{2\pi} } e^{-\dfrac{1}{2\sigma^2}(x - \mu)^2}, \begin{dcases} -\infty < x < \infty\\ -\infty < \mu < \infty\\ \sigma > 0 \end{dcases}

Similarly, code blocks are highlighted at “compile time” and converted into HTML:

    testing.py
"""
Deletes the final line in a file.
Modified from https://stackoverflow.com/a/10289740/11457597
"""
import os

with open("path/to/file", "rb+", encoding="UTF-8") as file:
    file.seek(0, os.SEEK_END)
    pos = file.tell() - 1
    # Search for newline from the end
    while pos > 0 and file.read(1) != "\n":
        pos -= 1
        file.seek(pos, os.SEEK_SET)
    if pos > 0:
        file.seek(pos, os.SEEK_SET)
        file.truncate()

For more information about code blocks on this site, please see Overengineered HTML Codeblocks.

Design

The design of this website should be cohesive to the best of my ability.

Regular links are colored blue and visited links are colored purple because you’ve read them and red plus blue makes purple. Links are underlined on hover. Special interactables are green on hover and all interactables show a red outline on keyboard focus.

Where applicable, highlighted text should have a  yellow to magenta gradient .

Color

Speaking of color, the website supports both a light and a dark theme. By default, the site will use a theme dependent on the browser/operating system preference. Here is the color palette used on the site:

  • gray
  • red
  • orange
  • yellow
  • green
  • cyan
  • blue
  • purple
  • magenta

Raw HTML

Regular HTML elements can be written in djot and embedded into the page. Congratulations for making it to the end of the page! Here’s a playable sliding puzzle as a reward:

  • Moves: 0
  • State: Idle
  • Grid size: