Update for the week ending on Friday, Oct 30, 2026
mtlynch.io
- Improved the caption on the melty breadboard image
- Fixed it for the book and might as well copy it here
Refactoring English
Book
- Adjusted the layout so that paragraphs are half a line-width apart vertically, and all elements follow the inner < outer rule
- Tweaked the preface based on re-read
- Added a fast-preview build
- It renders just the cover and tutorials chapter so I can iterate quickly on style changes without rendering the whole book, which is slow
- Fixed a bad word break in a table
- Fixed more awkward page breaks
- Adjusted behavior so that examples never break mid-page by default unless explicitly marked as
breakable="true". - Improved the caption overlay on a photo
- Improved performance of PDF comparison script
- Refactored out redundant style rules from the PDF print theme
Feedback app
- Completed transition from Buttondown-based account IDs to custom Lockwood backend
- Deleted design doc from repo
- No need to keep it around, and it keeps distracting agents by updating a point-in-time document.
- Refactored code to avoid shadowing package names
- Added a go-critic linter check for it
- Added an AGENTS rule forbidding agents from editing
AGENTS.md- I used to think they could do it, but they’re just too aggressive at editing it, and they’re bad at extrapolating general rules from a specific conversation.
- Consolidated some unit tests
Website
- Made all the pages use consistent horizontal margins
- Added space below the navbar on every page
- Upgraded to surge 0.52.0
Lockwood Backend
- Ported improvements from go-app-starter
Go App Starter
- Ported repo to Codefloe
- Added convenience scripts to push and pull all child repositories from dev-scripts
- Backported improvements from child projects
- Bind SQLite values with named parameters
- Install development dependencies without prompting
- Keep production and development app builds in sync
- Build and cache every package through flake checks
- Run frontend tooling on Node.js 24.15.0
- Update flake-utils without changing supported systems
- Upgrade TypeScript lint tooling to 8.68.0
- Upgrade shared system bindings to x/sys 0.47.0
- Upgrade the SQLite driver to 0.35.3
- Added a rule to avoid mentioning private project details commit messages
- Added a rule to skip litestream updates in push-down-improvements
- Litestream updates to 0.5.x are more than just simple code changes.
Other tools
- Updated the invoice generator to support the paperback version
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).
- Ported improvements from go-app-starter
ScreenJournal
ScreenJournal is basically Goodreads, but for TV and movies. Or letterboxd, but focused on small communities.
- Ported improvements from go-app-starter
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.
- Fixed a crash in guest upload handler that could happen when the client disconnects unexpectedly
- Run frontend checks with Nix-provided interpreters
Grosiree
Grosiree is a shared grocery list web app I’m making with my wife to show her how vibecoding works.
- Ported improvements from go-app-starter
Weekly Snippets
- Updated the
new-weekscript to label open and closed PRs- These are the outliers that I have to treat specially.
- Also, sometimes I have multiple PRs with the same title, and several are abandoned attempts at the same thing.
ActivityWatch Frontend
- Moved repo to Codefloe and NixCI
- Added a a NixOS module
- Add hot config reloading when
config.yamlchanges - Adjusted the web view to support nesting subcategories
- Adjusted the web view to aggregate activities within each category
- Adjusted the matching rules to make more liberal assumptions about URL matching
- For example,
https://example.com/*should matchhttps://example.comtoo
- For example,
- Parsed activity URLs earlier
- Separated text and URL pattern matching from configuration
- Rewrote configuration tests to focus on rule integration
- Removed
BEHIND_PROXYandbehindProxysupport since I don’t need them for local running - Ported improvements from go-app-starter
NixOS config
- Bumped my sandbox VMs to 400 GiB storage and 64 GiB swap
- Merged my to-do list and inbox dashboards into a single dashboard
- Refactored AI sandbox implementation to cut down on LOC count
- Improved forgejo-pr tool to reject non-existent base branches
- Fix stderr output in sandbox
- Fixed a race condition in starting sandbox
- Made switches from different sandbox versions explicit
- Tweaked my commit message skipll
- Updated CUDA nix cache signing key
QNAP Switch Manager
Started working on a custom frontend to my QNAP managed switch, whose native UI is terrible and slow. My hope is to make a frontend that makes it easy/convenient to flip PoE switches on and off, as it would be fun to turn my Pi 4 nodes on from a browser.
- Created a vibecoded proof of concept
Maildir Viewer
- Ported improvements from go-app-starter
Misc
- Updated all my systems to 6.18.56 to mitigate CVE-2026-98432
- Rearranged my server rack
- I was hoping to put a rack shelf on the top rack, but it looks like I need to extend my rack a bit to fit it at its shortest length
- Tested self-hosted XMPP chat server
- I tried Snikket and ejabberd as the backend
- I wasn’t crazy about either of them, but I found Snikket a little easier to use
- I didn’t like Snikket’s client side, so I swapped it out for Prose
- I found Prose okay, but it’s very directly a copy of Slack, which is not my ideal chat UX
- I tried Snikket and ejabberd as the backend