Update for the week ending on Friday, Jan 30, 2026
mtlynch.io
- Worked on my year 8 as a bootstrapped founder post
- Fixed my explanation of twisted pair vs. fiber in my rack server post
- Clarified compatibility of single mode and multimode fiber in my rack server post
- Adjusted my wordword CI job to print commands to stdout
- It was failing and I couldn’t figure out why without echoing the commands
Refactoring English
- Added notes on how I use AI tools
- Added an HTML version for excerpts I share with subscribers
- Added more CI checks for NixCI
- Added an undocumented HTTP header to bypass firewall on Buttondown API
Stream Preserve
Stream Preserve is a web app for recording video in a situation where your phone may be stolen or destroyed in the middle of a recording. It’s just an experiment so far.
- Got video recording to work on desktop and on Firefox Android
- Had to work around an odd bug in Firefox
- Added support for capturing video from partial uploads
- Added video thumbnails
- Made it so that videos auto-download to the client device after recording stops
- That way, you have a safe copy if something goes wrong with the server-side copy
Little Moments
Little Moments is an open-source web app I’m working on to replace the current family photo sharing app (TinyBeans) I used (which I strongly dislike).
- Continued working on design doc
- Added a D2 architecture diagram (which AI is decently good at making, though it took me about 90 mins)
python3_seed
- Switched to uv to manage Python dependencies
- Replaced isort with ruff
- Updated to coverage to 7.13.1
- Fixed my bash scripts shebangs to use a more portable version
resticpy
- Gave feedback on a third-party PR
- Linked to my commit messages guide for PR descriptions
- Linked to the Google Python Style Guide in CONTRIBUTING
- Tried switching from yapf to pyink
- YAPF seems no longer maintained, and pyink is a light fork of the more popular Black tool
- But it seems like pyink has a non-configurable line length of 88, which feels too disruptive
PicoShare
PicoShare is a minimalist web-based file sharing tool I’m working on. I’m often frustrated that I can’t just send someone a link directly to a file because every file-sharing service tries to re-encode images/video or wrap their own viewer around other files, so I’m making a simple self-hostable tool that lets you upload files and share them with other people.
- Set up performance tests to test different performance improvements
- I thought this was going to be easy for an AI agent but it turned out to be a huge pain
- My goal was to run PicoShare in constrained RAM scenarios and measure the impact of different performance improvements
- I wanted to use VMs to constrain RAM because I’ve tried using Docker in the past, and Docker seems to not be
- Added a note to flake.nix about nixhub
- This is mainly to help AI agents understand it
- Align mobile navbar items with Upload button text
- Consolidated .clinerules into AGENTS.md
- I’ve officially abandoned Cline for terminal-based agents
- Fixed path to playwright artifacts on CI
- Investigated whether I can replace the gorilla package with native Go muxer
- It seems more complicated than I expected
- Replaced modd with air
- air seems more actively maintained and easier to configure
- Updated CSS to use a consistent breakpoint
- Switched to crypt/rand instead of math/rand
- Added CSS nesting
- Refactored theme colors into CSS variables
go-app-starter
go-app-starter is my template project for Go web apps.
- I had a lot of improvements I’d discovered in other Go proejcts, so I backported them all to my template so I’d have a single canonical place to reference them, plus discovered a few more.
- Added a nix build target for the Docker build
- Added a note about nixhub to flake.nix
- Switched
generateRandomStringto use crypto/rand- I don’t know why it wasn’t using
crypto/randbefore - It probably doesn’t matter, but it’s one of those cases where there’s no reason not to, and I might as well just for the sake of not wondering if there’s an issue
- I don’t know why it wasn’t using
- Moved ESLint ignores to eslint.config.js
- Moved
Storeinterface tohandlerpackage- I was accidentally letting the implementation define the
interface
- I was accidentally letting the implementation define the
- Removed CircleCI config - Continuing to migrate most projects to NixCI
- Removed .env.dev from serve script
- It didn’t exist in the boilerplate project
- Replaced .clinerules with AGENTS.md
- Replaced Replace gorilla/mux with net/http mux
- Replaced modd with air
- Simplified Litestream install in Dockerfile
Grosiree
Grosiree is a shared grocery list web app I’m making with my wife to show her how vibecoding works.
- Added inputs for item, quantity, notes, and section
- Added auto-complete for inputs and sections
NixOS config
- Added a check for Lua syntax on commit
- It prevents me from applying an invalid Awesome WM config early
- Adjust SSH config so that I don’t offer all SSH identies to all hosts by default
LLM sandbox
- Adjusted the sandbox config so that it doesn’t share the
.venvdirectory with the sandbox container- I’m pretty sure this was messing up my .venv because I think the container points to a nix store that differs from the host, though I haven’t tested it rigorously.
- Wrote a custom opener for
- Fixed Firefox behavior in Awesome WM
- By default, when I open a URL from a non-browser, it opens in the last Firefox window I touched, which is often in a different desktop
- I vibecoded a custom URL handler that always opens in the current desktop
- Formatted everything with alejandra and enabled a pre-commit check for formatting
- Split up my
home.nixfile into a few separate files- My VS Code, SSH, and git settings had gotten large and unwieldy within the single file, so it’s easier to manage each in dedicated files
Misc
- Reported a security vulnerability to a utility provider
- Played around with fuzzing VLC
- Emailed an old coworker
- Checked out the new TinyPilot Voyager 3