May 30, 2026

Recording 4K60 on Linux is now easy (my first kernel patch)

Recording 4K60 on Linux used to be a mess. As of Linux 6.19 you plug in an Elgato 4K X, open OBS, and get clean 4K60 with the in-kernel driver and no extra software. What fixed it is a small USB quirk i got into the kernel.

i needed this for my daughter Karolina’s YouTube channel, Karo’s Gaming World, which records clean 4K60 Nintendo gameplay. Shameless plug: if you like that kind of thing, leave her a sub. :) Read more

May 9, 2026

Frontend builds in Bazel with Vite and rules_js

i build my frontends as SPAs with Vite inside a Bazel workspace alongside Go backends. bazel build //... builds everything. The output is one JS bundle, one CSS file, and an index.html. The Go server serves it as static files, with index.html returned for any path that doesn’t match a file on disk (so client-side routing works on refresh).

i don’t use Next.js or any SSR framework.

Why Vite, not Next.js

The frontend runs in the browser. The browser runs JavaScript. So you write JavaScript for the browser and ship it as static files. The backend is Go, serving APIs over ConnectRPC or plain HTTP. Clean separation. The Go server serves the SPA as static files. Done. Read more

March 11, 2026

Go linting with nogo in Bazel

i use nogo instead of golangci-lint for Go linting in Bazel. nogo is a rules_go feature that compiles Go analyzers into the build. Lint errors become build errors. Bazel caches results per package, so incremental builds only re-lint what changed. golangci-lint has its own cache, but it doesn’t share between CI and local, so you duplicate work.

Setup

You enable nogo in MODULE.bazel by pointing go_sdk.nogo at a nogo() target:

1go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
2go_sdk.from_file(go_mod = "//:go.mod")
3go_sdk.nogo(nogo = "//:nogo")

go_sdk.from_file reads the Go version from your go.mod, so you don’t duplicate it. You can also use go_sdk.download(version = "1.24.5") if you want to pin it explicitly. Read more

September 6, 2025

The Linux setup | Part 1 - An Investment for Life

I’ve been a Linux user for about 15 years, and I owe a lot of that journey to my first job at Capgemini Deutschland GmbH. It was a classic corporate setup-developers used Windows, but all the servers ran on Linux. That’s where I finally got to learn the essentials: Bash scripting, maintaining on-premise servers for testing environments, and all that fun in-house stuff.

I was working there part-time while studying computer science, so it wasn’t long before I started using Linux for personal projects, too. I kept my gaming PC on Windows, though, because back in 2012, gaming on Linux was basically impossible. Read more

December 8, 2024

Replace Buf Remote Plugins with local vendored plugins

Buf is the best tool to manage protobufs. One of the biggest pain points of protobuf is the management of protoc plugins. You need to manage them, and make them available to other engineers working on the same repository/project. Versions need to be centrally managed, code generation must produce the same result, no matter if it happens on an engineer A or B’s machine, or in CI.

This becomes even more challenging, as protoc plugins are written in different programming languages. Go protoc plugins are written in Go, and are therefore compiling to a single binary without dependencies. Easy. However, other plugins are more difficult to manage. Typescript plugins like protoc-gen-es are written in Typescript, and therefore do not compile to a single binary. Read more