Posts in Ui (20 found)
ava's blog Yesterday

playing the mass effect board game

As a Mass Effect fan, and I am very grateful that my wife gifted me the ( relatively new) board game Mass Effect: Priority Hagalaz :) I am completely smitten with it! You can tell so much thought and love went into it by a huge fan who knows their stuff. The gameplay was translated so well to this format, and the characters and their abilities stay very true to the games. Nothing feels weirdly renamed, missing, or wrong, or too vague. Nothing feels like they had to compromise. All materials are beautifully printed on thick, glossy paper with amazing artwork, consisting of three spiral bound booklets and separate character and scenario sheets to track stuff on. The dice feel great, the tokens are sturdy, you have six character minifigs that are nice, two card stacks that look and feel high quality, and you get a little sack with the Alliance symbol on it and a marker pen with the Mass Effect label on it. Just feels like they went the extra mile with some little details they knew fans would love :) The concept is less a static boardgame, but a whole campaign you can play through with different paths, missions and outcomes. Instead of having to build a map via different physical parts or a map you unfold in each scenario, you open the specific map page in one of the spiral bound books and play on that. Less mess, cooler maps! You use the included colorful stones and marker to track skill progress, XP and unlocked abilities on the character sheets, as well as the tracker for each scenario for what you did or didn't do, and the tracker for the whole campaign. Thanks to the glossy/laminated finish, you can just remove the markings on any material so you can easily play again. There are different starting missions, character loyalty missions, and depending on your choices (what missions to do, who is loyal, how many War Points you get, if you play the scenario as more Paragon or Renegade, etc.) you get different sections in the Story Book, so it's a little like a "Make Your Own Adventure" book where it says " If you did this, continue reading at xyz, if you did the other, read abc ". This is so amazing for replayability! Gameplay-wise, it is easy to get into, but hard to succeed initially. It takes you a bit to get to know how the game expects you to behave and what you should focus on, and it can be difficult. If you do not focus on taking out at least 1-2 enemies each turn of a character (or at least weakening them), you will quickly be completely overrun as new enemies spawn frequently and existing ones get activated after each character turn. While shields recover, health only recovers with medigels you may find in the scenario. Just like the real game, characters love to go down and have to be revived (lol). If Shepard goes down, the scenario fails. As it was our first run through one of the possible routes of the campaign, we gave each other a bit of grace. There were a few moments where we realized we had played wrong (discovering a new rule or that we had applied it wrong, like for example, realizing later that you cannot split movements on the same die), and then either decided to do it right from that moment on, or create a map state as close as possible to how it would have been if we had been playing right. In the Loyalty Mission for Garrus, there's the option to actually monumentally fuck up Shepard's position in a way that completely traps them and makes moving away without dying impossible based on how the map is structured in that spot and due to a specific boss spawning. We agreed that if we had known this trap could occur when the enemy spawns, we would not have positioned Shepard this way or made her run away immediately. As we didn't wanna start over because of this incredibly niche problem/beginner mistake, we agreed to reset to an earlier boardstate as best as possible where Shepard wasn't standing in that horrible spot. I know it's technically cheating, but we really wanna focus on getting to know the game and progressing forward in the story as best as we can while learning :p I'm not sure a non-Mass Effect fan would like it as much; maybe the gameplay isn't convincing enough to stand on its own without the game relation. But for me, it's so fun to get back into a world with these characters again. I love it, and there are expansions announced for it, too! I hope they aren't cancelled, would love to have and play them. Published 08 Aug, 2026

0 views
Kev Quirk 4 days ago

New Pets, Sick Pets, and Hemorrhaging Money

Wooh! The last few weeks have been absolutely mental here in Casa del Quirk. Around 2 months ago we started renovating the stables to make things better for the goats and chickens. We've had an extraction system put in so fresh air is always circulating, as chickens are very dusty and goats don't like it too hot and stuffy. While we were at it, we also had some new fencing and gates put in, as well as better hard standing around the stables. Finally we had the old, rotten windows and doors replaced with lovely new ones that have shutters so we can control the air flow depending on the weather. Our stables with the new windows and doors As you can imagine, this has been a significant expense, but we planned for it. So it's all good, but then... Around a month ago we noticed that our older (and favourite) dog, Tia, had rather smelly breath and her mouth was bleeding when she was playing with her ball. We figured it's just old age and bad teeth, so we took her to the vet to have her mouth checked and properly cleaned. Unfortunately it was bad news. Tia has a benign but aggressive tumour growing in her gum. Apparently they're relatively common in older dogs (she's nearly 14) but if left untreated it would get very painful and we ultimately end up having to have her euthanised as it would significantly effect her quality of life. So we paid the unexpected £1,000 (~$1,350) bill to have the initial tumour removed, her teeth cleaned, and a biopsy. In the meantime we were also referred to a specialist to hopefully get the issue sorted properly. Last week Tia went to the specialist to have a full body CT scan. This would give them more info about the tumour in her mouth and what our options are, but also (because she's so old) let us know if there's anything more malicious going on in her body. We have to be pragmatic about this - the treatment was going to be expensive, and we had to make a call on whether we wanted it doing if they found something like cancer lingering somewhere in her body. Luckily for us the old girl came back with a clean bill of health and the tumour was treatable. That was another £1,500 (~$2,020) down the drain, but well spent. The procedure to treat the tumour involved taking around 40mm (~1.5") of her lower jaw away. It's a significant operation and the recovery, especially for an older dog, will be difficult. On Monday she had the procedure, it went really well, and yesterday she came home a day earlier than we expected. She's a tough old girl. She's much better today, but still struggling as she's been through a lot. Having a pet that's in pain is the worst - you can't really reassure them like you can a human, so you find yourself hopelessly watching them suffer. It's heartbreaking, but it's for the best. We're still to get the bill for this procedure, but the vet has estimated an eye-watering £4,400 (~$6,000). If anyone is playing along, that's £6,900 (~$9,200) in unexpected vet bills over the last few weeks. She also isn't insured as it's prohibitively expensive for a dog of her age. So we need to foot the entire bill. Anyway, on to more positive news... Last Saturday we welcomed the newest addition to our family, Nelly the 8 week old Labrador/cocker spaniel cross. The breed is known as a Cockador apparently - very unfortunate name if you ask me. Nelly on her first visit to the vet, being very good. Like any puppy, Nelly is a lot of work. Especially if you add into the mix a very sick dog, and the kids being off school for the summer holidays. I've also been working long hours recently, so my poor wife has been juggling most of this on her own. She's at her whits end. Nelly, Tia, and our other dog Sidney are all getting on well though. Nelly is even helping distract Tia from the pain she's in. It's fair to say that all our savings are gone, and the last of Tia's treatment will need to be thrown on a credit card so we can pay it off over the next few months. Things are extremely busy and stressful at the moment. But hopefully we will have Tia for a couple more years so her, Nelly, and Sid will become a proper little pack that gives us lots of lovely memories. Pets are a gift and we wouldn't have it any other way. I just wish vets bills were a little cheaper! Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
alikhil 1 weeks ago

How to control RGB on RAM sticks, motherboards, coolers, graphics cards programmatically with OpenRGB.

When I was building my gaming PC a few years ago, I bought a second-hand pair of RAM sticks with RGB lights. It was entertaining to see them glowing and changing colors. I did not bother myself to control them. Some time later, I got sick of gaming and made a decision to rebuild it into a self-hosting server. The PC moved from my table to an under-TV shelf in the living room. And here, glowing lights became distracting during watching TV or when we have guests sleeping in the living room. Therefore, I started searching for ways to control/disable RGB lights. After some search, I encountered OpenRGB . It’s open-source RGB control software that is independent from manufacturer software. It supports color syncing across several devices and has a community-managed effects library . It has a long list of more than 2,500 supported devices and, hopefully for me, my Corsair Vengeance was there! What a great piece of software, right? It’s a shame that I needed this software only to disable RGB . OpenRGB runs on Linux, macOS, and Windows. You can download the package for your operating system from the releases page . On my Debian-based server, I downloaded the package and installed it with: The package includes the required udev rules. If you use an AppImage, Flatpak, or a build from source, install the udev rules too. Without them, OpenRGB may not be able to access the RGB hardware without running as root. Before creating the service, check that OpenRGB can detect your devices: Make a note of the device numbers you want to control. Mine were and . I needed the RGB to turn off every time the system starts. So I ended up with the following systemd service. First, test the command manually. is black, which turns the LEDs off. The mode is supported by my devices; use the output of to check which modes yours support. When that worked, I created the service below. Now the RAM lights turn off automatically on every boot. No proprietary RGB application, no running desktop session, and no bright lights in the living room. If you have devices with RGB lights, check whether they are supported by OpenRGB . You might find a more creative use for it than I did and build some nice RGB animations.

0 views
Unsung 1 weeks ago

You only get one chance to make a zeroth impression

Contra the previous post , just spotted this “Same settings, new look!” callout in Firefox, on a page I have never visited before, talking about a feature I have never used: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/you-only-get-one-chance-to-make-a-zeroth-impression/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/you-only-get-one-chance-to-make-a-zeroth-impression/1.1600w.avif" type="image/avif"> I mentioned this once – when you get someplace new, everything is new. This redesign announcement’s conditions were engineered poorly, because they didn’t even consider people who didn’t use the feature before the redesign. I keep thinking of the very old computers from the 1940s, 1950s, and even 1960s, where the challenge wasn’t what to do with the computer, but with keeping the computer running. There was a machine called JOHNNIAC which gained a nickname “pneumoniac” because it refused to work on a warm day. On many other computers, there was a daily ritual of finding which of the vacuum tubes blew up and had to be replaced. Some teams had a literal downtime tax; they knew and communicated in advance that 40% of the days the machine would not be up to the task, consumed by tweaks and repairs to bring it just to the state of being ready to do work . When I look at those kinds of pop-ups and callouts, I think how we’re unwillingly recreating the very same conditions. I deeply believe people are exhausted not just by changes in software , but also constant questions, pop-ups, unnecessary notifications, “STOP 2 END,” emails to unsubscribe from, unsubscribes that don’t work the first time, and so on. Software should not require the user to occasionally click on buttons just to keep it running. #attention #onboarding

0 views
Unsung 1 weeks ago

In between the lines

Over the years, I acquired this weird collection of almost-invisible, but important signifiers of when I know a product really focuses on craft and thinks about its users. I thought about one recently. Here’s what happens when you try to copy a long block of text from YouTube’s (otherwise very useful) text transcript pane: And here’s an analogous example from GitHub: GitHub’s arrives ready to go. YouTube’s throws in a lot of messy things in between the lines. Why does it matter? Because these both feel like places you’ll be copying a lot from, and dealing with a messy paste can feel so, so unpleasant. You have probably seen this chart before, from xkcd : = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/in-between-the-lines/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/in-between-the-lines/3.1600w.avif" type="image/avif"> This is the fabled automation trade-off, or the high fixed cost vs. low variable cost dilemma. Yeah, if you’re doing a lot of copy/​paste, you might invest in creating some sort of a clean-up step, or even going through a programming text editor which has multiple cursors or other casual automation . But what if you don’t do that often, or if you don’t even know how much time it’d take you to automate it? Then the investment seems scary or insurmountable, and you’re stuck doing something like this, time and again: And it’s really nice to encounter a place like GitHub, where the team was thoughtful enough to save you all this trouble. There is also an asymmetry that’s worth pointing out. I believe making this good doesn’t have to be a lot of work for people putting these surfaces together. Here’s me fixing the YouTube situation with two simple lines of CSS with : I don’t know if it’d be as easy for all big text block situations, but I think it’s good practice to look around a bit and think about what are tiny things that you can do on your side that will save your users minutes or hours of tedium (see also: recents and paste and even more recents ). #copy paste #selection #text editing

0 views
@hannahilea 2 weeks ago

Birduino: A card-triggered audio player for [learning] the birds

Tap a bird card to the NFC reader to hear one of its calls, identify birds from their vocalizations, and up your bird game!

0 views
Unsung 2 weeks ago

Five moments in snapping history

Bear (a notetaking tool) has simple image resizing, with one extra nicety – if your images are near each other, resizing one will snap to the width of the other: In the Finder, columns snap to the width necessary to keep all the names untruncated – and not one pixel more: (Sidebar: This is also the only place I’m mentioning today that nicely uses the trackpad’s haptic feedback at the snap moment. I tried to indicate it in the video; this is not the final visual treatment I’m thinking of, but let me know if this kind of visualization of haptics feels useful to you!) macOS does something really interesting when you get its windows close to each other. Instead of typical snapping – pulling the thing you hold toward the other item like a magnet – it instead prevents you from going further for a while, in either direction. Perhaps the right analog here would be glue : If initially feels a bit funny, but I think I like it. It’s less aggressive and avoids needing some sort of cancellation (an option or a modifier key) if you don’t want it, because it never feels in a way. It also works for matching heights, like in Bear: In Figma, building atop regular snapping, we introduced something I awkwardly called “self-snapping”: if your objects are inside a container, the container will snap its padding to whatever it sees on the other side, without any explicit auto layout/​flexbox: I am sharing these five examples (and one from before ) because I think they exemplify a nice thing: precision without bureaucracy. In each case you could imagine an explicit heavy option somewhere in the menu… …that would feel slow and cumbersome. Instead, these take the freedom of direct manipulation and sprinkle just enough almost-invisible structure in a moment where that structure is undeniably useful. (Of course, you still might want explicit options somewhere in the menu or your command palette, if only for accessibility reasons.) I like that these quiet features have your back and make you look good, and that their creators understand that something almost aligned can feel worse than something completely misaligned. #bear #complexity #direct manipulation #interface design #mouse Bear: Set Image Width… macOS: Match Window Heights Finder: Restore Column Width Figma: Unify Padding

0 views
Kev Quirk 1 months ago

📝 2026-07-07 18:43: Guinea fowl keets are doing great too. All 5 are loving life with their foster...

Guinea fowl keets are doing great too. All 5 are loving life with their foster mums. Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
Unsung 1 months ago

A simple notification preview in Retro

A nice and I think effective notification preview in Retro , with a verbatim sample text of a notification right below its name: Not only you can see exactly what you’re going to get and make a much better-informed decision, but the app even uses actual names of your in-app contacts, so you can relate to the notifications more. #attention #preview

0 views
Unsung 1 months ago

“That knowledge slides away.”

In response to my recent interactive essay about interactions , Waider on Mastodon posted a great crystallization of a common problem: There is nothing quite so frustrating as a persistent user interface papercut. You know it’s there, but you keep running into it because the moment you start thinking about what you’re doing instead of how you’re doing it , that knowledge slides away until BAM you run into it again . I think this is really nicely put and highlights about why it’s very important to care about this kind of stuff. If you forgo a standard interaction out of carelessness, a bug, bad systems thinking, or for other reasons, you’re not just making your users frustrated by something not working. You’re also at risk of making them frustrated at themselves , assuming they can change what their fingers do easily, not fully knowing that a) this is motor memory, not just regular conscious actions (and any memory is hard to “update” intentionally), and b) motor memory is separated from regular, declarative memory, and not possible to reason with using the same techniques. (As an example, it’s very hard when keyboard shortcuts or mouse gestures disagree between apps, because while you consciously might know which app you’re in, that’s not necessarily true of your fingers.) Waider continues with an example: The canonical example of this, for me, is Microsoft apps on macOS: even now, decades after Microsoft started producing macOS versions of their apps, they insist on largely disregarding the native UI idioms in favour of their own. Current pet hate is that if I’m commenting on a document, the Ctrl-A/Ctrl-E actions do not work, and boy howdy do I use those constantly. My recent example is that even though I wrote about Safari overriding the natural “scroll to top/bottom” tap gesture on their tabs – so I am aware of it in my declarative memory, I know Safari designers messed it up, and I know exactly what to do and not do – my fingers still occasionally tap to scroll in Safari anyway. #details #flow #interface design

0 views
マリウス 1 months ago

Minimal yet Productive Travel Desk Setup

Being able to travel while being productive sounds romantic until you’ve spent hours hunching over your laptop on a hotel nightstand, untangling cables, hunting for outlets, and trying to focus in a space that clearly wasn’t designed for it. Over time, I have realized that productivity on the road has less to do with where you are and more to do with how intentionally you pick your equipment and set up your workspace. A good travel desk setup isn’t about recreating your home office, but rather about stripping things down to the essentials that actually help you think, create, and execute, no matter where you are. Although the term minimalism has gained a bad reputation over the past years due to its overuse by influencers , the actual philosophy behind it still remains valid and plays a huge role here, just not in the aesthetic-only sense that you might have been told about by “social” media . My personal setup is minimal because every item earns its place in it. When you’re living out of a bag for months at a time, friction becomes obvious very quickly and extra weight, redundant items, or tools that look nice but don’t meaningfully improve your workflow or comfort are the exact opposite of what this minimalism is about. The goal isn’t to carry less just for the sake of it, but it is to carry with purpose, depending on the circumstances. The point of a minimal travel setup is to have a reliable configuration that works wherever I am, whether that’s at an airport lounge, a café, an Airbnb , or a hotel “desk” , and to be able to open my bag and effortlessly set up everything needed in that situation. It’s basically a familiar, well-considered arrangement of tools that support what I do and, more importantly, that are modular , like little LEGO pieces, to offer a varying degree of completeness and availability, depending on the environment I’m in. Before getting into the actual hardware, it is worth being explicit about the rules I use to decide what does and what does not end up in my bag. Over the years, four principles have emerged that I now apply to every item, regardless of how cool , useful, or objectively good it might be in isolation. They are the reason the same bag works for a one-night business trip, or a month-long stay, without ever feeling like a bad compromise in any direction. These principles are also why I tend to ignore influencer packing lists when refining my own setup. They typically focus on what to pack, while the more durable question is why to pack one thing instead of another. Hardware comes and goes, gets discontinued, gets replaced, but the criteria for choosing the next iteration stay the same. The four principles below are the ones I keep returning to, in roughly the order in which I apply them. The first criteria behind my travel setup is modularity . Not in the physical sense (i.e. not in the way LEGO bricks click together), but in the sense that every component is useful on its own and becomes more useful when combined with others. Nothing in my bag depends on another item being present, yet whenever two or more components are around, they recognize each other and start cooperating without me having to touch a single knob or configuration. Let me get ahead of myself for a second to give you a short example. When I’m working out of a café, I usually have my laptop (plus my keyboard Sonshi-style ) that connects to my LTE router , either over WiFi or over Ethernet. Most of the time that’s the entire setup. However, the moment I’m in a hotel for a few days, I add my WiFi router to the mix, to have a LAN that I have full control over, that provides me with a VPN to circumvent geo-restrictions on all of my devices, and that is able to easily interconnect more items further down the road. Plugging the LTE router into the WiFi router automatically disables the LTE router’s built-in WiFi and switches it into tethering mode , after which the WiFi router load-balances WAN traffic between the LTE connection and the hotel’s own WiFi. Unplug the LTE router and it falls back to standalone hotspot mode. Plus, both WiFi networks (the one from the LTE router, and the one from the WiFi router) are named alike and share the same password. This way my WiFi clients don’t even notice the switch from one to the other. This is what I mean by modular . Components don’t depend on each other to function, but recognize each other the moment they are together and adjust accordingly, ideally without any manual intervention from my side. Adding a piece extends the setup, and removing a piece simplifies it rather than breaking it. By dropping the Ultra-Portable Data Center into the same network, for instance, I get a near-perfect replica of my home LAN anywhere in the world, without changing a single configuration along the way. And, yes, that home LAN write-up definitely needs a refresher, as many things have changed over the years; Coming soon™ . The second principle is redundancy with different functionality . Every backup item in my bag must already earn its keep on its own. The classic approach to redundancy (carrying a duplicate of an important device) means paying for the same capability twice in money, space, and weight, while the backup contributes nothing on the (hopefully many) days that nothing breaks. Instead, I’d rather find a device that I’m already carrying for its own reason and that can also step in when something fails. Take my LTE router. The obvious redundancy would be a second LTE router, identical to the first, sitting in my bag purely for the just in case scenario. My actual backup, however, is my phone . It is in my pocket regardless, and if the LTE router ever gives up on me, the phone tethers the same way over USB and offers a similar WiFi hotspot on the go. When tethered, the WiFi router doesn’t even need to know the difference, as all that it sees is a USB Ethernet device anyway. The same logic applies to my laptop . If its screen should ever get smashed during one of my travels , I don’t need a spare laptop, I have my tablet . Over the LAN, the tablet can SSH into the laptop, run a VNC session against my desktop environment, or, with the EVGA XR1 Pro , display the laptop’s HDMI output via VLC . And in case the whole laptop should malfunction, I can plug its USB-C hub into the tablet and use that as a temporary workstation until I can get the laptop fixed or replaced. As a matter of fact, I can do the exact same thing with my phone, because, it too allows me to connect the USB-C hub, plus my keyboard, plus my mouse and even an external HDMI display, if things really go sideways. None of these devices are in my bag because of the laptop, they are there for their own reasons, and happen to be capable of covering for it. The third principle is the priority order I apply to every item in my bag: Weight first, then function , then form . This runs contrary to the trends on “social” media , which tend to put form ahead of everything else. In my setup, an item must first be light enough to be worth carrying, then capable enough to do its job reliably, and only after that does its appearance get a vote. My laptop stands are a good illustration for this principle. They are simple, 3D-printed with PETg, with an infill of 20%, and far from what most people would call good looking . Their job is to raise my laptop’s screen to a comfortable viewing height, which they do reliably while weighing almost nothing. The commercial alternatives are typically machined from aluminum for uLtRa DuRaBiLiTy and for aesthetics , and weigh several times what mine do, while offering durability that I never come close to needing for the actual use case. At cents per print, breaking one is also a non-event, as I can just print another. The same trade-off shows up across the entire setup. 3D prints over machined aluminum, plastic over metal, lightweight pouches over hard cases, USB-C cables over barrel-connector PSUs. Each swap individually shaves only grams, but in aggregate the difference between a thoughtfully chosen and a just bought what looked nice travel kit quickly adds up to several kilograms, which is the difference between a carry-on that I can comfortably wear all day and one that has me dreading every moment of it. The fourth principle is calculated use . Before any item enters my bag, I run the numbers on it. The two formulas I always start with are cost per use (purchase price divided by how often I realistically expect to use it) and cost per time unit (the same idea, but measured per hour, day, or trip of actual use). Those two alone often reveal that a flashy 200 USD gadget I’d touch twice a year is far more expensive per use than the unglamorous 80 USD one I’d reach for daily. For items where the decision isn’t clear-cut from those two, I also calculate the expected value of ownership , factoring in how frequently I’d actually use the item across different trip types, the utility-adjusted cost , weighting the price by how much the item improves the overall setup, not just its own niche, the net present value , treating gear as a multi-year investment with a discount rate, and the replacement cost comparison , to understand how much I’d pay later to replace it versus buying the better option now. Lastly, I evaluate the opportunity cost not only in money but also in bag space and grams, since both are finite resources on the road. Now, you might be thinking that this sounds borderline neurotic for what amounts to picking out hardware, and… well… it probably is. But having had to walk away from items that I had bought and lugged around for months, only to realize they ultimately weren’t worth the bag space, has taught me to be deliberate. The few minutes spent running these numbers up front have saved me significantly more time, money and shoulder pain afterwards. Also, sitting here for now almost 15 minutes straight and reading through this write-up isn’t particularly less autistic either; You’re welcome . :-) So what does my actual setup look like? Let’s dive into the details and go through the items one category at a time. Let’s start with the most basic item in my setup: The power supply. Depending on how long I’m planning to be on-the-go and which parts of my modular desk I’m taking with me, I either bring the UGREEN X757 15202 Nexode Pro GaN 100W 3-Port charger, or its bigger brother, the UGREEN 55474 Nexode 300W GaN 5-Port PSU. On shorter trips with only my primary workstation, my phone and/or my tablet , the portable 100W charger is sufficient. However, on longer trips I usually bring the 300W brick , which allows me to power additional (networking) equipment in parallel. Both UGREEN PSUs are USB-C PD 3.1 capable and support at least 65W on at least one port, which means I can comfortably charge my laptop at full speed while simultaneously powering other things, instead of having to juggle multiple chargers. With almost every device in my setup running off of USB-C PD, from my mobile WiFi router all the way down to my LTE router , I can leave almost all proprietary wall warts (looking at you, Raspberry Pi!) at home and instead only bring a small bag of compact USB-C cables. As an added bonus, that also means I never have to deal with yet another set of region-specific power outlet adapters, beyond a single one for the UGREENs ’ Type A/B and F plugs. Note : Because I’m picking up my hardware in different parts of the world, every socket-bound item has a different plug, which at times makes it really cumbersome to deal with them. Therefor I try to make sure that if a device has a power plug, it is a detachable cable that I could replace for a different plug type in the future. In some cases, as it is with the UGREEN X757 15202 Nexode , this obviously won’t work and I’m stuck with the inferior and comparatively dangerous Type A plug. I don’t have redundancy for the PSU because these items are usually easily available everywhere in case it should break. My primary workstation is a 14" Star Labs StarBook Mk VI , which is an AMD Ryzen 7 5800U machine with 64GB 32GB Corsair Vengeance DDR4 (3200 MHz CL22) RAM and a 2TB SK hynix Gold P31 NVMe SSD. The device runs a hardened Gentoo Linux installation with a minimal Wayland desktop . It weighs around 1.4kg and has sadly become relatively tedious to work with over the years, due to various hardware issues and its lacking performance. Therefor I will be replacing the device with a sub-1.4kg 14" device very soon™ . Because the StarBook only has a single USB-C port and I don’t feel like taking the dedicated USB-C-to-barrel cable with me, I usually bring my uni 8-in-1 USB-C hub with USB-C PD power input. The hub adds three USB-A ports (which I desperately need on the StarBook ), an SD/microSD card reader, an additional HDMI port, and an Ethernet port, and it accepts 100W USB-C PD input while forwarding up to 90W to my laptop. This means a single USB-C cable from the UGREEN charger into the hub powers both, the laptop and any peripherals plugged into it. As a side effect, the hub also makes the StarBook feel like a docking station setup, where I plug or unplug a single cable to instantly add or remove three USB-A peripherals, Ethernet, and a card reader to/from my workstation. However, having only a single USB-C port in 2026 is nevertheless limiting, which is another reason to move away from the Star Labs hardware. To avoid completely screwing up my posture, I use two 3D-printed laptop stands, with added self-adhesive rubber pads, that raise my laptop’s screen a good ~20cm, as mentioned before . The 20% infill PETg prints are super lightweight yet stable, at least once the laptop is in place. Because the two stands are not interconnected, however, they’re not as stable as one of those foldable metal stands, and I wouldn’t recommend trying to use them e.g. on the little tray table in an airplane. I always bring my mechanical keyboard , because my laptop ’s keyboard, like every integrated keyboard, is absolute garbage. To transport my keyboard, I use the NuPhy NuPack , which is intended as an accessory for specific NuPhy keyboards, but it turns out that the pouch fits a variety of other keyboards, including my Kunai Corne v3 . The NuPack also has a dedicated compartment for cables and accessories, which means I don’t have to dig through my bag to find the keyboard’s USB-C cable. When I’m at a proper desk, I lift my laptop using the two 3D-printed stands mentioned above, and I place my keyboard in front of it. When I’m at a café or in any other place with little space, I place a lightweight bridge made out of plastic on top of my laptop and use my keyboard Sonshi-style . The bridge weighs next to nothing, and is shaped to span the keys of the integrated keyboard without putting pressure on them. To complement this, I run , a small helper that automatically disables the laptop’s internal keyboard whenever my external keyboard is connected, so that I don’t accidentally mash arbitrary keys on the integrated keyboard when typing on the Kunai Sonshi-style . I almost always bring my mouse as well, despite my desktop workflow being 99% keyboard driven. There are websites and some applications (e.g. VMs) that are cumbersome to use with the keyboard alone. My mouse of choice is the Razer Basilisk V3 Pro , and depending on where and for how long I’ll be going, I might also bring the Razer Mouse Dock Pro for easy overnight recharging. On shorter trips, I instead rely on the mouse’s built-in battery, which comfortably gets me through a week of regular use, and recharge it via USB-C from the same charger that powers everything else. I used to carry a portable display with me, but ever since I bought the Google Pixel Tablet I have been using that as a “secondary screen” . While it doesn’t support actual HDMI input from my laptop without additional hardware, I don’t really need that, as my primary use case for a secondary screen is for monitoring data streams, and occasionally following along conversations and videos. For quick data sharing between the laptop and the tablet, LocalSend and Syncthing both run on the same LAN (more on that further down ), and for actual remote control I tend to use either an SSH session in Termux or a VNC client. I am however considering an external display, due to the added screen real estate. While the integrated 14" monitor is okay, my aging eyesight would definitely benefit from having a 16" or 18" display to look at. Sadly, most of those options are still too bulky/heavy to be suitable for the ridiculous weight limitations air travel has these days. By using the tablet as an “external monitor” , the device doubles as a backup just in case anything should ever happen to my laptop. Since Android 16, the operating system mimics a desktop well enough for me to be able to work with it in case of emergency. A true portable monitor would be bigger and maybe even heavier than the tablet, yet wouldn’t work independently of the laptop. Given how most hotels and Airbnbs these days have TVs with HDMI input, however, finding a dumb output in case of display failure is easier than finding a computer to work off of temporarily. Note: Having all that said, I’m getting increasingly frustrated of Google ’s garbage hardware and, in particular, the Google Pixel Tablet . Its lacking performance has rendered the device almost useless for many serious tasks, apart from pure media consumption. Even navigating through somewhat packed Grafana dashboards (with auto-refresh) has become painfully slow these days. Hence, I am seriously reconsidering this piece of hardware long-term and I probably wouldn’t recommend it to anyone for more than just media consumption at this point. While I don’t consider myself an audiophile, I do appreciate the difference that decent gear makes once you’ve spent a few years collecting music in lossless formats. To not waste all those FLACs on the (mediocre) DACs of my laptop or my phone , I bring along an iFi hip-dac3 , a compact USB DAC and headphone amplifier. The device handles PCM up to 384kHz and DSD256, has both a 4.4mm balanced and a 3.5mm single-ended output, an XBass+ switch for low-end emphasis, and an XSpace switch that simulates a more open soundstage. I usually pair the hip-dac3 with my phone when on the go, or with my laptop when at the desk, to listen to my self-hosted Jellyfin music library that lives on my Ultra-Portable Data Center . Beyond the sound quality improvement, the hip-dac3 also lets me avoid Bluetooth, which I generally distrust security-wise and which I’d rather not blast at my head for hours every day. Lower-end Bluetooth headphones combined with Android also tend to produce occasional disconnects and audio glitches when running LDAC , which is something I don’t want to deal with anymore. Battery life on the hip-dac3 is solid enough that I can leave it on the desk for a full work day or carry it around for an entire flight without having to worry about it dying mid-track. And when I do need to top it up, it charges via the same USB-C source as everything else. For video, I often carry the EVGA XR1 Pro , a USB-C HDMI capture device that turns any HDMI output into a webcam-style USB Video Class ( UVC ) stream. Whenever I need a high-quality video feed, for example for a video call or for content recorded for my (currently inactive) YouTube channel , I plug the HDMI output of either my Fujifilm X100VI or my Sony Alpha 7 III into the XR1 Pro , which my laptop then sees as a regular webcam. The picture quality, optics, and color reproduction of either camera blow any integrated laptop webcam (and any of those overpriced 4K USB webcams ) out of the water, especially in the kind of mediocre lighting one tends to find in hotel rooms. As a bonus, the XR1 Pro also doubles as a fallback display path. As mentioned earlier, in case my laptop’s screen should ever die mid-trip, I can feed the laptop’s HDMI output into the capture device and view it on my tablet via VLC to keep working until I can get the display fixed or replaced. On longer trips, and only on longer trips, I sometimes break my own weight rule and bring along my Teenage Engineering OP-1 . At nearly 600g without its protective gear, it is by far the heaviest non-essential item that ever ends up in my bag , and the only one I let in for purely creative reasons rather than productive ones. When spending months on the road it’s important to bring something fun, and the OP-1 is the most travel-friendly synth/sampler I own. It’s a self-contained creative outlet that fits on a hotel desk without dragging an entire studio along. The catch is that the OP-1 ’s integrated speaker is, frankly, a gimmick. It is fine for previewing what you just played, but nowhere near good enough for actual listening or for mixing anything down. In practice that means I always pair it with my wired headphones , since I don’t carry a portable speaker with an AUX input that would do the device justice. For transit, the OP-1 lives inside a Decksaver TE OP-1 Cover , which itself sits in a dedicated Teenage Engineering Large Duty Bag , both of which add roughly another 170g on top. The OP-1 unapologetically fails the calculated use test by any rational metric, but it earns its spot purely through the joy it brings me on long trips. Networking is probably where the modular aspect of my travel setup shines the most. Just as with the rest of my equipment, every networking device can function on its own and remains useful in different combinations. Depending on whether I’m hopping between places or settling in city for a longer stay, I might bring only the bare minimum (just my LTE router, acting as a hotspot), or my full setup that consists of a dedicated mobile WiFi router, an Ethernet switch, and the Ultra-Portable Data Center . The thinking here is the same as with the rest of my equipment. I want to be able to recreate as much of my home area network as possible, in any location, while still having the flexibility to leave parts behind if they don’t make sense for the trip. Tethered hotspot at the airport? Just the LTE router. Hotel room with mediocre WiFi for a few weeks? Add the WiFi router, the switch, and the UPDC . The key is that these devices are configured and wired up the same way regardless of where I am, which means I never have to mess with configurations on the road. The setup just extends , like LEGO . For mobile data I’ve been carrying the Netgear Nighthawk M2 for several years now. The device is a 4G / LTE-A Cat. 20 router with a built-in battery and a small color touchscreen, and despite being almost seven years old at this point, it still holds up for the most part. When I’m out and about, the M2 acts as a straightforward mobile hotspot, providing connectivity through its own WiFi to my laptop , phone and tablet . When I’m settled at the travel desk, however, the M2 connects as a client to whatever WiFi the venue offers (be it a hotel, an Airbnb, or a co-working space) and re-shares that connection to my mobile WiFi router via USB tethering. Because of how the WiFi router is configured, plugging the M2 into it automatically disables the M2 ’s WiFi hotspot and switches it into tethering mode , where it acts as a USB Ethernet device. The mobile router then load-balances WAN traffic between the venue’s WiFi (making the M2 a WiFi client) and the M2 ’s LTE connection, which gives me a fairly resilient internet uplink without having to fiddle with any settings. Additionally, both WiFi networks, the one of the M2 and the one of my mobile WiFi router, are configured in the same way, so that clients don’t even notice the switch. The Netgear has, however, started showing its age in the past year or so. It has begun crashing and rebooting at random, and reports increasingly nonsensical battery charge percentages, which I’m fairly certain is due to the now almost 7 year old internal battery, which is user-replaceable but seemingly very hard to find. In addition to the battery, the touch buttons on the device have also started malfunctioning, with presses not being registered most of the time. As I begin to lose trust in the device, I’m in the process of replacing it with the GL.iNet Mudi 7 ( GL-E5800 ). The Mudi 7 supports 5G NSA/SA , multiple SIM/eSIM cards, and runs OpenWrt with GL.iNet ’s firmware layer on top, much like the Slate 7 I’m already using. Multi-SIM in particular is interesting for me, as it lets me keep separate SIMs for different countries or carriers active simultaneously, without having to physically swap cards every time I cross a border. That said, I’m skeptical about how the Mudi 7 will perform when it comes to battery runtime. 5G modems and the more sophisticated hardware around them will inevitably draw significantly more power than the Nighthawk does. Also, the device is clearly heavier and more bulky than the M2 , which is going to be a significant downside. Given its importance, however, it is a trade-off I’m willing to make. Time will tell whether the Mudi 7 will turn out to be a worthy successor, or whether I’ll have to keep the M2 on life support a little longer until something better comes along. The centerpiece of my travel network is the GL.iNet Slate 7 ( GL-BE3600 ), a Wi-Fi 7 dual-band travel router that weighs a mere 295g and is powered via USB-C PD . I covered the device in detail in its own review not too long ago, so I’ll keep this section brief. The Slate 7 replaced my long-running Linksys WRT3200 ACM as my primary router, mostly thanks to its compact 130×91×34mm form factor, dual 2.5 GbE Ethernet ports, USB-A tethering input, and the convenience of being able to power it directly from the same UGREEN charger that powers everything else. The built-in touchscreen is a nice extra, as it displays connection stats, VPN status, and a QR code for quickly joining the network from any device. The router runs an OpenWrt 23.05-SNAPSHOT fork with GL.iNet ’s firmware layer on top, which gives me both root SSH access and a friendly admin UI, even if it isn’t a fully vanilla OpenWrt experience. The bigger reason the Slate 7 stays in my bag, however, is that it turns whatever environment I’m in into a familiar LAN. All my devices ( laptop , phone , tablet , UPDC ) connect to the same network regardless of where I am, which means tools like Syncthing and LocalSend work out of the box, Jellyfin playback follows me from device to device, and SSH between machines uses local IPs without any configuration gymnastics. It also means I can run a single WireGuard VPN connection on the router itself and route the entire LAN through it when needed, which is great for circumventing geo-IP limitations on services and similar shenanigans, without having to configure a VPN client on every individual device, including the ones that don’t even support one. Because the Slate 7 only has a single 2.5 GbE LAN port, I usually carry a Netgear GS305 5-port gigabit switch as well. I tend to prefer wired connections wherever possible, both for stability/throughput and for security reasons. The GS305 is unmanaged, dirt cheap, and has been working flawlessly for years, but it has two notable downsides: It tops out at 1 GbE, which becomes the bottleneck in a setup with 2.5 GbE endpoints, and it requires its own dedicated barrel connector cable. I’m therefore looking to replace it with something like the Ubiquiti Flex Mini 2.5G 5-port switch, which matches the Slate 7 ’s 2.5 GbE link, and which can be powered via USB-C , resulting in yet another barrel-connector adapter that I can leave at home. On longer trips, the Ultra-Portable Data Center (v2) always travels with me. The UPDC v2 is a Raspberry Pi 5-based NAS that I built in 2024, replacing the original mini-ITX-based UPDC v1 . The device runs two 4TB NVMe drives in mirrored RAID1 ( ) on top of LUKS, served over the LAN via Samba , Syncthing and Jellyfin , and packs a 4-cell 18650 UPS HAT, a handful of environmental sensors and a small LCD into a 3D-printed cube that weighs about 800g (with the optional stand) and measures 114mm a side. It is in essence a very compact, travel-ready NAS that I can plug straight into the Slate 7 ’s LAN port and have all my data, services, and music library available on the road, without ever touching the cloud . For a deep-dive into the hardware choices, the enclosure, the migration from TrueNAS SCALE , and the full software stack, please refer to the dedicated UPDC post . One major disadvantage of the UPDC , however, is the fact that the Raspberry Pi 5 requires its own dedicated power supply due to its special 5.1V/5A USB-C PD voltage requirements , which most generic chargers and power banks simply don’t speak. This means I cannot share the UPDC ’s power source with the rest of my travel setup, and I have to bring along a dedicated CanaKit 45W USB-C power supply just for the Pi. To make matters worse, despite the dedicated PSU I have never been able to fully get rid of the occasional warnings that show up in from time to time. The Pi 5 is a notoriously whiny little b…oard in that regard, and Raspberry is arguably to blame for it. Performance-wise the under-voltage events have no noticeable impact on my workloads (which are mostly Syncthing , Samba , and the occasional Jellyfin transcode), but they’re a reminder that the Pi 5’s power story isn’t quite as easy as I would expect. The Ultra-Portable Data Center project was a fun thing to build and has served me well, but with more elaborate and truly minimal all-in-one solutions becoming available these days (the Beelink ME mini and the UnifyDrive UT2 being prominent candidates I’m keeping an eye on), I might at some point move away from a self-built solution in favour of something off-the-shelf that doesn’t need a separate PSU. As things stand today, however, the UPDC remains the most travel-friendly option for me, and the only one that gives me an end-to-end open-source storage stack that I fully control. The remainder of my bag is filled with the small connective tissue that holds the rest of the setup together. Whether or not these items come along depends entirely on the length and nature of the trip, but each of them has earned a spot in the lineup the same way the bigger pieces did. The first of these is a small, modular tablet rig made up of two parts. The Lyrcro desktop microphone tripod is, as the name suggests, intended for desktop microphones, but its 3/8" screw thread doubles as a perfectly good universal mount for anything that takes the same standard. What I most often attach to it is the KDD Tablet Tripod Clamp-Mount as well as some no-name ballhead connecting the two items. The clamp holds my tablet (as well as my phone ) securely on top of the tripod and lets me park the device right next to my laptop, at exactly the same height as the screen sitting on top of its 3D-printed stands. The result is a makeshift dual-screen desk that takes seconds to assemble. As a nice side effect, the same little tripod is also sturdy enough to support my Fujifilm X100VI when I want to use the camera as a webcam via the EVGA XR1 Pro , despite being technically rated for microphones only. Next, there is a small organizer pouch full of USB adapters that I keep refusing to leave behind, because every single one of them has saved me at least once. I carry USB-A to USB-C and USB-C to USB-A converters for situations in which whoever designed that particular hotel TV or rental car decided that 2026 isn’t quite ready for USB-C yet, as well as L-shaped (90°) and U-shaped (180°) USB-C adapters that let me plug cables into my laptop or my phone at angles other than straight out , which matters more than you’d think when working off a nightstand or when using a device on a tripod. None of these adapters cost much, none of them weigh much, but each of them turns a potential problem into a non-event the moment it appears. I already mentioned the Razer Mouse Dock Pro briefly in the keyboard & mouse section , but it is worth revisiting here as a true accessory . On shorter trips it stays home, and the Basilisk V3 Pro ’s built-in battery covers me for a week without complaint. On longer trips, however, the dock comes along, both for the convenience of overnight wireless recharging and because, in the rare event the mouse runs flat mid-day, dropping it onto the dock for a few minutes is faster than digging out a USB-C cable. Lastly, my Seeed Studio SenseCAP T1000-E LoRa/Meshtastic card travels with my EDC regardless of the trip. The card weighs next to nothing, lives in the same pouch as the rest of my EDC, and lets me scan for and join Meshtastic communities in whichever region I happen to be in. On a fun day, that means chatting over LoRa with strangers on the other side of a city. On a less fun day, it doubles as a fully off-grid communication device that doesn’t care whether the local mobile network is up, down, or compromised. It’s a small but meaningful piece of the preparedness side of my travel kit, in case anything more serious than the usual hotel WiFi outage should ever happen. What this setup ultimately gives me is the confidence to open my bag in any environment, anywhere in the world, and have a familiar workstation within minutes, all without having to check-in one of Pelican ’s SuperMAC rack mount cases. Instead of a compromised version of my home office, I get a fully-featured, modular workspace that scales from a single laptop on a plane’s tray table all the way to a multi-device LAN with NAS, capture hardware, and high-fidelity audio in a hotel room. Every component has been chosen, replaced, or rebuilt over the years, sometimes more than once, with weight, modularity, redundancy, and calculated use as the guiding principles. Nothing here is in my bag because it looked nice on Instagram , but because it has earned its spot through repeated, real-world use. If there’s one piece of advice I’d give anyone considering building a similar setup, it is the following: Resist the urge to copy someone else’s packing list , including this one. Your own travel patterns, constraints, and physical comfort will dictate what actually deserves to end up in your bag. Use this post as inspiration, but pick each item based on your workflow, your destinations, and your tolerance for carrying things around . The most minimal setup is not the one with the fewest items, but the one in which every item is actually indispensable and useful.

0 views
Chris Coyier 2 months ago

The New Van

I got something I’ve wanted for years and years! A camper van! I’m a camper van guy now! It’s a Mercedes-Benz Sprinter, and even more technically a Winnebago Revel . I scoured Craigslist, Facebook Marketplace, and RV-specific sites for a long time drooling over these things. I’ve rented a half dozen of them on Ourdoorsy over the years. I’ve borrowed friends. So I feel like I knew what I wanted and I knew the specific price range I could go, so it took a little while to find it. Ultimately one that came up on Craigslist led back to one sitting on the lot at a local spot called Just Used Cars . I liked the size of it. Just a normal length, not “extended”. Plenty of height to stand up in. I like that it’s an actual Sprinter base because of it’s nice poise/stance compared to other van bases. Also it’s 4WD and has good ground clearance which. That wasn’t a requirement for me, but this will make me trust it driving in the winter and up to Mt. Bachelor and such, which will be really nice. Although funnily enough, I’ve already gotten it stuck once out in Pacific City at the beach — even in 4WD Low and using the traction boards on the roof. Sand is rough. I like the tan color as well. Maybe I’ll get some cool decal or have an artist paint the side or something someday. I wasn’t specifically looking for a Winnebago Revel, but that’s just how those roll, and honestly, the Winnebago name sounds nice to me. Long history making campers, obviously. The interest rate on this thing was horrible. It’s 8 or 9% or something. It doesn’t really matter, as my plan is to pay it off in the next few months. My thinking is that it will do great things for my credit score this way. We’ll see. I co-signed for a “normal” new car just recently, and that rate was 3%, which seems fine/good. I started writing a bunch more little stories about the van. I’ve been using it and thinking about it and working on it a ton, so there is a bunch to say. But I think I’ll break those out into smaller blog posts as I go! One quick one: after I bought it, the dealership called and told me the previous owner wanted to talk to me. I approved them giving him my phone number, we chatted, and he came over to see the van. I was able to return to him some things that belonged to him tucked away into crannies all over the van. He was a nice guy who just really really wanted the new owner to understand it . All the little details about how it worked and where you can put things and quirks and whatnot. We spent a few hours going over things. I really appreciated that, and it shows how attached some people can get to these homes-on-wheels.

0 views
Jeff Geerling 2 months ago

Tuning in FM Radio on a 3D Printer Heatbed

Pooch from Repkord dropped by my studio while he was in St. Louis, and asked a simple question: Can a 3D printer's heatbed act as an antenna? A fair question, as many an antenna is embedded in a PCB these days... and the traces on a PCB heatbed like the one used in Prusa's Core One look kinda like an antenna, if you squint the right way. Really, anything (or anyone) can be an antenna, given enough power.

0 views

SQLAlchemy 2 In Practice - Chapter 4 - Many-To-Many Relationships

This is the fourth chapter of my SQLAlchemy 2 in Practice book. If you'd like to support my work, I encourage you to buy this book, either directly from my store or on Amazon . Thank you! Continuing with the topic of relationships, this chapter is dedicated to the many-to-many type, which as its name implies, is used when it is not possible to identify any of the sides as a "one" side.

0 views
Justin Duke 5 months ago

Past Lives

I am legitimately struggling to articulate why Past Lives did not quite resonate with me the way it did with so many others. I found it beautiful without being indulgent — the lighting in the third act bar, for instance, or the long, luxurious tracking shot to close out the film are both stunning. The triptych of lead performances are all extremely solid, perhaps most of all that of John Magaro playing Arthur. The films that this is in conversation with — Lost in Translation and In the Mood for Love — are major touchstones for me. And yet something just didn't quite hit, and left the film merely at the status of admiration rather than love. Perhaps it was the neatness of the framing device and the way we don't quite spend enough time with our central character in any one era to have a really strong and intimate understanding of who they were and are. Song, playwright by training, deploys a bizarre barbell of extreme economy punctuated by monologue. Nora, her autofictional insert, is an oddly thin character — she has little chemistry with either of the male leads and little interiority beyond that of her career goals. This might be the pleasantness of the film's aesthetic working against it: in a quest to make every shot subdued and beautiful, Song smooths away the knots and edges that make things feel alive. That's too harsh for how I feel — this was a lovely film, just left me a little colder than I was expecting.

0 views
(think) 5 months ago

Neocaml 0.1: Ready for Action

neocaml 0.1 is finally out! Almost a year after I announced the project , I’m happy to report that it has matured to the point where I feel comfortable calling it ready for action. Even better - recently landed in MELPA , which means installing it is now as easy as: That’s quite the journey from “a fun experimental project” to a proper Emacs package! You might be wondering what’s wrong with the existing options. The short answer - nothing is wrong per se, but offers a different set of trade-offs: Of course, is the youngest of the bunch and it doesn’t yet match Tuareg’s feature completeness. But for many OCaml workflows it’s already more than sufficient, especially when combined with LSP support. I’ve started the project mostly because I thought that the existing Emacs tooling for OCaml was somewhat behind the times - e.g. both and have features that are no longer needed in the era of . Let me now walk you through the highlights of version 0.1. The current feature-set is relatively modest, but all the essential functionality one would expect from an Emacs major mode is there. leverages TreeSitter for syntax highlighting, which is both more accurate and more performant than the traditional regex-based approaches used by and . The font-locking supports 4 customizable intensity levels (controlled via , default 3), so you can pick the amount of color that suits your taste. Both (source) and (interface) files get their own major modes with dedicated highlighting rules. Indentation has always been tricky for OCaml modes, and I won’t pretend it’s perfect yet, but ’s TreeSitter-based indentation engine is already quite usable. It also supports cycle-indent functionality, so hitting repeatedly will cycle through plausible indentation levels - a nice quality-of-life feature when the indentation rules can’t fully determine the “right” indent. If you prefer, you can still delegate indentation to external tools like or even Tuareg’s indentation functions. Still, I think most people will be quite satisfied with the built-in indentation logic. provides proper structural navigation commands ( , , ) powered by TreeSitter, plus integration definitions in a buffer has never been easier. The older modes provide very similar functionality as well, of course, but the use of TreeSitter in makes such commands more reliable and robust. No OCaml mode would be complete without REPL (toplevel) integration. provides all the essentials: The default REPL is , but you can easily switch to via . I’m still on the fence on whether I want to invest time into making the REPL-integration more powerful or keep it as simple as possible. Right now it’s definitely not a big priority for me, but I want to match what the other older OCaml modes offered in that regard. works great with Eglot and , automatically setting the appropriate language IDs for both and files. Pair with ocaml-eglot and you get a pretty solid OCaml development experience. The creation of LSP really simplified the lives of a major mode authors like me, as now many of the features that were historically major mode specific are provided by LSP clients out-of-the-box. That’s also another reason why you probably want to leaner major mode like . But, wait, there’s more! There’s still plenty of work to do: If you’re following me, you probably know that I’m passionate about both Emacs and OCaml. I hope that will be my way to contribute to the awesome OCaml community. I’m not sure how quickly things will move, but I’m committed to making the best OCaml editing experience on Emacs. Time will tell how far I’ll get! If you’re an OCaml programmer using Emacs, I’d love for you to take for a spin. Install it from MELPA, kick the tires, and let me know what you think. Bug reports, feature requests, and pull requests are all most welcome on GitHub ! That’s all from me, folks! Keep hacking! is ancient and barely maintained. It lacks many features that modern Emacs users expect and it probably should have been deprecated a long time ago. is very powerful, but also very complex. It carries a lot of legacy code and its regex-based font-locking and custom indentation engine show their age. It’s a beast - in both the good and the bad sense of the word. aims to be a modern, lean alternative that fully embraces TreeSitter. The codebase is small, well-documented, and easy to hack on. If you’re running Emacs 29+ (and especially Emacs 30), TreeSitter is the future and is built entirely around it. - Start or switch to the OCaml REPL - Send the current definition - Send the selected region - Send the entire buffer - Send a phrase (code until ) to quickly switch between and files Prettify-symbols support for common OCaml operators Automatic installation of the required TreeSitter grammars via Compatibility with Merlin for those who prefer it over LSP Support for additional OCaml file types (e.g. ) Improvements to structured navigation using newer Emacs TreeSitter APIs Improvements to the test suite Addressing feedback from real-world OCaml users Actually writing some fun OCaml code with

0 views
David Bushell 5 months ago

Declarative Dialog Menu with Invoker Commands

The off-canvas menu — aka the Hamburger , if you must — has been hot ever since Jobs’ invented mobile web and Ethan Marcott put a name to responsive design . Making an off-canvas menu free from heinous JavaScript has always been possible, but not ideal. I wrote up one technique for Smashing Magazine in 2013. Later I explored in an absurdly titled post where I used the new Popover API . I strongly push clients towards a simple, always visible, flex-box-wrapping list of links. Not least because leaving the subject unattended leads to a multi-level monstrosity. I also believe that good design and content strategy should allow users to navigate and complete primary goals without touching the “main menu”. However, I concede that Hamburgers are now mainstream UI. Jason Bradberry makes a compelling case . This month I redesigned my website . Taking the menu off-canvas at all breakpoints was a painful decision. I’m still not at peace with it. I don’t like plain icons. To somewhat appease my anguish I added big bold “Menu” text. The HTML for the button is pure declarative goodness. I added an extra “open” prefix for assistive tech. Aside note: Ana Tudor asked do we still need all those “visually hidden” styles? I’m using them out of an abundance of caution but my feeling is that Ana is on to something. The menu HTML is just as clean. It’s that simple! I’ve only removed my opinionated class names I use to draw the rest of the owl . I’ll explain more of my style choices later. This technique uses the wonderful new Invoker Command API for interactivity. It is similar to the I mentioned earlier. With a real we get free focus management and more, as Chris Coyier explains . I made a basic CodePen demo for the code above. So here’s the bad news. Invoker commands are so new they must be polyfilled for old browsers. Good news; you don’t need a hefty script. Feature detection isn’t strictly necessary. Keith Cirkel has a more extensive polyfill if you need full API coverage like JavaScript events. My basic version overrides the declarative API with the JavaScript API for one specific use case, and the behaviour remains the same. Let’s get into CSS by starting with my favourite: A strong contrast outline around buttons and links with room to breath. This is not typically visible for pointer events. For other interactions like keyboard navigation it’s visible. The first button inside the dialog, i.e. “Close (menu)”, is naturally given focus by the browser (focus is ‘trapped’ inside the dialog). In most browsers focus remains invisible for pointer events. WebKit has bug. When using or invoker commands the style is visible on the close button for pointer events. This seems wrong, it’s inconsistent, and clients absolutely rage at seeing “ugly” focus — seriously, what is their problem?! I think I’ve found a reliable ‘fix’. Please do not copy this untested . From my limited testing with Apple devices and macOS VoiceOver I found no adverse effects. Below I’ve expanded the ‘not open’ condition within the event listener. First I confirm the event is relevant. I can’t check for an instance of because of the handler. I’d have to listen for keyboard events and that gets murky. Then I check if the focused element has the visible style. If both conditions are true, I remove and reapply focus in a non-visible manner. The boolean is Safari 18.4 onwards. Like I said: extreme caution! But I believe this fixes WebKit’s inconsistency. Feedback is very welcome. I’ll update here if concerns are raised. Native dialog elements allow us to press the ESC key to dismiss them. What about clicking the backdrop? We must opt-in to this behaviour with the attribute. Chris Ferdinandi has written about this and the JavaScript fallback . That’s enough JavaScript! My menu uses a combination of both basic CSS transitions and cross-document view transitions . For on-page transitions I use the setup below. As an example here I fade opacity in and out. How you choose to use nesting selectors and the rule is a matter of taste. I like my at-rules top level. My menu also transitions out when a link is clicked. This does not trigger the closing dialog event. Instead the closing transition is mirrored by a cross-document view transition. The example below handles the fade out for page transitions. Note that I only transition the old view state for the closing menu. The new state is hidden (“off-canvas”). Technically it should be possible to use view transitions to achieve the on-page open and close effects too. I’ve personally found browsers to still be a little janky around view transitions — bugs, or skill issue? It’s probably best to wrap a media query around transitions. “Reduced” is a significant word. It does not mean “no motion”. That said, I have no idea how to assess what is adequately reduced! No motion is a safe bet… I think? So there we have it! Declarative dialog menu with invoker commands, topped with a medley of CSS transitions and a sprinkle of almost optional JavaScript. Aren’t modern web standards wonderful, when they work? I can’t end this topic without mentioning Jim Nielsen’s menu . I won’t spoil the fun, take a look! When I realised how it works, my first reaction was “is that allowed?!” It work’s remarkably well for Jim’s blog. I don’t recall seeing that idea in the wild elsewhere. Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds.

0 views
Giles's blog 6 months ago

Writing an LLM from scratch, part 32d -- Interventions: adding attention bias

I'm still seeing what I can do to improve the test loss for a from-scratch GPT-2 small base model, trained on code based on Sebastian Raschka 's book " Build a Large Language Model (from Scratch) ". This is the third intervention I'm trying: adding bias to the attention weight matrices. In the code from the book, we have this: So: we initialise the weights W q , W k and W v as linear layers rather than simple matrices of weights, and have a parameter to say whether or not we should add bias to those. In all of our trains so far we've set that to . Why do we have this parameter, and where did it come from? In Raschka's book, the use of the for these weights is introduced in section 3.4.2 with the wording: We can improve the implementation further by utilizing PyTorch's layers, which effectively perform matrix multiplication when the bias units are disabled. Additionally, a significant advantage of using instead of manually implementing is that has an optimized weight initialization scheme, contributing to more stable and effective model training. So, it's presented essentially as a way of getting better weights for our untrained model, which makes good sense in and of itself -- but, if that's the only reason, why don't we just hard-wire it to have ? That would be the sensible thing to do if the initialisation were the only reason, but clearly there's more to it than that. Section 4.1 has a bit more information: determines whether to include a bias vector in the layers of the multi-head attention ... We will initially disable this, following the norms of modern LLMs, but we will revisit it in chapter 6 when we load pretrained GPT-2 weights from OpenAI into our model. That looks like a typo, as the real explanation is in chapter 5, section 5 (page 164 in my copy), where we do indeed load the OpenAI weights: OpenAI used bias vectors in the multi-head attention module's linear layers to implement the query, key and value matrix computations. Bias vectors are not commonly used in LLMs anymore as they don't improve the modeling performance and are thus unnecessary. So, that all makes sense so far. QKV bias was part of the original GPT-2 models, perhaps just because it was standard at the time, inherited from something else, or perhaps for some other reason -- I can't find any reference to it in the actual paper . But people have found it doesn't help, so no-one uses it these days. But... is there some way in which an LLM of this specific size, or in some other way similar to the GPT-2 small model that we're training, might in some way benefit from having bias? That's what this experiment is for :-) One thing that occurred to me while setting this up is that we have been training on a Chinchilla-optimal number of tokens, 20x the number of parameters. Without QKV bias, we have 163,009,536 parameters, so we've been training on 3,260,190,720 tokens, rounded up to the nearest batch size, which is 3,260,252,160 in our current setup for these experiments (per-GPU micro-batches of 12, with 8 GPUs, so a total batch size of 96). These extra bias terms will be parameters, though! We're essentially making our model larger by adding them, which changes the Chinchilla calculation. How much? OK, that's essentially nothing -- 27,648 extra total paramaters on top of 163 million. I make it less than two hundredths of a percentage point larger! The correct number of tokens goes up to 3,260,743,680, so if we wanted to be very pedantic, we're under-training. But I feel like training on a larger dataset is worse in terms of comparability between the baseline and our "intervened-on" model with QKV bias. So: we'll train a model with QKV bias on 3,260,252,160 tokens, accepting that it's a tiny bit less than Chinchilla-optimal. Let's see how it goes! Here's the config file for this train. Running it gives this training chart: Pretty standard, though the loss spikes look less prominent than they have been in the other trains. Might QKV bias actually help with model stability in some way...? The train finished with these stats: Timing-wise, pretty much indistinguishable from the baseline train's 12,243.523 seconds. The final train loss looks a tad better, but we can't rely on that -- the test set loss is the important one. So it was time to download it, upload it to Hugging Face Hub , and then on to the evals. Firstly, our normal "how should you continue ": Not bad at all, borderline coherent! Next, the loss on the test set: Well, crap! Now that's a surprise. Let's look at that in the context of the other interventions to see how surprising that is, given Raschka's comments (which were undoubtedly backed up by serious research): So, adding QKV bias actually improved our test set loss by more than gradient clipping did! The loss spikes in the training chart look smaller than in the other trains 1 , so, speculating wildly, perhaps with a model of this size, the bias stabilises things somehow? Or perhaps what we're seeing is the model become that tiny bit smarter because it has some extra parameters -- albeit less than 0.02 percent more? I'm not going to spend time investigating things now, but this is a really interesting result. One extra thing that does occur to me is that the direction research has taken since GPT-2 has definitely been in the direction of larger models. The attention weight matrices are sized d emb × d emb , so excluding bias they have d emb 2 weights each. Bias adds on another d emb . So, as a model scales up, the attention-related non-bias weights will scale quadratically -- doubling d emb will square their number -- while the bias weights will scale linearly. So perhaps it's just that the effect -- whatever causes it -- gets rapidly swamped as you scale out of toy-model territory. That, at least, seems pretty plausible. One final note to self, though: these improvements are small enough that I do find myself wondering whether or not it might be some kind of noise, despite the setting of the random seeds I'm doing: I think that at the end of this, before I do a final train, it would be worth doing another baseline train and measuring the test set loss again, and doing another comparison. If it comes out exactly the same -- and I can bump up the number of significant figures in the output, it's just a formatting parameter -- then I don't need to worry. But if they vary to some degree, perhaps I'll need to update my mental model of what level of finding is significant, and what isn't. I think it goes without saying that QKV bias definitely goes onto the list of interventions we want to add when training our best-possible GPT-2 small-scale model, assuming that the random seed test goes well. That surprises me a bit, I was expecting it to have negligible impact! That, of course, is why it's worth doing these tests. Next up, I think, is trying to understand how we can tweak the learning rate, and its associated parameters like weight decay. This will need a bit of a deep dive, so you can expect the next post late next week, or perhaps even later. I'm sure you can't wait ;-) Note to self: is there some way I could quantitatively measure those?  ↩ Note to self: is there some way I could quantitatively measure those?  ↩

0 views
Evan Schwartz 6 months ago

Scour - January Update

Hi friends, In January, Scour scoured 805,241 posts from 16,555 feeds (939 were newly added). I also rolled out a lot of new features that I'm excited to tell you about. Maybe because of some of these, I found more posts than usual that I thought were especially worth sharing. You can find them at the bottom of this post. Let's dive in! The Scour homepage has been completely revamped. It includes a new tagline, a more succinct description, and a live demo where you can try out my feed right from that page. Let me know what you think! Scour also finally has its own logo! (And it looks great on my phone's home screen, if I do say so myself! See below ) Have you ever wondered how Scour works? There is now a full documentation section, complete with detailed write-ups about Interests , Feeds , Reactions , How Ranking Works , and more. There are also guides specifically for RSS users and readers of Hacker News , arXiv , Reddit , and Substack . All of the docs have lots of interactive elements, which I wrote about in Building Docs Like a Product . My favorite one is on the Hacker News guide where you can search for hidden gems that have been submitted to HN but that have not reached the front page. Thanks to Tiago Ferreira , Andrew Doran , and everyone else who gave me the feedback that they wanted to understand more about how Scour works! Scour is now a Progressive Web App (PWA). That means you can install it as an icon on your home screen and access it easily. Just open Scour on your phone and follow the instructions there. Thanks to Adam Benenson for the encouragement to finally do this! This is one of the features I have most wanted as a user of Scour myself. When you're browsing the feed, Scour now keeps track of which items you've seen and scrolled past so it shows you new content each time you check it. If you don't want this behavior, you can disable it in the feed filter menu or change your default view to show seen posts. If you subscribe to specific feeds, as opposed to scouring all of them, it's now easier to find the feed for an article you liked . Click the "..." menu under the post, then "Show Feeds" to show feeds where the item was found. When populating that list, Scour will now automatically search the website where the article was found to see if it has a feed that Scour wasn't already checking. This makes it easy to discover new feeds and follow websites or authors whose content you like. This was another feature I've wanted for a long time myself. Previously, when I liked an article, I'd copy the domain and try to add it to my feeds on the Feeds page. Now, Scour does that with the click of a button. Some of the most disliked and flagged articles on Scour had titles such as "The Top 10..." or "5 tricks...". Scour now automatically penalizes articles with titles like those. Because I'm explicitly trying to avoid using popularity in ranking , I need to find other ways to boost high-quality content and down-rank low-quality content. You can expect more of these types of changes in the future to increase the overall quality of what you see in your feed. Previously, posts found through Google News links would show Google News as the domain under the post. Now, Scour extracts the original link. You can now navigate your feed using just your keyboard. Type to get the list of available keyboard shortcuts. Finally, here are some of my favorite posts that I found on Scour in January. There were a lot! Happy Scouring! Have feedback for Scour? Post it on the feedback board and upvote others' suggestions to help me prioritize new features! I appreciate this minimalist approach to coding agents: Pi: The Minimal Agent Within OpenClaw , even though it didn't yet convince me to switch away from Claude Code. A long and interesting take on which software tools will survive the AI era: Software Survival 3.0 . Scour uses Litestream for backup. While this new feature isn't directly relevant, I'm excited that it's now powering Fly.io's new Sprites offering (so I expect it to be a little more actively developed): Litestream Writable VFS . This is a very cool development in embedding models: a family of different size (and, as a result, cost) models whose embeddings are interoperable with one another: The Voyage 4 model family: shared embedding space with MoE architecture . A thought-provoking piece from Every about How AI Made Pricing Hard Again . TL;DR: over are the days where SaaS businesses have practically zero marginal cost for additional users or additional usage. A nice bit of UX design history about the gas tank arrow indicator on a car, with a lesson applied to AI: The Moylan Arrow: IA Lessons for AI-Powered Experiences . Helpful context for Understanding U.S. Intervention in Venezuela . Stoolap: an interesting new embedded database. Stoolap 0.2 Released For Modern Embedded SQL Database In Rust . I keep browsing fonts and, while I decided not to use this one for Scour, I think this is a neat semi-sans-serif from an independent designer: Heliotrope .

0 views
ava's blog 6 months ago

a month without caffeine - conclusion

In January, I wrote about doing a month without caffeine and gave an update one week in. In the original post, I wrote about realizing I was using it to override exhaustion rather than addressing it. I had been relying on matcha, black tea, come coffee and caffeinated water flavours to get through poor sleep, university pressure, workouts, and social commitments, which ultimately led to burnout. So I decided to quit for a month, and also not allow any decaf products, since they also contain a lesser amount. I experienced withdrawal headaches, nausea and changes to my hunger, but also my energy became steadier, my mood calmer, and my concentration more sustainable without the sharp spikes and crashes. I concluded with some lessons for when I resume, namely reserving caffeinated drinks for when it really matters, not consuming them after noon, reducing the caffeine intake (less strong matcha or black tea, less coffee shots etc.) and not using it to suppress hunger or other needs. Now that the month has passed, I'm back to report that it continued like the first post ended; I feel very calm, emotions and situations are more manageable, focus and task-switching is less of an issue. Getting up and going to bed feel easier. What took the longest to normalize were the gastrointestinal effects; it became clear my body relied on the caffeine to do that business at the usual times, and at first, everything was very delayed and I dealt with constipation. But during the third week, it went back to normal. I've had quite a few moments towards the end where I almost gave in, but I persisted. Sometimes I just really crave a specific taste or mouthfeel, and nothing can really replace matcha for me. It's such a comfort and reward. I'm also very, very used to having specific kind of beverages to study or work on something, so breaking that was difficult. I think this reset was great. I found out I can just go without caffeine as well without a meaningful drop in productivity, and I genuinely feel happier, more rested and stable. Now I know it's still entirely optional and I can enjoy it for the taste or specific rituals to get ready :) I like to think I have reset my palate with this too, which will come in handy for upcoming matcha reviews ! Now I will enjoy a mocha chocolate bar I saved for this! Reply via email Published 04 Feb, 2026

0 views