<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Willow at large</title><link>https://willow.al/</link><description>The macroblog of Willow et al</description><atom:link href="https://willow.al/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © Willow et al </copyright><lastBuildDate>Thu, 23 Jul 2026 03:03:13 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>New clearnet domain</title><link>https://willow.al/posts/new-clearnet-domain.html</link><dc:creator>Willow et al</dc:creator><description>&lt;p&gt;So, besides &lt;a href="https://domainnamewire.com/2025/03/11/icann-moves-to-retire-soviet-era-su-country-domain-name/"&gt;ICANN wanting to phase out .su by 2030&lt;/a&gt;, it looks like &lt;a href="https://www.atakdomain.com/en/blog/ru-domain-registration-guide-esia-requirement-trustee-service-and-transfer"&gt;Russia is getting stricter with their domains&lt;/a&gt;. Basically since I'm not Russian, just a vaguely communist person who thinks a Soviet Union domain is pretty cool, it would cost me twice the price to keep willow.su, and I wouldn't be able to transfer it either. Fortunately, willow.al (as in Albania) is cheap and it gels as "willow at large". Unfortunately it looks like registration is handled manually lol. Also there's no WHOIS server, which I didn't even know is allowed :O&lt;/p&gt;
&lt;p&gt;I don't like this domain as much as my .su but I guess all good things must come to an end.&lt;/p&gt;</description><guid>https://willow.al/posts/new-clearnet-domain.html</guid><pubDate>Thu, 23 Jul 2026 02:54:14 GMT</pubDate></item><item><title>Username systems, ranked</title><link>https://willow.al/posts/username-systems-ranked.html</link><dc:creator>Willow et al</dc:creator><description>&lt;p&gt;When designing a platform with user-facing/public profiles, the way you go about handling usernames is important. Here I look at various systems for that.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;

&lt;h2&gt;Awful: un-namespaced usernames&lt;/h2&gt;
&lt;p&gt;This is what most sites use, including Discord and Twitter. Your username has to be a unique entry in a singular giant pool of usernames. These suck because there's a limited pool of usernames and so it's likely that your idea is already taken, leaving you to either choose a username you'd less prefer, or add punctuation to vary it. Discord actually gets a dishonorable mention here, because they &lt;em&gt;used to&lt;/em&gt; use discriminators and then moved to this inferior username system.&lt;/p&gt;
&lt;h2&gt;Decent: Usernames with discriminators&lt;/h2&gt;
&lt;p&gt;Blizzard does this, and Discord originally took a page from their book. This is where you can pick whatever username you want, and the system adds numbers to the end of it to help prevent your username from being taken. For example, my Signal username is Willow.1312. This lets me have Willow even though that's a pretty common name. From what I've heard, Blizzard even adds digits if the base 10,000 are taken. And Signal puts between 2 and 9 digits after a username, which should make it extremely unlikely whatever username you want is taken. This approach is good for silos, ie platforms that have your data locked in to one server.&lt;/p&gt;
&lt;h2&gt;Good: namespaced usernames&lt;/h2&gt;
&lt;p&gt;This is what Bluesky and the fediverse do. In Bluesky, usernames are just domain names! That means the entire breadth of the DNS can be used for a username. So mine is @willow.su, but if I didn't have my own domain, I could use someone else's or a subdomain of the standard .bsky.social domain. This is just a DNS entry that refers to my ATProto DID, and my actual profile could be hosted anywhere (although Bluesky is basically a silo at the moment). It's not exactly the same on fedi, where instead of an arbitrary domain name, the domain name identifies the server, as in @Willow@translunar.academy. Here, translunar.academy is the server that hosts my profile.&lt;/p&gt;
&lt;p&gt;It's less common for people to share their domain names than people opening their fedi instance registration, so I still prefer how fedi does it.&lt;/p&gt;
&lt;p&gt;Unfortunately, though, you can only use ASCII characters in these usernames. Discord's old username system didn't have this limitation. I hope someday fedi and Bluesky won't either, using IDN.&lt;/p&gt;</description><guid>https://willow.al/posts/username-systems-ranked.html</guid><pubDate>Thu, 18 Jun 2026 05:42:21 GMT</pubDate></item><item><title>A Case for Proprietary Software</title><link>https://willow.al/posts/a-case-for-proprietary-software.html</link><dc:creator>Willow et al</dc:creator><description>&lt;p&gt;I am a free software advocate, but I have limits. I can think of three reasons not to publish my own code or not to always use "free" licenses.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;

&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; This mostly only applies to server-side code, as that's most of what I've written. I don't have a strong opinion about this when it comes to compiled code, as I have no experience with it.&lt;/p&gt;
&lt;h2&gt;1. Opsec&lt;/h2&gt;
&lt;p&gt;Publishing your code can be a huge opsec risk. Maybe you have commits under an old handle. Maybe you have an oddly unique code style. Maybe you use an obscure programming language. Maybe you want to publish anonymously (via Tor or I2P). Or maybe you have a "contact me" page on your blog that you want to not publish the history of (&lt;em&gt;ahem&lt;/em&gt;). Sometimes you can get away with publishing an archive of the code without the VCS (e.g. git) history, but other times merely publishing any amount of the code would be enough to dox you. This is especially true of server-side code, where any kind of code could have generated that same HTML or JSON response.&lt;/p&gt;
&lt;p&gt;This doesn't just apply to you. If you release your code under the AGPLv3, everyone running your code will have to show their work too, meaning their opsec could be at risk too. For this reason, I used a permissive license for my upcoming comments system replacement, &lt;a href="https://codeberg.org/Willow-et-al/dsc#license"&gt;dsc&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;2. Scraping&lt;/h2&gt;
&lt;p&gt;Scrapers are often highly dependent on the markup of the site they're scraping. Publishing your scraping code accelerates the cat and mouse game you're playing with the site you're scraping, making it harder to accomplish your goals with the software in the first place.&lt;/p&gt;
&lt;h2&gt;3. Disagreements about what licenses are free&lt;/h2&gt;
&lt;p&gt;I like the &lt;a href="https://www.mongodb.com/legal/licensing/server-side-public-license"&gt;SSPL&lt;/a&gt;. I don't really plan to use it for my own code, as I find that the AGPLv3 is enough, but I'm not gonna fault anyone for using it. Why? I think it's not unreasonable to show your work for &lt;em&gt;everything&lt;/em&gt; needed to run the software, including backup scripts. It might violate the OSI, sure, but I don't really care about the OSI anyway :) I still think it's an open source / free software license. Copy far left is cool, when it doesn't fall under the previous two reasons.&lt;/p&gt;</description><guid>https://willow.al/posts/a-case-for-proprietary-software.html</guid><pubDate>Wed, 27 May 2026 02:21:51 GMT</pubDate></item><item><title>Types of post link trackers and how to avoid them</title><link>https://willow.al/posts/link-trackers.html</link><dc:creator>Willow et al</dc:creator><description>&lt;p&gt;Sometimes when you share a link to a video, post, or photo, the link includes tracking details that reveal a shocking amount of data to the platform owner when your recipient opens the link, or even just when you share it, depending on where you share it. I came up with two different types of link trackers, and how to avoid them (usually). We'll look at those, and then look at &lt;em&gt;what&lt;/em&gt; they reveal, &lt;em&gt;to whom&lt;/em&gt;, and &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;

&lt;h2&gt;Untracked links&lt;/h2&gt;
&lt;p&gt;"Untracked" links are the same for everyone. They just refer to the content itself, with no identifying details about the sender. Some examples of untracked links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://youtu.be/Ps-8QspaBug&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://www.tiktok.com/@ad_em_up/video/7623830159128333599&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://www.instagram.com/p/DXP8AYND-6b/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ID of the content (&lt;code&gt;Ps-8Q...&lt;/code&gt;, &lt;code&gt;762383...&lt;/code&gt;, &lt;code&gt;DXP...&lt;/code&gt;) is the same for everyone, and it's harder for Google/TikTok/Meta (in this case) to track you or your recipient. This is what you want when sharing a link to a friend.&lt;/p&gt;
&lt;h2&gt;Opaque trackers&lt;/h2&gt;
&lt;p&gt;"Opaque" trackers, such as &lt;code&gt;https://www.facebook.com/share/v/1AF.../&lt;/code&gt; (link censored to protect the anonymity of my mom), just have one parameter that uniquely identifies the content, but it &lt;em&gt;also&lt;/em&gt; identifies when and who shared the video. This is kind of a nightmare to handle because you have to identify yourself in order to unmask the link.&lt;/p&gt;
&lt;h2&gt;Transparent trackers&lt;/h2&gt;
&lt;p&gt;Here's an example of a link with a "transparent tracker": &lt;code&gt;https://www.instagram.com/p/DXP8AYND-6b/?utm_source=ig_web_copy_link&amp;amp;igsh=NTc...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can see the static post ID (&lt;code&gt;DXP8...&lt;/code&gt;) as well as an ugly link tracker, &lt;code&gt;utm_source&lt;/code&gt;, but more importantly &lt;code&gt;igsh=Ntc..&lt;/code&gt;. Fun fact, this parameter used to be called &lt;code&gt;igshid&lt;/code&gt;, which they probably shortened because it was too immature lmao. Say it a few times fast sometime though.&lt;/p&gt;
&lt;p&gt;Another example is &lt;code&gt;https://youtu.be/Ps-8QspaBug?si=dsj...&lt;/code&gt; The &lt;code&gt;si&lt;/code&gt; probably stands for "share ID" and is another example of a transparent link tracker.&lt;/p&gt;
&lt;h2&gt;What they reveal (in theory)&lt;/h2&gt;
&lt;p&gt;Platform owners can glean a &lt;em&gt;lot&lt;/em&gt; of data from people that share links from their site. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Who shared it&lt;/li&gt;
&lt;li&gt;Who they shared it to (be it via IP address or worse, if the recipient is signed in to the platform, what user account opened it)&lt;/li&gt;
&lt;li&gt;When they shared it / when it was opened&lt;/li&gt;
&lt;li&gt;What kind of device they shared it from and what kind of device it was opened on&lt;/li&gt;
&lt;li&gt;What platform it was shared on, if that platform does link embedding&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Link embed tracking&lt;/h3&gt;
&lt;p&gt;When you share a link on Discord, Twitter, or Signal, the link is fetched in order to extract a link preview, like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A link preview on Signal" src="https://willow.al/images/link-trackers/signal-embed.png"&gt;&lt;/p&gt;
&lt;p&gt;So now YouTube knows (in theory) that the video was shared on Signal. This is because Signal sends a unique User-Agent string to every site it fetches that identifies itself as a Signal client.&lt;/p&gt;
&lt;p&gt;Signal is actually a little worse about this because it uses &lt;em&gt;your&lt;/em&gt; IP address to fetch the embed, rather than some centralized proxy like it used to do. (That proxy was getting blocked.) Discord etc fetch the link using their centralized servers, but Google (in this case) still knows the link was shared on that platform.&lt;/p&gt;
&lt;h2&gt;How to avoid transparent trackers&lt;/h2&gt;
&lt;p&gt;Identify the component of the URL that stays the same for everyone. This is usually the first part of the URL, like the &lt;code&gt;Ps-8QspaBug&lt;/code&gt; in &lt;code&gt;https://youtu.be/Ps-8QspaBug?si=dsj...&lt;/code&gt;. Then remove the rest. Or try Firefox's "copy clean link" context menu item, although this is not foolproof.&lt;/p&gt;
&lt;p&gt;You should also enable a filter list in your ad blocker. AdGuard includes a &lt;a href="https://adguard.com/en/blog/adguard-url-tracking-filter.html"&gt;URL link tracking filter list&lt;/a&gt;, and so does uBlock Origin.&lt;/p&gt;
&lt;h2&gt;How to avoid opaque trackers&lt;/h2&gt;
&lt;p&gt;This is a little harder, and not always even possible. The best way, though, is to fetch the opaque link in a web browser, and see if it redirects to a transparent link. This at least works on TikTok, but I've also had some grief trying this technique on other sites, where I would either not get a new link, or it would try to get me to sign in constantly.&lt;/p&gt;</description><guid>https://willow.al/posts/link-trackers.html</guid><pubDate>Sat, 18 Apr 2026 04:09:09 GMT</pubDate></item><item><title>This is not a 24-hour clock</title><link>https://willow.al/posts/24-hour-clocks.html</link><dc:creator>Willow et al</dc:creator><description>&lt;p&gt;A 24-hour clock should cycle every 24 hours. Seems obvious right? But in a lot of apps, we get something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The 24-hour time picker in Google Calendar, showing 23:00 at the same position as 1:00 but in a different ring." src="https://willow.al/images/24h/google-24-hour-time-picker.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;This is basically two 12 hour clocks jammed together.
It forces you to think in lowly 12-hour terms rather than thinking about what part of the entire day cycle you need.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;

&lt;p&gt;It gets worse too:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The &amp;quot;orbit&amp;quot; clock in the Kvaesitso launcher, which is essentially just a 12 hour clock but with 24-hour text" src="https://willow.al/images/24h/kvaesitso-orbit-clock.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;This is Kvaesitso's "orbit" clock when you have the system set to 24h. 
It's basically just a 12 hour clock with a 24 hour face. The bigger planet still has a 12 hour orbit but it displays 0-23 instead of 12-12.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;should&lt;/em&gt; a 24 hour clock look like? Behold, one of the few things OnePlus did right in their buggy-ass OS:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The 24-hour clock in OnePlus's built-in Clock app" src="https://willow.al/images/24h/oneplus-alarm.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;0 is at the top, 12 is at the bottom, and it cycles once a day. Glorious.&lt;/p&gt;</description><guid>https://willow.al/posts/24-hour-clocks.html</guid><pubDate>Fri, 17 Apr 2026 05:40:59 GMT</pubDate></item><item><title>Hello, world!</title><link>https://willow.al/posts/hello-world.html</link><dc:creator>Willow et al</dc:creator><description>&lt;h2&gt;The site&lt;/h2&gt;
&lt;p&gt;In case you missed the footer, this is using &lt;a href="https://getnikola.com/"&gt;Nikola&lt;/a&gt;.
I wanted something lightweight and fast, so I was gonna go with &lt;a href="https://gohugo.io"&gt;Hugo&lt;/a&gt;, but I find Go's &lt;code&gt;text/template&lt;/code&gt; rather annoying to work with.
So I tried out &lt;a href="https://getpelican.com/"&gt;Pelican&lt;/a&gt; briefly, but apparently it doesn't do incremental compilation very well, and that is important to me.
Next I looked at Nikola and I quite like it!
It does support incremental compilation (although it's kinda slow to start up, so that may not pay off for a while) and it uses &lt;a href="https://jinja.palletsprojects.com/en/stable/"&gt;Jinja&lt;/a&gt; which I quite adore &amp;lt;3&lt;/p&gt;
&lt;h2&gt;The comments&lt;/h2&gt;
&lt;p&gt;Getting comments on here was quite a journey.
I wanted something that federated over ActivityPub, so I first tried &lt;a href="https://pinka.dev"&gt;Pinka&lt;/a&gt; but I couldn't get it to federate properly.
So then I tried &lt;a href="https://blog.leahdevs.xyz/p/federated-blog-comments/"&gt;Leah's Mastodon-API fetching script&lt;/a&gt; along with &lt;a href="https://gotosocial.org/"&gt;GoToSocial&lt;/a&gt; and a read-only API key.
Turns out there's a bug in that script which doesn't allow top level comments from other servers.
At this point I was running out of options, so I ended up just going with &lt;a href="https://isso-comments.de"&gt;Isso&lt;/a&gt;, which is an old Python project that just does
local comments and nothing else. I really wanted federation though, but I figure this is even lower friction because it doesn't require an account.&lt;/p&gt;</description><guid>https://willow.al/posts/hello-world.html</guid><pubDate>Thu, 16 Apr 2026 06:27:25 GMT</pubDate></item></channel></rss>