Latest Posts (20 found)
Unsung Today

“Traditionally, fonts were just shapes.”

Should you ever be worried that displaying just one glyph could take almost 2 seconds and slow down your website by as much? Naw, of course not. This wasn’t a problem already in the 1980s and, in the lord’s year 2026, computers are pretty good at rendering a letter or a symbol at a moment’s notice. Ha. I was just messing with you. Of course you should always be worried about fonts. All the time. Typography is beautiful, but fonts are brutal. They will constantly put you to the test, they will find ways to get out of alignment faster than a Zastava Yugo , and they will teach you about corner cases in places you didn’t even realize had edges. Fonts will break your heart like it’s the month before the prom again, and again, and again. Or, in Allen Pike’s case, break a heart somewhat literally. Pike wrote a nice quick story of the complexity of what needed to happen to show the heart emoji, and how under a very specific set of conditions – a certain browser, a certain emoji font, a certain emoji within that font – this led to an extreme slowdown. What’s really interesting is that in order to fix it, Apple can either improve Safari or the font itself, and at the moment of writing, it wasn’t clear what was the right thing to do. (Oh, yeah. Fonts don’t just have bugs . Fonts have many kinds of bugs.) Another interesting in-between-the-lines thing is that Apple’s emoji are perhaps the only survivor of the original skeuomorphic pre-iOS 7 era. Even today’s emoji party like 2008 never ended – still glossy, still textured, still bitmapped. I’m curious whether somewhere deep inside Apple, there exist exploratory designs for flat, vector versions of emoji that never saw the light of day. #bugs #skeuomorphism #typography

0 views
Unsung Today

“Who thinks about a screwdriver?”

I found this 9-minute video from Rex Krueger about screwdriver handle design really interesting in the context of my post about Photoshop’s dialogs . = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/who-thinks-about-a-screwdriver/yt1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/who-thinks-about-a-screwdriver/yt1.1600w.avif" type="image/avif"> Screwdriver handles evolved over the decades in response to user needs and usage patterns, with a few clever affordances: some for everyone, some for specific use cases that might not be obvious. I think by now all the basic onscreen UI elements – input fields, pop-up menus , checkboxes, buttons, top menus, sliders, and so on – have similar richness, as do all the core input devices like a keyboard, a mouse, a trackpad, or a touch screen. That doesn’t mean that everything is set in stone, that no changes are possible, and that stuff that fell out of favour can ever be taken away – after all, computer usage, input devices, and conventions are evolving much faster than screws at this point – but that one has to be aware of the history so that the changes are intentional, not accidental. A few select comments from under the video that I found interesting: The Craftsman handles are also different colors for Phillips and slotted screwdrivers. The fluted handle was patented. So anyone else wanting to make a screwdriver would have to pay the patent holder. So they tried alternatives to make more money. That is the real reason until the patent expired. Plus if they invented a “better” way and held the patent, others would have to pay THEM. The Swedish word for screwdriver is “skruvmejsel” with literally translates as “screw chisel.” #details #real world #youtube

0 views

Building With Intent

I'm working on a new application called TinyFeeds, it's a native RSS feed reader. Sure there's thousands of those, but this one is mine and as such I'm being extremely intentional about how it's built. I believe constraints breed innovation, and as such I've outlined a few constraints for myself in this project. First off, the file size has to be 5MB or under for the shipped binary. This is inspired by Matt's Fits on a Floppy manifesto. I'm also inspired by the Palm Pilot apps I use on a daily basis, many of which are under 5MB. Maintaining a small file size makes you second guess the need for features, libraries, graphics, etc. In a world where Google Chrome secretly downloads an extra 4GB for a local LLM , I feel like small apps are sorely needed. Second, the application is to be built in Rust and Iced . This constraint has forced me to finally dig in and learn Rust. The result is a fast, native application that has a high level of stability thanks to the tools used to build it. Finally, no LLM generated code is to be used. This again forces me to actually learn the language, focus on code structure, and de-scope feature bloat. It also makes me feel proud of what I've built, something I never feel when using LLMs. So how's it going? Great so far! As I mentioned, TinyFeeds is built intentionally for me and how I enjoy consuming RSS. With any feed reader I always filter by unread posts from today. I don't use folders, tags, bookmarks, etc. So that's exactly what TinyFeeds does: The UI has been designed to facilitate this. It's incredibly simple, but the layout is intentional. TinyFeeds won't be for everyone, heck it might only be something I want, but that's the point! I find it a joy to use even in it's early state. While it isn't ready yet, you can early trial it if you so desire by cloning from Codeberg and building it yourself ( ). The app currently clocks in at 4MB when built with the build script! After TinyFeeds, I plan to build similar apps focused on small size, performance and minimal feature sets. All hand coded. Possibly inspired by Palm OS apps :-P Reads your feeds from a simple .txt file Shows new stories from today Only shows a single story at a time Remembers what stories you've viewed so they aren't shown again

0 views

Fragments: May 5

Over the last couple of months Rahul Garg published a series of posts here on how to reduce the friction in AI-assisted programming . To make it easier to put these ideas into practice he’s now built an open-source framework to operationalize these patterns . AI coding assistants jump straight to code, silently make design decisions, forget constraints mid-conversation, and produce output nobody reviewed against real engineering standards. Lattice fixes this with composable skills in three tiers – atoms, molecules, refiners – that embed battle-tested engineering disciplines (Clean Architecture, DDD, design-first methodology, secure coding, and more), plus a living context layer (the .lattice/ folder) that accumulates your project’s standards, decisions, and review insights. The system gets smarter with use – after a few feature cycles, atoms aren’t applying generic rules, they’re applying your rules, informed by your history. It can be installed as a Claude Code plugin or downloaded for use with any AI tool. ❄                ❄                ❄                ❄                ❄ This is also a good point to note that the article by my colleagues Wei Zhang and Jessie Jie Xia on Structured-Prompt-Driven Development (SPDD) has generated an enormous amount of traffic, and quite a few questions. They have thus added a Q&A section to the article that answers a dozen of them. ❄                ❄                ❄                ❄                ❄ Jessica Kerr (Jessitron) posted a merry tidbit of building a tool to work with conversation logs. She observes the double feedback loop involved. There are (at least) two feedback loops running here. One is the development loop, with Claude doing what I ask and then me checking whether that is indeed what I want.[…] Then there’s a meta-level feedback loop, the “is this working?” check when I feel resistance. Frustration, tedium, annoyance–these feelings are a signal to me that maybe this work could be easier. The double loop here is both changing the thing we are building but also changing the thing we are using to build the thing we are building. As developers using software to build software, we have potential to mold our own work environment. With AI making software change superfast, changing our program to make debugging easier pays off immediately. Also, this is fun! Indeed it is, and makes me think that agents are allowing us to (re)discover one of the Great Lost Joys of software development - that of molding my development environment to exactly fit the problem and my personal tastes. A while ago I wrote about this under the name Internal Reprogramability . It was a central feature of the Smalltalk and Lisp communities but was mostly lost as we got complex and polished IDEs (although the unix command line gives a hint of its appeal). ❄                ❄                ❄                ❄                ❄ Ashley MacIsaac is a musician from Cape Breton, who plays folk-influenced music (I have a couple of his albums in my collection). Google generated an AI overview that asserted that had been convicted of crimes, including sexual assault and was on the national sex-offender registry. These were completely false, confusing him with another man with the same name. MacIsaac is suing Google for defamation : “This was not a search engine just scanning through things and giving somebody else’s story […] It was published by them. And to me, that is defamation. The guardrails were not there to prevent Google AI from publishing that content.” MacIsaac’s point is that Google must take responsibility for what a tool it controls publishes. MacIsaac suffered genuine harm here, not just to his reputation, but he also had a concert canceled and the claims affect his performing. “I felt that tangible fear from something that was published by a media company,” he said in an interview with The Canadian Press. “I feared for my own safety going on stage because of what I was labelled as. And I don’t know how long this will follow me.” Too often tech companies try to dodge the consequences of their actions. There are genuine issues about the difficulties of monitoring what’s published at scale, but that’s a responsibility that they should face up to. ❄                ❄                ❄                ❄                ❄ Stephen O’Grady (RedMonk) takes a serious look at how much the big tech companies are spending on AI build-outs . The sums involved are staggering, not just in absolute terms (over $100 Billion), but also compared to the revenues of the companies involved. Firms like Amazon, Alphabet, and Microsoft are spending over 50% of their revenues (not profits). Meta and Oracle hit or pass 75% of revenues. That level of investment would have been unthinkable a decade ago. Today, the chart suggests it’s table stakes There is a notable exception: Apple. Here they are clearly Thinking Different, eyeballing the chart they seem closer to 10% of revenues. ❄                ❄                ❄                ❄                ❄ Most folks I talk to about agentic programming are using models in the cloud: Claude, Codex, and the like. Everyone agrees these are the most powerful models, the ones that triggered the November Inflection . But do we need to use the Most Powerful Models, particularly when we have to ship data to them, and pay handsomely for the privilege? Willem van den Ende considers an alternative, that local models are Good Enough. Assumptions - We are all figuring this out. - Quality of a harness (coding agent + “skills” + extensions) can matter as least as much as the model - Running open models and an open coding agent + custom extensions takes time, but pays off in understanding and a stable base where engineering effort compounds - Open, local, models have (for me) crossed the point where they are good enough for daily work with a coding agent. The post describes in detail his setup for local model work. It includes sandboxing with Nono, which is something to consider even if using a Cloud model - such powerful tools need a Zero Trust Architecture . ❄                ❄                ❄                ❄                ❄ In case you haven’t noticed, those last two fragments resonate. Apple isn’t playing the cloud AI model game, they are saving a huge amount of money, and if local models end up being the future, they’ll be looking rather wise. Van den Ende’s post led me to a podcast by Nate B Jones that argues that Apple is replaying a fifty-year old strategy here. All those years ago anyone who used a computer bought time on a mainframe, the Apple II put far less capable compute into the home and small office. From there came spreadsheets, desktop publishing, and the modern home computer - things that weren’t possible using mainframes. He sees the rise of John Ternus as CEO isn’t merely a switch to a known insider successor - but a bet that the future of AI is sophisticated hardware in the home, office, and pocket. If Open Source models are Good Enough, then why spend money sending tokens - containing your sensitive data - to the AI megacorps? ❄                ❄                ❄                ❄                ❄ Talking of five decades in the past, it was in 1974 that Fred Brooks opened one of the most influential books in our profession with these paragraphs: No scene from prehistory is quite so vivid as that of the mortal struggles of great beasts in the tar pits. In the mind’s eye one sees dinosaurs, mammoths, and sabertoothed tigers struggling against the grip of the tar. The fiercer the struggle, the more entangling the tar, and no beast is so strong or so skillful but that he ultimately sinks. Large-system programming has over the past decade been such a tar pit, and many great and powerful beasts have thrashed violently in it. Most have emerged with running systems — few have met goals, schedules, and budgets. Large and small, massive or wiry, team after team has become entangled in the tar. No one thing seems to cause the difficulty — any particular paw can be pulled away. But the accumulation of simultaneous and interacting factors brings slower and slower motion. Everyone seems to have been surprised by the stickiness of the problem, and it is hard to discern the nature of it. But we must try to understand it if we are to solve it. With the title of his recent post Kent Beck summons up that imagery as the Genie Tarpit . After explaining why skilled software development is about building both features and futures, he observes that these AI tools aren’t doing a good job of producing software with the kind of internal quality that is needed for a good future. Here’s what I’ve observed — genies naturally live down & to the left of muddling. The “plausible deniability” task orientation of the genie leaves it claiming success even though the code doesn’t work at all. And complexity piles on complexity until even the genie can’t pretend to make progress any more. It’s still an open question whether, or to what extent, internal quality matters in the age of agentic programming. One view is, as Laura Tacho puts it, “The Venn Diagram of Developer Experience and Agent Experience is a circle”. Well organized elements, with good naming, help The Genie understand code, so are important if we can continue to go beyond small disposable systems. The other view is that such internal quality doesn’t matter, that the galaxy brain of LLMs will make sense of the biggest bowls of spaghetti. Maybe not now, but after a couple more inflections. That’s the fundamental question. Can The Genie evade the tar pit, or will it struggle fruitlessly against the tar’s sticky grip?

0 views

Bliki: Mythical Man Month

In the early 1960s, Fred Brooks managed the development of IBM's System/360 computer systems. After it was done he penned his thoughts in the book The Mythical Man-Month which became one of the most influential books on software development after its publication in 1975. Reading it in 2026, we'll find some of it outdated, but it also retains many lessons that are still relevant today. The book contains Brooks's law: “Adding manpower to a late software project makes it later.” The issue here is communication, as the number of people grows, the number of communication paths between those people grows exponentially. Unless these paths are skillfully designed, then work quickly falls apart. Perhaps my most enduring lesson from this book is the importance of conceptual integrity I will contend that conceptual integrity is the most important consideration in system design. It is better to have a system omit certain anomalous features and improvements, but to reflect one set of design ideas, than to have one that contains many good but independent and uncoordinated ideas. He argues that conceptual integrity comes from both simplicity and straightforwardness - the latter being how easily we can compose elements. This point of view has been a strong influence upon my career, the pursuit of conceptual integrity underpins much of my work. The anniversary edition of this book is the one to get, because it also includes his even-more influential 1986 essay “No Silver Bullet”.

0 views
Stratechery Yesterday

Amazon’s Durability

Listen to this post : When it comes to the AI soap opera — there is news every day, and the company on top and the bottom seems to shift by the quarter if not the month — the news that I find most intriguing and instructive this week is about physical goods and logistics. From Bloomberg : Amazon.com Inc. unveiled a suite of logistics services that will let businesses buy its existing freight and distribution offerings as a package, sending shares of rival delivery companies such as FedEx Corp. and United Parcel Service Inc. lower. The world’s largest online retailer on Monday announced Amazon Supply Chain Services (ASCS), offering other companies access to its “full portfolio” of supply-chain and distribution offerings. The service largely consolidates a package of existing products — air and ocean freight, trucking and last-mile delivery — into a new suite it says companies like Procter & Gamble Co. and 3M Co. are already using. This is a very satisfying announcement for Stratechery, given it’s the culmination of a prediction I made a decade ago in The Amazon Tax . Amazon at that point had two primary businesses — Amazon.com and AWS — and I made the case in that Article that they were actually very similar: in both cases Amazon built “primitives” that had Amazon itself as their first, best customer, justifying and driving initial development, but in both cases the ultimate play was to sell those primitives to other companies. It was already clear at the time that logistics would follow the same path: It seems increasingly clear that Amazon intends to repeat the model when it comes to logistics: after experimenting with six planes last year the company recently leased 20 more to flesh out its private logistics network; this is on top of registering its China subsidiary as an ocean freight forwarder… So how might this play out? Well, start with the fact that Amazon itself would be this logistics network’s first-and-best customer, just as was the case with AWS. This justifies the massive expenditure necessary to build out a logistics network that competes with UPS, FedEx, et al, and most outlets are framing these moves as a way for Amazon to rein in shipping costs and improve reliability, especially around the holidays. However, I think it is a mistake to think that Amazon will stop there: just as they have with AWS and e-commerce distribution I expect the company to offer its logistics network to third parties, which will increase the returns to scale, and, by extension, deepen Amazon’s eventual moat. Now, ten years later, we are here, with the official unveiling of Amazon Supply Chain Services , and I think the time frame is an important one: Amazon, more than any other company, actually operates with decade-long timeframes, consistently making real-world investments at massive scale that (1) convert their marginal costs into capital costs and (2) gain leverage on those capital costs by selling them to other businesses. This is, by the way, still a story about AI. Three years ago SemiAnalysis wrote an Article entitled Amazon’s Cloud Crisis: How AWS Will Lose The Future Of Computing , and I found it very compelling. First, though, some history (much of which is covered in SemiAnalysis’ article). Amazon not only invented cloud computing, but also realized it would be a commodity market. While most people in tech think about building sustainable differentiation that allows you to charge higher prices, thus producing profit, commodity markets work differently: there, sustainable profits come from having structurally cheaper costs. Amazon developed exactly that, first through having the largest scale — giving the company both buying power and also the most leverage on their development costs — and second through genuine innovation. AWS built a specialized system called Nitro, built on their own chips, that offloaded server management, including network management, storage management, hypervisor management, etc. from the expensive Intel and AMD servers that the company sold access to; this let Amazon run that many more virtual machines on a single server, significantly increasing utilization, i.e. delivering a structural cost advantage. Amazon doubled down on their custom chip efforts with Graviton, their ARM processors. Graviton chips, particularly the first few generations, were inferior to Intel or AMD chips, but that didn’t mean they were useless. By that time AWS had expanded from simply being an Infrastructure-as-a-Service (IaaS) provider to being a Platform-as-a-Service (PaaS) provider as well. IaaS means you provide raw compute, storage, etc., on which customers can run things like operating systems or databases; PaaS means you provide that basic functionality as a service. Amazon Relational Database Service (RDS), for example, is a fully managed database that customers can access via a set of APIs without having to worry about actually managing the full database themselves, worrying about scaling, duplication, etc. This, by extension, means that customers don’t need to know and don’t need to care about the compute infrastructure that undergirds services like RDS — which has long been Graviton! PaaS lets Amazon double-dip in terms of profitability: first, AWS could sell PaaS products at a higher margin than IaaS products, and second, the company could leverage its own cheaper silicon to serve those products, reducing their costs. Over time Graviton has become more competitive in performance — while still being cheaper — giving Amazon a lower-cost compute instance to sell to end users, but even without 3rd-party take-up the investment in building its own silicon has paid off over time. Fast forward to AI, and SemiAnalysis’ concern was that all of these optimizations left AWS ill-prepared for AI. One big problem was networking: Rather than implement the best networking from Nvidia and/or Broadcom, Amazon is using its own Nitro and Elastic Fabric Adaptor (EFA) networking. This works well for many workloads, plus it delivers a cost, performance, and security advantage. There are business, cultural, and security reasons why Amazon will not implement other networking. The cultural one is important. Nitro and networking SoC’s generally have been Amazon’s biggest cost advantage for years. It’s ingrained into their DNA. Even EFA delivers on this too, but they don’t see how new workloads are evolving and that a new tier is needed due to the lack of foresight in their internal workload and infrastructure teams. Amazon is making a deliberate choice of not adopting that we believe will bite them in the future. Another was Amazon’s insistence on building its own chips, which were not only inferior to the best Nvidia chips in terms of performance, but might also lead to them getting fewer Nvidia chips going forward: At least some other clouds will implement out-of-node NVLink. That’s where the discussion of prioritization now comes in. AI GPUs face tremendous shortages, for at least a full year. This is one of the most pivotal times for AI, and it may mark the haves and the have-nots. Nvidia is a complete monopoly right now. Why would Nvidia prioritize Amazon for these GPUs, when they know Amazon will move to their in-house chips as quickly as they can, for as many compute workloads as they can? Why would Nvidia ship tons of GPUs to the cloud that is not using any of their networking, thereby reducing their share of wallet? Instead, Nvidia prioritizes the me-too clouds. Amazon does get meaningful volume, but nowhere close to where demand is. Amazon’s H100 GPU shipments relative to public cloud shipments is a significantly lower than their share of the public cloud. Those other clouds also can’t satisfy demand, but they get a bigger percentage of the GPUs they ask Nvidia for, and as such, firms looking for GPUs for training or inference will move to those clouds. Nvidia is the kingmaker right now, and they are capitalizing on it. They have to spread the balance of power out to prevent compute share from clustering towards Amazon. These concerns were well-founded in the 2023 time-period when that Article was written: that was a time when AI, thanks to ChatGPT, had hit the mainstream, but the largest share of compute still went to training. Training required all of the things that Amazon lacked, particularly the ability to network large numbers of Nvidia GPUs together into one coherent system. In such a system the most important capability was horizontal networking between chips, so that you could update weights during training, a step that needed to happen serially. It was absolutely the case that cloud providers like Microsoft or Oracle or the neoclouds, which implemented full Nvidia solutions, instead of the standalone HGX racks that AWS favored, were much better suited to training large language models. That is still the case, by the way. What has changed is that training is no longer the biggest AI compute market; inference is, thanks not only to increased AI adoption, but also because of fundamental changes in terms of how AI works. From an Update about Nvidia : Both the shift to inference and the shift in the nature of inference have been positives for AWS’ approach. The utilization point is an important one. Nvidia CEO Jensen Huang made his case for Nvidia chips over custom ASICs at length at GTC 2025 . Huang’s argument was that AI factories — to use his term — were ultimately constrained by power; that meant that the most important metric for profitability was not the cost of chips but rather tokens-per-watt. In other words, if you can’t increase watts, it’s worth spending more on chips to increase tokens on those watts. There are, however, three reasons why this argument may not hold, particularly for a company like Amazon. These points are moot, however, if you don’t have your own logic chip that is at least competitive, and here Amazon’s long-term outlook is paying off. Amazon bought Annapurna Labs, which makes their chips, in 2015, and launched their first AI-focused chip in 2019. No, it wasn’t very good, but critically, that was seven years ago: now Trainium 3 is decent and the trajectory is even better. AWS is positioned to have a sustainable cost advantage for inference going forward. Moreover, they are already replaying the Graviton playbook. Trainium chips help undergird Bedrock, its AI platform, which is to say that users are using Trainium chips even if they didn’t explicitly choose to do so. AWS CEO Matt Garman made this point explicitly in a Stratechery Interview : I think just with GPUs, by the way, you’re going to interact with a lot of these accelerator chips through abstractions. So the vast majority of customers don’t interact with GPUs either, except through maybe like in their laptop or something like that, for graphics. But when you’re talking to OpenAI, even if they’re running on GPUs, you’re not talking to the GPUs, if you’re talking to Claude, you’re through GPUs or Trainium or TPUs, you’re not talking to any of those chips, you’re talking to the interface. And the vast majority of inference out there is being done on one of a handful of models. And so whether it’s 5, 10, 20, 100, it’s not millions of people that are programming to those things directly, and that’s gonna be true going forward just because these systems are so complex, they’re very large. If you’re going to go train a model, not that many people have enough money to go train a model, not that many people have the expertise to actually manage it. They’re very complicated systems, and the OpenAI team is incredible in their ability to squeeze value out of a very large compute cluster. But not that many people have the team that can do that, independent of what the chip happens to be, and so I think that that’s going to be true for all accelerator chips, honestly. The frontier models are an important factor in this, and that is an angle that I didn’t see coming. Nvidia CEO Jensen Huang explained in a recent interview with Dwarkesh Patel why Nvidia didn’t invest in Anthropic early on: At the time, I didn’t deeply internalize how difficult it would be to build a foundation AI lab like OpenAI and Anthropic, and the fact that they needed huge investments from the supplier themselves. We just weren’t in a position to make the multi-billion dollar investment into Anthropic so that they could use our compute. But Google and AWS were. They put in huge investments in the beginning so that Anthropic, in return, used their compute. We just weren’t in a position to do that at the time. I would say my mistake is I didn’t deeply internalize that they really had no other options, that a VC would never put in $5-10 billion of investment into an AI lab with the hopes of it turning out to be Anthropic. So that was my miss. But even if I understood it, I don’t think we would’ve been in a position to do that at the time. But I’m not going to make that same mistake again. Amazon had both the money and the chips to invest into Anthropic precisely because they had built such a cash machine with AWS in the first place. That’s the thing with big investments in infrastructure: they take years to build, but the benefit of that investment compounds over time. Anthropic, meanwhile, thanks to those investments from Amazon and Google, can not only run across a variety of chips, but for a long time was the only frontier model available on all of the leading clouds, an important selling point for enterprises. Microsoft, in the end, needed to let go of Azure’s exclusive access to OpenAI’s API in part because that exclusivity was hurting the prospects of their mammoth stake in OpenAI. You can also make the case that Amazon is the best choice for frontier model access in a world of limited compute: Microsoft’s core business is software, which is to say that the company faces massive pressure to invest in their own AI capabilities, even at the cost of de-prioritizing cloud customers. That’s exactly what happened at Microsoft earlier this year , when the company missed Azure growth projections because they devoted more compute to their internal workloads. It was an understandable decision: cloud demand is eternal, but the risk from AI for existing software businesses is existential. This also applies to Google: the company’s core business is also digital, and while search has fended off the threat from chatbots that many expected, the fundamental challenge is still one to be managed, not extinguished. Amazon’s core businesses, meanwhile, are very much rooted in the physical world: selling and shipping physical goods, and building data centers. Both are amenable to Amazon devoting the majority of its chips to customers’ workloads. If this week marks the resolution of one of Amazon’s long bets, you can see the outline of future resolutions in present day announcements. One prominent example is Amazon Leo, the company’s satellite service that seems, at first glance, duplicative of SpaceX’s Starlink, which has the advantage of already existing at scale. Remember Amazon’s formula, however, which CEO Andy Jassy stated explicitly with regards to Leo on the company’s most recent earnings call : Today, if you ask what stops us from growing the business, we have to get the constellation into space. We have over 20 launches planned this year. We have over 30 launches planned in 2027. But I think the business has a chance to be a very large many billion-dollar revenue business. And I think it has some characteristics that are reminiscent of AWS in that it’s capital-intensive upfront where you’re committing a lot of capital and cash in the early years for assets that you get to leverage over a long period of time. And so I like the free cash flow and return on invested capital characteristics of that business in the medium to long term. The fact that it is extremely capital-intensive is not the only thing about Leo that makes it like AWS: a critical factor is that Amazon is the first-best customer to give the service scale, and here it’s worth going back to logistics. I noted above that Amazon delivery still has marginal costs, and that is because humans have to make the delivery. Amazon, however, has already pointed to the future, a full 13 years ago when the company first started talking publicly about drone delivery. It’s been a long slog, to be sure, but it’s increasingly plausible to imagine a future where delivery costs are a matter of depreciation on drone assets, and what would such a future require? How about reliable widespread satellite coverage for communicating with and guiding those drones? And, if Amazon doesn’t want to be dependent on Jensen Huang for chips, do you think they want to be dependent on Elon Musk for drone connectivity? Of course other businesses — like Apple — will be able to pay to use Amazon’s satellite infrastructure, just like they can now pay to use Amazon’s delivery service, or pay to use AWS, or pay to sell on Amazon.com. The world may change, in increasingly drastic ways, but Amazon’s approach, by virtue of its focus on long-term investments in the physical world, appears to be as sturdy as ever. More generally, I increasingly suspect that long-term vulnerability to AI — or, to put it more positively, long-term incentives to invest in AI — are very strongly correlated with the degree to which a company interacts with the physical world, and secondarily, the degree to which companies feel secure in their control of distribution: This is, in the end, another advantage to making the sort of long-term bets Amazon specializes in: the threats are so distant that you have plenty of time to make new investments that address any weaknesses that develop in the meantime — or, as is the case of AI, wait for the market to tilt in your favor. The first inflection point was the emergence of LLMs — call this the ChatGPT moment. In this first paradigm tokens were generated by GPUs and presented as the answer to a question. The second inflection point was the emergence of reasoning models — call this the o1 moment. In this paradigm there are a very large number of tokens that are generated to figure out the answer before the answer is actually generated; this was an exponential increase in the addressable market for tokens. The third inflection point was the emergence of functional agents — call this the Opus 4.5 moment. In this paradigm those reasoning models are not triggered by humans asking a question, but by an agent solving a problem. This increases the market in two directions: first, humans can run multiple agents, and secondly, agents can leverage reasoning models multiple times to accomplish a task. This isn’t just an exponential increase in the addressable market for tokens, it’s two exponential increases squared. First, while inference still requires significant memory, the requirement is significantly less than that required for training. It’s actually viable to store a model’s parameters in a single server; you don’t need to network together thousands of chips. Second, while reasoning and agentic workloads require significantly more tokens, and thus a massively larger KV cache, the increase is actually so large that even the most optimized Nvidia inference systems are being built with dedicated memory servers . This sort of architecture is much more compatible with Amazon’s networking approach than the thousands-of-chips-networked-together approach is. Third, agents are heavily CPU dependent, which has two important implications. First, fully utilizing accelerators is a function of having sufficient general compute; second, achieving maximum utilization of heterogeneous compute means unbundling CPUs and GPUs and routing workloads between resources, which is exactly the sort of disaggregated-resource abstraction that Amazon has been building with Nitro. First, if you have the money to buy that many Nvidia chips, you also have the money to spend on getting more power — which is exactly what AWS has been focused on. This very much fits AWS’ modus operandi, which is to invest more upstream (in this case in power) with the goal of spending less downstream (paying Nvidia huge margins for their chips). Second, in the long term, electricity is more of a commodity than logic is. That means it is a market where innovation and competition are more likely to break a bottleneck, which is another way to say that investing in one’s own silicon is the area most likely to deliver a return on investment. Third, the nature of inference workloads — particularly agentic ones — is such that perfect accelerator utilization is going to be a much harder problem to solve than when it comes to training. Apple and Amazon feel comfortable not having leading edge models, just access to them, because their business is rooted in the physical. Microsoft has invested heavily in data centers, but doesn’t own their own model, perhaps because they feel their control of distribution to enterprises will protect their core business (or because they had too much of a dependency on OpenAI). Google and Meta are investing at a similar scale to Amazon, and are also heavily invested in their own models. Both are Aggregators, which is to say they have to continually earn attention from consumers, given that competition is only a click away; having good AI is existential to them.

0 views
iDiallo Yesterday

AI didn't delete your database, you did

Last week, a tweet went viral showing a guy claiming that a Cursor/Claude agent deleted his company's production database . We watched from the sidelines as he tried to get a confession from the agent: "Why did you delete it when you were told never to perform this action?" Then he tried to parse the answer to either learn from his mistake or warn us about the dangers of AI agents. I have a question too: why do you have an API endpoint that deletes your entire production database? His post rambled on about false marketing in AI, bad customer support, and so on. What was missing was accountability. I'm not one to blindly defend AI, I always err on the side of caution. But I also know you can't blame a tool for your own mistakes. In 2010, I worked with a company that had a very manual deployment process. We used SVN for version control. To deploy, we had to copy trunk, the equivalent of the master branch, into a release folder labeled with a release date. Then we made a second copy of that release and called it "current." That way, pulling the current folder always gave you the latest release. One day, while deploying, I accidentally copied trunk twice. To fix it via the CLI, I edited my previous command to delete the duplicate. Then I continued the deployment without any issues... or so I thought. Turns out, I hadn't deleted the duplicate copy at all. I had edited the wrong command and deleted trunk instead. Later that day, another developer was confused when he couldn't find it. All hell broke loose. Managers scrambled, meetings were called. By the time the news reached my team, the lead developer had already run a command to revert the deletion. He checked the logs, saw that I was responsible, and my next task was to write a script to automate our deployment process so this kind of mistake couldn't happen again. Before the day was over, we had a more robust system in place. One that eventually grew into a full CI/CD pipeline. Automation helps eliminate the silly mistakes that come with manual, repetitive work. We could have easily gone around asking "Why didn't SVN prevent us from deleting trunk?" But the real problem was our manual process. Unlike machines, we can't repeat a task exactly the same way every single day. We are bound to slip up eventually. With AI generating large swaths of code, we get the illusion of that same security. But automation means doing the same thing the same way every time. AI is more like me copying and pasting branches, it's bound to make mistakes, and it's not equipped to explain why it did what it did. The terms we use, like "thinking" and "reasoning," may look like reflection from an intelligent agent. But these are marketing terms slapped on top of AI. In reality, the models are still just generating tokens. Now, back to the main problem this guy faced. Why does a public-facing API that can delete all your production databases even exist? If the AI hadn't called that endpoint, someone else eventually would have. It's like putting a self-destruct button on your car's dashboard. You have every reason not to press it, because you like your car and it takes you from point A to point B. But a motivated toddler who wiggles out of his car seat will hit that big red button the moment he sees it. You can't then interrogate the child about his reasoning. Mine would have answered simply: "I did it because I did it." I suspect a large part of this company's application was vibe-coded. The software architects used AI to spec the product from AI-generated descriptions provided by the product team. The developers used AI to write the code. The reviewers used AI to approve it. Now, when a bug appears, the only option is to interrogate yet another AI for answers, probably not even running on the same GPU that generated the original code. You can't blame the GPU! The simple solution is know what you're deploying to production. The more realistic one is, if you're going to use AI extensively, build a process where competent developers use it as a tool to augment their work, not a way to avoid accountability. And please, don't let your CEO or CTO write the code.

0 views
Unsung Yesterday

The land where time stood still

It’s hard to be in charge of continuity on a movie set. It would already be difficult under the best of circumstances: after all, you can’t freeze the sun in the sky, prevent hot drinks from going cold, cigarettes from extinguishing themselves, or entropy in general for doing all the stuff it loves doing. But on top of that, scenes are shot out of sequence, and movies are shot out of sequence. There are pick-ups if you’re lucky, and reshoots when you’re not. About the only time your job will be noticed is if you mess up: cue Super-man’s reverse CGI moustache, Josh Trank’s Fantastic Four wig situation, Commando’s damaged-then-pristine Porsche, and so on and so on. ( This 7-minute YouTube video is a great walkthrough from an expert .) = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-land-where-time-stood-still/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-land-where-time-stood-still/1.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-land-where-time-stood-still/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-land-where-time-stood-still/2.1600w.avif" type="image/avif"> Apple famously freezes time on their phones in all the promotional materials to be 9:41am. The specific moment they chose is a celebration of the first iPhone unveiling to be at around that time, but it also makes production easy – while people won’t mind that the time on the screen doesn’t match the current time, or even that it doesn’t seem to advance at a normal rate, they will definitely notice if you happened to splice two screenshots with different time side by side, just because you didn’t anticipate that splice as you were preparing them. So it’s easiest just to avoid this situation altogether. But what I didn’t realize until today as I was recording the previous post’s screengrab is that 9:41am is also enforced whenever you record your phone’s screen via QuickTime. It’s a peculiar feeling: Start recording, and the time on your phone jumps to 9:41. Yank the USB cord out, and it’s back to where it was: Oh yeah, the date changes too, for the same reason – to January 9, 2007. In a time-honored Apple tradition, I can’t decide whether I’m annoyed at it (there seems to be no option to turn it off), or admire it.

0 views
Unsung Yesterday

The vision of persistence

I want to show you something glorious. This is Bear , the note taking app: There are desktop apps that get flustered if you ⌘+Tab away and back, misplacing focus or closing a dialog box inside. There are iOS apps that fully reset themselves whenever they get swapped out of memory and have to be reloaded. But Bear, right here, remembers which note you were on, and exactly where you were in that note, even between phone reboots . Software is transient and malleable, and one of the hard parts is knowing when that’s beneficial and when detrimental. In real life, you can leave a notebook on your desk, open on a certain page, leave a pen pointing to a specific word – and then depart for a two-month trip to Europe. You will find your notebook exactly how you left it. Why shouldn’t software behave this way? Also, another thought: This is very likely not something users will complain about when broken, or suggest when absent, even if you go out of your way to open yourself for feedback. Just swapping an app out of memory is hard to understand and “repro” (in engineering parlance). There’s a certain design mindset and taste necessary to notice and care, and a certain vision to carry it through. The lack of direct user feedback doesn’t mean it’s not worth doing. It just means that there are some things that designers and only designers will know how to properly weigh, describe, and prioritize. If you have a few design-minded users that actually send you feedback like this – treasure them. But most likely this will have to come from “within the house.” To me, it’s clear that within Shiny Frog (the makers of Bear), there are people who care about this kind of stuff, and leadership that trusts them. Kudos. #above and beyond #culture #flow #research

0 views
ava's blog Yesterday

📌 married for a year

Celebrated our first wedding anniversary by hanging out with some friends who were here for my wife's birthday the previous day, then visited a botanical garden, walked through beautiful parts of a city, and had a sushi dinner date. Also drank some flower tea we got as a gift when we got married, and soon, we will attend the jewelry making workshop we also got :) Reply via email Published 04 May, 2026

0 views
<antirez> Yesterday

Redis array type: short story of a long development

I started working on the new Array data type for Redis in the first days of January. The PR landed the repository only now, so this code was cooked for four months. I worked at the implementation kinda part time (kinda because many weeks were actually full time, sometimes to detach yourself from the keyboard is complicated), and even before LLMs the implementation was likely something I could do in four months. What changed is that in the same time span, I was able to do a lot more. This is the short story of what happened. In the first month I just wrote the specification document. The rationale for the new data type, the C structures, the sparse representation used, the exact semantics of the array cursor for ring buffer and ARINSERT. I started writing for days a long specification by hand, then I paired with Opus initially, then GPT 5.3 was released and I switched all the design and development with Codex. Since then I use only GPT 5.x for system programming tasks. Thanks to AI, the specification evolved a lot, via back and forth of feedback, intellectual challenges about what was the best design, what was the right compromise, what was too engineered and what not. Starting from the second month, I started the implementation using automatic programming (auto coding if you prefer), constantly reviewing the developed code. Then I realized that the level of indirection I picked was wrong. I really wanted people to be able to do ARSET myarray 293842948324 foo and everything to still work without huge allocations. The two levels of directory + slices (sparse and dense) I had were not enough. Because I had AI, I took no compromises, and I decided to go the extra mile. Once certain conditions are reached, the data structure internally changes shape, and becomes a super directory of sliced dense directories, that also point to the actual array slices (4096 elements per slice, by default). This design provided still the internal "is actually an array" representation I wanted, and the memory characteristics I seeked, while being able, for ARSCAN, and ARPOP, to scan the existing arrays taking a time proportional to the existing elements and not to the range span. Then, it was time to read all the code, line by line. Everything was working, and this type has massive testing, thanks, again to AI, but still things that superficially work do not mean they are optimal. I found many small inefficiencies or design errors that I didn't want, so I started a process of manual and AI-assisted rewrite of many modules. When this stage was done, I started, during the third month, to stress test the implementation in many different ways. I started to be confident that it was really solid, useful, well designed. Then… it happened. While modeling different use cases to see if the data structure was comfortable to use, I started to put markdown files into Redis arrays. Because files are a very good match for it. At this point, as I was working for other goals with agents, I realized that I could have the skills markdown files centralized knowledge base that I needed, so from a need of mine I decided to implement ARGREP. But I wanted regular expressions, too. What library to pick? I ended up picking TRE (thanks Ville Laurikari!), because when you have regexp in Redis, you want to be sure that there are no pathological patterns in time or space. But TRE was very inefficient in a specific and extremely useful case, that is matching foo|bar|zap. So with the help of GPT I optimized it, fixed a few potential security issues, and extended the test. I had everything in place. You know what was the biggest realization of all that? For high quality system programming tasks you have to still be fully involved, but I ventured to a level of complexity that I would have otherwise skipped. AI provided the safety net for two things: certain massive tasks that are very tiring (like the 32 bit support that was added and tested later), and at the same time the virtual work force required to make sure there are no obvious bugs in complicated algorithms. To write the initial huge specification was the key to the successive work, as it was the key to review each single line of sparsearray.c and t_array.c and modifying everything was not a good fit. I didn't spend any word on the use cases as I tried to document the PR itself with a message where they are detailed: https://github.com/redis/redis/pull/15162 So it was not really useful to repeat myself here. Enough to say that I really believe it is about time for Redis to have a data type where the numerical index is part of the semantics. I hope the Array PR will be accepted soon, and that we can benefit from the new use cases it opens. Of course, feedback is welcomed. Thank you. Comments

0 views

Premium: The AI Compute Demand Story Is A Lie

Everyone, it’s time to talk about AI demand and the capacity constraint issues across the industry. These constraints are not a result of “incredible demand” for AI, but the desperation of hyperscalers and the avariciousness of two near-trillion-dollar failsons living off their parents’ welfare. Just two weeks ago, both Amazon and Google pledged to invest up to another combined $65 billion in Anthropic, a company that just raised $30 billion in February and plans to raise another $50 billion more , following Amazon’s $15 billion (and as much as $35 billion more) investment in OpenAI in February . This is not what you do when real, meaningful demand exists for AI services. Assuming that these rounds are closed at their higher limits, it will mean that Google has invested $43 billion and Amazon $33 billion in keeping Anthropic alive. This also doesn’t make sense when you look at Anthropic’s own projections. Per The Information , Anthropic believes it will become cash-flow-positive in the next two years after losing exactly $11 billion in both 2026 and 2027: This only becomes more astonishing when you read that Anthropic intends to make $18 billion in 2026, $55 billion in 2027, $102 billion in 2028, and $148 billion in 2029. That’s revenue, not profit.  You may also be wondering how Anthropic goes from losing $11 billion two years running to making $2 billion in profit, and the answer is “nobody knows, including Anthropic.”  In any case, what Anthropic is saying in these projections is that it will lose $29 billion in 2026 and $66 billion in 2027. It’s also not clear what Anthropic’s actual costs will be in those years, because The Information decided it wasn’t necessary to include those. Thankfully, The Wall Street Journal did , suggesting that Anthropic intends to spend at least $86 billion on training costs alone through the end of 2029. It’s become blatantly obvious that Google and Amazon are conspiring to keep one of their largest business lines alive, much like Microsoft funneled over $13 billion into OpenAI before allowing OpenAI to seek other compute providers when it slowed down its data center construction . While I think Satya Nadella is a verbose dullard, Microsoft CFO Amy Hood is clearly quite smart, and jumped at the opportunity to allow Oracle to mortgage its entire future on OpenAI and Sam Altman’s clammy little dreams . Hood has managed to disconnect Microsoft from OpenAI’s welfare system, and while it claimed it was investing in Anthropic last November and in its February 2026 funding round , its latest 10-Q only mentions Anthropic once — as part of the work “philanthropic” on page 59. And now Microsoft has ended its exclusivity deal over OpenAI’s models, allowing Amazon to sell them too, but still retaining a revenue share of 20% from OpenAI’s sales , including from its partnership with Amazon, a few months after Amazon and OpenAI agreed a $138 billion eight-year-long deal that involved 2GW of capacity. A gigawatt here, a gigawatt there, soon you’ll be making real money. Except…nobody is making real money, and it appears that the vast majority of AI capacity and revenue is either going to OpenAI or Anthropic, and the rest is going to Microsoft, Google, and Amazon, who then spend that money on GPUs from NVIDIA or data centers to put them in. What numbers we do have around AI revenues are extremely sad.  I estimate that 70% or more of Microsoft’s $37 billion in annual AI run rate comes from OpenAI’s estimated $24 billion in annualized compute spend on Azure, taking up more than 80% of Microsoft’s estimated 2GW of AI capacity . OpenAI, per its CFO, ended 2025 with 1.9GW of capacity , and 67% of CoreWeave’s revenue is Microsoft paying for OpenAI’s training compute.  Similarly, Amazon’s $15 billion in annualized AI revenue is taken up by an estimated $12 billion in annualized AWS spend from Anthropic, and I estimate that more than 80% of that is accounted for by my estimated $12 billion in annualized spend from Anthropic. Today I’m pushing against the grain about as hard as anybody has in the AI bubble. I fundamentally believe that the AI demand story is nonsense — a mirage created by two companies that have only been successful as a result of having near-infinite resources provided to them by hyperscalers. Google, Amazon, and Microsoft have spent a combined $803 billion in capex on the AI bubble so far, and OpenAI and Anthropic have raised (assuming their rounds fully close) over $252 billion.  Assuming the rounds close, these three hyperscalers have sunk a combined $78 billion in funding into OpenAI and Anthropic, all while building infrastructure almost entirely in their service, and signing deals with neoclouds to continue providing it. The AI demand story is a lie, because the only way to create a company able to actually meet said demand is for a hyperscaler to fund it themselves.  Had Amazon not given it $8 billion and Google $3 billion in its earliest days, Anthropic would’ve never been able to grow to the scale that it could spend tens of billions of dollars a year on AWS and Google Cloud, nor would OpenAI have been able to do so without the earliest infusions of over $10 billion from Microsoft (of which the majority came in the form of Azure credits), and none of this would’ve been possible had hyperscalers not effectively pre-sold their own infrastructure to their own incubated companies. There is little “AI demand” outside of hyperscalers funnelling themselves money. The AI data center capacity crunch is a result of how long it takes to build data centers — Microsoft, Google and Amazon had an early lead, experience, and massive amounts of cash to deploy in a way that nobody else could. That’s why you can’t find A) anybody who’s spending anywhere near as much on compute as OpenAI and Anthropic and B) anybody who’s managed to compete with them at any scale. Their existence is entirely subsidized, their success a mirage, and their compute spend effectively three companies feeding themselves money.  And despite all the crowing around “the insatiable demand for compute,” there doesn’t appear to be any evidence that anybody is spending that much on it outside of Anthropic and OpenAI. If I were wrong, we’d see literally any other AI startup signing these massive compute contracts. Big Tech needs $3 trillion in new AI revenue by the end of 2030, or it’s wasted the majority of its capex. I estimate that Anthropic and OpenAI make up at least 85% of current and future AI compute spend, either through their own direct spending or hyperscalers like Google, Amazon or Microsoft renting capacity for them. Microsoft, Google and Amazon have built as much as 75% of their AI data center capacity to service two customers — OpenAI and Anthropic — putting the true cost of OpenAI and Anthropic, including total funding of $180 billion and $72 billion respectively, at at least $600 billion in combined infrastructure and equity investments.  And, obviously, the vast majority of their funding going toward compute spend across these three companies. OpenAI and Anthropic cannot afford to pay their future compute commitments without hyperscaler and venture capital subsidies. Outside of Anthropic, OpenAI, Google (for OpenAI, Anthropic and Meta), Microsoft (for OpenAI and Anthropic), Amazon (for OpenAI, Anthropic and Meta), CoreWeave (for OpenAI, Anthropic, and Meta) and Meta, less than $1 billion of actual AI compute demand exists.  In all honesty, I’ve struggled to find more than $500 million outside of Jane Street, which also funded CoreWeave. OpenAI and Anthropic’s compute spend and demands have created an illusion of demand, becoming a systemic weakness in CoreWeave, Nebius, IREN, and TeraWulf. Hyperscaler buildouts appear to be almost-entirely focused on either OpenAI or Anthropic, with little proof of their own services generating enough demand to fulfil them. There is not enough revenue to substantiate the existence of the in-progress data center construction, with over $157 billion in annual revenue required to monetize the 15.2GW (11.2GW critical IT) of data centers under construction to be finished by the end of 2027. Google is creating SPVs with investment firms to sell TPUs to itself, and has, via Broadcom, sold $63 billion in TPUs to Anthropic, which it will then bill for the compute, creating a circular financing system similar to NVIDIA’s. To support the estimated $800 billion in GPU sales that NVIDIA claims will come through by end of 2027, there needs to be 39.6GW of new data centers constructed (only 15.2GW of which are under construction), and around $383 billion in annual AI compute demand for an industry that — even with OpenAI and Anthropic’s spend — doesn’t even reach $70 billion in annual demand.

0 views

The Shapeless Unease

Struck by the sudden and untimely death of her cousin, and distressed by the terrible political order, Samantha Harvey finds that she cannot sleep. There is nothing wrong with her, or there is everything wrong with her, or there is everything wrong in the world—in the grief that has passed and in all the grief that is yet to come. Mordant and morbid, suffused with anxiety, The Sleepless Unease is as much a meditation on being in a world marked by intolerable uncertainty, global-scale grift, and constant noise as it is about that most basic human need. A worthwhile companion on many a sleepless night. View this post on the web , subscribe to the newsletter , or reply via email .

0 views

The whole joy of it all

Four days ago, on Thursday 30 April 2026, my wife Olga gave birth to a beautiful baby named Marius , and the three of us seem to be glowing with love ever since. Mother and child are both healthy, and I am as happy as I am in admiration of the work from every one involved at the hospital; midwives in particular have been truly incredible. I cannot wait for us to be back home as a family.

0 views
Stratechery 2 days ago

Google Earnings, Meta Earnings

Wall Street loved Google's earnings, and hated Meta's, even though the latter's core business was more impressive. The difference is that Google is monetizing its investments now (and it might be all Anthropic).

0 views
Stavros' Stuff 2 days ago

Adding a feature to a closed-source app

I use Audiobookshelf (abbreviated ABS) for all my legal audiobooks that I bought legally, and I really like it. I also use the Smart Audiobook Player (abbreviated SABP) Android app, which I also bought (legally this time) to listen to books, because it has the strongest featureset out of all the apps I’ve tried, particularly when it comes to navigating around books. Unfortunately, there’s one problem: SABP can’t synchronize my reading progress with the ABS server, which is inconvenient for me. I use SABP when cycling or walking, but use other apps that integrate deeply with ABS (mostly Lissen and ABS’s own app) on my car’s Android console, and the lack of syncing between the two is a major pain. The ABS-compatible apps are mostly open source, and what better way to contribute to open source than to submit some patches that add the features I like? “However”, I thought, “why not not do that, and instead see if I can add Audiobookshelf syncing to the app?” “Yes”, I decided, “this sounds reasonable, despite SABP being a closed-source Android app, a platform with which I have zero familiarity”. What I do have familiarity with, though, is telling Claude what to do and steering it along. Therefore, I decided I would do the impossible , and use LLMs to add ABS syncing to SABP ! The first step was to see whether this is possible at all. Android apps come as APKs, which are just zip files containing bytecode. The first thing I did was to ask Claude to decompile the app (even though I didn’t really know if that was possible, or how it was done). Luckily, all this required was to run and on the files in the APK. is a utility that turns bytecode into a textual representation (called smali) so that it can be edited. This is a lossless, reversible process (which means you can edit the resulting code and recompile it back into the app), but the textual representation is basically assembly, and pretty hard to work with. , on the other hand, decompiles to (hopefully) readable Java, but is useful only for illustration; you can’t recompile it back into an app, and you can’t really edit it in any way. Some developers use obfuscation tools (like ProGuard) to make their decompiled code much more opaque and hard to read. So, the question at this stage was whether the app could be decompiled, and how readable the resulting output would be. Running the tools gave some promising results: The app was fairly readable, with even human-readable class names having been partially preserved! A lot of the code was obfuscated, with names like , , , but I lucked out and enough relevant code was readable that I didn’t have to spend hours piecing things together. This was encouraging, but I still didn’t know whether I could easily inject syncing code into the app. To begin my due diligence, I asked Claude to trace whether there was a point where we could add a hook to send our position to the server. After a bit of digging around, it discovered that one function, , was being called by every code path that saved progress to disk: regular ticks, pauses, file changes, backgrounding, they all saved progress using it. The existence of this code path was a stroke of luck, as it meant that I had found a natural point to hook my progress updating into, but Claude did a lot of work to verify that the code paths actually converged. This was great, we found a single spot where we could hook things, but how could we do the hooking itself ? We can’t edit or recompile the decompiled Java, and smali, which we can edit and recompile, is a real pain to write anything significant in. Still, though, the impossible was slowly drifting within my reach. The second part of due diligence was to see for myself how the ABS API worked, so I knew what to send in the payload if I ended up being able to hook into the syncing. I sent a few requests by hand, but kept getting some weirdness. The times I was submitting didn’t match what I was getting back, and the progress indicator was out of sync with the submitted position in seconds. This was surprising to me, because I know ABS progress syncing works fine with other apps. After some trial and error, I realized that during my testing I had accidentally set to on the book I was testing with, and ABS was resetting the progress when the book transitioned from “finished” to “not finished”. This is a surprising thing to happen, since I’d expect the server to reset when I’m going the other way (i.e. when I finish the book), but I guess the rationale is that I’m starting the book fresh if I mark as on an already-finished book. When I used a non-finished book as the target, the API started responding reasonably, and I had all the info on the endpoints I needed, with their payload shapes, which I gave to Claude. It’s important for me to do this sort of experimentation myself, as often edge cases will be hiding in these API contract boundaries, and I want to build a good mental model of how the change will work before I ask the LLM to implement it. Having the API calls was good, but writing smali code to perform an HTTP request and send/receive JSON would still be taxing work, even for an LLM, and I couldn’t really help here. Luckily, Claude knew that Android makes modding significantly easier than other platforms: We didn’t have to write smali at all! We could write all the syncing code in bog-standard Java, compile it with into bytecode, create the necessary file with (which ships with the regular Android SDK!), and put that into the tree. Then, we just needed a tiny bit of smali code in to jump to our compiled Java code, and everything should work: This works because Android itself natively supports multiple files in one APK, so you don’t have to hack around anything. The investigation was finished, but now we also needed to actually build the thing (an affair whose success was still not guaranteed). Writing the code for this and compiling it into an APK was all Claude, with steering from me. You can read about my exact LLM workflow in my recent post , but it roughly consists of planning (using ticket to write… tickets), implementation, and review steps. Claude discovered that apktool 2.7.0 doesn’t like $-prefixed filenames in the resource table, and decided to use the original manifest, which was fine because we weren’t using custom resources. It also caught a timing bug in the smali patch, where it needed to call a function after another one was run, otherwise the BookData field would be stale. These issues did affect the final implementation, and I was relieved that Claude is smart enough to catch and fix them. Claude did a lot of heavy lifting here, and we ended up with ~550 lines of Java, and some smali magic with to jump to our Java code. The code review phase was all LLMs (Opus 4.6/GPT-5.5), and it’s a step I never skip, as I’ve found that it catches most of the bugs. In one case, Claude had written thirty lines of reflection code because it assumed a setter didn’t exist. The reviewer caught that the setter existed, and had Claude use it directly and remove the superfluous code. This is a pattern I see very frequently in LLM-assisted development, where one model will have big blind spots, leading to bugs or departures from the desired functionality. A second review pass with another model generally fixes this, though I’m not sure whether it’s because of different models spotting different things (like “you can’t spot your own typos” for LLMs) or because a second, focused review pass makes the model pay more attention. I suspect it’s a combination of the two. The reviewer also caught a mistaken compression of the resources file, which would have caused the APK to silently fail to install on my device, even though it looked fine. There was also a race condition that was flagged and fixed in this step, and an instruction to clamp the end timestamp to the book’s length, though I would hope that this check happens on the server too. The codey bits having been done, I had to decide how to handle book matching and server configuration. I needed to make a decision on two things: There were a few options, one of them being adding an “Audiobookshelf” section to the settings, and adding the server’s hostname and API key there, but this was too much work, especially trying to find call sites to patch into existing screens. For the book matching, Claude recommended that we do a lookup of the book by name every time we loaded progress, but that was brittle and would break with more than one book of the same name. I decided to use a config file in the book directory, which was a simple JSON file that looked like this: This way, the app could load everything it needed with minimal fuss (the Java code could simply read this file at startup). There was something that Claude didn’t catch, and actually recommended the opposite: Its advice was to only send the timestamp to the server if it was later than the server’s timestamp (ie if it was later in the book). I pointed out to Claude that this would create a significant problem where, if you seeked to a later position for some reason, you’d never be able to come back from it. The app would keep syncing your position to the later one when loaded, and never update the server’s timestamp, effectively not only invalidating the syncing, but also forcing you to remember your position manually, which is quite a big regression from current functionality. This bug would also cause other apps to get their position overwritten with the later one every time SABP loaded. Claude quickly agreed that this was an issue, and changed the code to sync all seeks. Testing it out, I realized that Claude never retrieved the book’s position from the server at all. I pointed out here that this was necessary to avoid clobbering the position in other apps, because I might use Lissen (and progress there), go back to SABP, and have my (true) progress overwritten by the old position. This was a serious data loss issue that the LLMs completely missed, both in planning/implementation and in review, and an issue that human involvement solved. The code was now in good enough shape to actually try out, which led to another problem. Android, like basically any modern platform, requires apps to be signed by the developer before they can run. Unfortunately, I’m not the developer of SABP, which means I didn’t have access to the key used to sign the app. This isn’t a big obstacle, since apps can be signed by any key (though Google is trying to force us to show them ID to run our apps on our devices), so I just created my own key and signed the recompiled APK with it using . Unfortunately, this does have one downside: The resigned app can’t be installed over the old one, you need to uninstall the old app (and probably lose data) and install the new one again. I opened it up, I started playing a book, and verified that the ABS server position got updated. I didn’t even lose any settings, because SABP keeps its settings in a file next to the audiobooks, which wasn’t deleted when uninstalling. Modifying the application to add the feature I wanted worked fine, and, with the increased skill the LLMs gave me, the lack of source access didn’t block me (it merely posed a sizable problem). However, there was still significant friction (what with the decompile dance, smali, figuring out call sites, etc), and I got very lucky that the code wasn’t more obfuscated. Even after the functionality has been implemented, though, I can’t share the output, both because of potential legal issues and because it’s just a hassle and will break every release. The journey was fun, and having an app that works how I want it is helpful, but there’s a wider point: Before LLMs, the code’s license didn’t matter much for end users wanting to modify their software. Whether the source was open or closed, the biggest reason people didn’t mod their software was just that they didn’t know how to . LLMs have expanded the candidate pool, and, now that many more people can write code that works, the availability of the source is the most important hurdle. The set of people who can now modify their software has increased by orders of magnitude, and includes people who always had good ideas, or good product sense, but didn’t have the skills to make them a reality. In this example, the feature I implemented will be used by me, and basically nobody else, because closed-source software has close to no mechanism for change ingestion. Open source software has always had concrete ways to accept contributions from others, you’d simply make the change you wanted and submit it to the maintainers for inclusion/rework/feedback. This contribution process is even more important now that code can be generated orders of magnitude more cheaply, and the fact that it exists is an important advantage that open-source software has over closed-source. When starting out, I thought this would be impossible, but each step turned out to be very doable. Where a few years ago only a handful of people could reverse engineer an app, now it’s within reach of the average developer with a free afternoon. I’m really happy about the way this feature turned out, but this adventure only made me realize that open source software just aligns with my interests so much more. I’m going to do what I joked I wouldn’t at the start of this article, and switch to Lissen as my audiobook player. I hadn’t used it in a while, but, while writing this post, I fired it up again, and it seems to have gained a few features, plus it’s always been very well-designed and looks great. I guess I’m not going to need SABP any more, but, well, the journey is the destination. The hostname and API key of the ABS server. The ID of each book on the server, so it can submit progress to the specific book without having to rely on name matching.

0 views
Hugo 2 days ago

Day 181: What I learned with a Claude SEO Skill

Alright, I’ve barely posted anything for the past 181 days, but you know how it is… procrastination. Anyway, it’s been 181 days since I launched Writizzy . It’s the blogging platform I’m using for this very article. I’m the first one convinced by my own product, which is already a small victory :) With a bit of exaggeration, I could tell you that in 181 days, Writizzy has managed to reach the same level as Substack, Medium, or Beehiiv in terms of features. Obviously, on the usage side, we're not quite there yet. About 480 users have tested it, with around 130 of them being truly active. And above all, it's far from being a smooth ride. I have a huge thorn in my side: very few people are discovering the product. Even worse, my traffic is decreasing. With 1,850 unique visitors in April, it’s my second worst month since the beginning. And one of the reasons (though not the only one) is SEO. "SEO is Failing", that sounds like it could be the title of a gritty Liam Neeson thriller. With 1,850 unique monthly visitors, I’m getting almost 3 times less traffic than my own personal blog (the one you’re reading right now). That’s… room for improvement :) Most of the traffic comes from social media, Reddit, Facebook (?? I don't know why), Uneed (a product launch platform), and various blogs already using Writizzy. There is some traffic coming from Google, but it’s what we call "Brand" traffic. These are people typing "Writizzy," so they already know the product. In that case, you can't really call it new user acquisition. So, a few weeks ago, I wanted to self-audit to see if I could find what was wrong. To do that, I found a set of skills for Claude: claude-seo . Claude-SEO consists of about twenty skills that test several areas: content quality, JSON-LD markup, GeoSearch (AI search optimization), technical SEO, etc. There are 21 of them, so I won't list them all, you'll have to excuse me... Once installed, I ran the command and here is the first result: 47/100 isn't great, but at the same time, it’s actually good news. It means there’s work to be done and the tool will be able to help me. Claude-SEO tests many things, especially technical SEO. In theory, this is the easiest part since it involves structural optimizations, titles, performance, JSON schemas, etc. I received some very relevant advice, particularly regarding home page image optimization and pre-connection directives for my Bunny CDN. I also got a lot of feedback on the JSON-LD schemas used on the page. ::callout{type=info} About JSON-LD: You have to understand that a bot indexing a site doesn’t read it like we do. We can help it better understand what the site is about by giving it structured data in JSON-LD format. It’s invisible to the human reader but very practical for the crawler. :: You can see the entire JSON-LD structure of the home page that I modified thanks to this site (which I invite you to use for yourself): validator.schema.org Claude-SEO also allowed me to realize there was a bug in the nuxt-seo library I use, which was impacting all the titles and meta descriptions of my site. Every page had the same attributes! (By the way, Claude also helped me diagnose the bug to open an issue , which has since been fixed). But most importantly, Claude-SEO suggested several relevant additions: Usually, we tend to create landing pages that group all this information together, but apparently, it can be beneficial to have separate pages to answer specific search intents, like "Writizzy pricing." As for the "About" page, it's about reinforcing the site's authority based on E-E-A-T criteria (Experience, Expertise, Authoritativeness, and Trustworthiness), criteria Google uses to assess the trust they can place in a site. Once all that was in place, I ran a second test and got a 64/100 . Claude-SEO is not a deterministic tool. In other words, new relevant problems can appear that weren't noted in the first run. Second issue: sometimes page crawling fails. For example, during this second run, the file was still considered missing even though it was there. Same for the blog, which wasn't detected. However, there was still clear progress between the two executions, and some new problems were totally valid: No security headers were present. It’s not crucial for SEO, but it’s still a bad signal. I installed nuxt-security , which resolved this very quickly. More annoying: http://writizzy.com was returning a 200 and https://www.writizzy.com was sending an SSL error because the only valid URL is https://writizzy.com . That’s normal, but bad for crawling. HTTP must redirect to HTTPS, and "www" as well if you don't want to manage it. This was all handled directly at the Bunny and Coolify levels. I'll skip other minor or less interesting detections, which brings us to the 3rd execution: 71/100 . This 3rd run mainly detected implementation errors on what had already been done, encoding errors in JSON-LD, logos with formats not accepted for Open Graph, and a few suggestions for additional pages. This Claude plugin was super interesting. I learned things (like E-E-A-T or certain JSON-LD entities I didn't know), it highlighted problems I could have seen myself (like security headers, lack of HTTP to HTTPS redirects), and it allowed me to better configure my Nuxt framework. I highly recommend testing it on your own site. Now, did it work? Has my SEO become the best in the world? Well, not really. For a reason I can't explain, Google refuses to index the pages of my site except for the Home page. If you look on Google with , only the home page shows up. And this is confirmed in the Google Search Console, which lists all other pages as "Discovered - Currently Not Indexed." And there, it’s a mystery. Especially since I have the exact same problem on hakanai.io (another product I'm building), only the home page is indexed once again. At this stage, I’m a bit lost. I think I’ve truly improved the SEO from a technical standpoint, but I must be missing a massive issue that I don’t understand. For some unknown reason, my site is considered untrustworthy or lacking interest, even though I have a Domain Rating of 47 and 3,000 backlinks. In short, SEO isn't just about tech, and for now, I don't have all the keys yet :) If you have SEO knowledge and ideas, feel free to share, I’m all ears. Next steps: I’m going to go through every page one by one. If Google deems my content "uninteresting," I need to understand why. In the meantime, if you want to help me send positive signals to Google (or just test a pretty cool blogging tool), don't hesitate to start your blog on Writizzy with a little backlink, it’s a boost that could really help me ^^ Adding an llms.txt file to improve my ranking for AI assistants. Adding dedicated pages for the founding team , pricing, and specific features. Claude-SEO suggested several additions for Cache-Control directives and even gave me the configuration for Nuxt since it knew I was using it.

0 views

Superpowers 5.1.0

I'm pleased to announce Superpowers 5.1.0. The biggest changes in this release are: -A reworking of how we use git worktrees, now that Claude Code and Codex have first-class support for them. You can always find the latest version of Superpowers on GitHub Removing the deprecated slash commands that date to the earliest days of Superpowers, when skills triggering was still really brittle. Switching the 'code reviewer' subagent to be a regular subagent with a custom prompt, reducing our platform footprint, so that we no longer need any special subagent types. A more efficient OpenCode integraiton New support for Factory Droid Cleanups to Subagent Driven Development and Code Review Removal of some old boilerplate text in skills that didn't improve outcomes.

0 views
Armin Ronacher 2 days ago

Content for Content’s Sake

Language is constantly evolving, particularly in some communities. Not everybody is ready for it at all times. I, for instance, cannot stand that my community is now constantly “cooking” or “cooked”, that people in it are “locked in” or “cracked.” I don’t like it, because the use of the words primarily signals membership of a group rather than one’s individuality. But some of the changes to that language might now be coming from … machines? Or maybe not. I don’t know. I, like many others, noticed that some words keep showing up more than before, and the obvious assumption is that LLMs are at fault. What I did was take 90 days’ worth of my local coding sessions and look for medium-frequency words where their use is inflated compared to what wordfreq would assume their frequency should be. Then I looked for the more common of these words and did a Google Trends search (filtered to the US). Note that some words like “capability” are more likely going to show up in coding sessions just because of the nature of the problem, so the actual increase is much more pronounced than you would expect. You can click through it; this is what the change over time looks like. Note that these are all words from agent output in my coding sessions that are inflated compared to historical norms: The interactive word trend chart requires JavaScript. Something is going on for sure. Google Trends, in theory, reflects words that people search for. In theory, maybe agents are doing some of the Googling, but it might just be humans Googling for stuff that is LLM-generated; I don’t know. This data set might be a complete fabrication, but for all the words I checked and selected, I also saw an increase on Google Trends. So how did I select the words to check in the first place? First, I looked for the highest-frequency words. They were, as you would expect, things like “add”, “commit”, “patch”, etc. Then I had an LLM generate a word list of words that it thought were engineering-related, and I excluded them entirely from the list. Then I also removed the most common words to begin with. In the end, I ended up with the list above, plus some other ones that are internal project names. For instance, habitat and absurd , as well as some other internal code names, were heavily over-represented, and I had to remove those. As you can see, not entirely scientific. But of the resulting list of words with a high divergence compared to wordfreq, they all also showed spikes on Google Trends. There might also be explanations other than LLM generation for what is going on, but I at least found it interesting that my coding session spikes also show up as spikes on Google Trends. The choice of words is one thing; the way in which LLMs form sentences is another. It’s not hard to spot LLM-generated text, but I’m increasingly worried that I’m starting to write like an LLM because I just read so much more LLM text. The first time I became aware of this was that I used the word “substrate” in a talk I gave earlier this year. I am not sure where I picked it up, but I really liked it for what I wanted to express and I did not want to use the word “foundation”. Since then, however, I am reading this word everywhere. This, in itself, might be a case of the Baader–Meinhof phenomenon , but you can also see from the selection above that my coding agent loves substrate more than it should, and that Google Trends shows an increase. We have all been exposed to LLM-generated text now, but I feel like this is getting worse recently. A lot of the tweet replies I get and some of the Hacker News comments I see read like they are LLM-generated, and that includes people I know are real humans. It’s really messing with my brain because, on the one hand, I really want to tell people off for talking and writing like LLMs; on the other hand, maybe we all are increasingly actually writing and speaking like LLMs? I was listening to a talk recording recently (which I intentionally will not link) where the speaker used the same sentence structure that is over-represented in LLM-generated text. Yes, the speaker might have used an LLM to help him generate the talk, but at the same time, the talk sounded natural. So either it was super well-rehearsed, or it was natural. At least on Twitter, LinkedIn, and elsewhere, there is a huge desire among people to write content and be read. Shutting up is no longer an option and, as a result, people try to get reach and build their profile by engaging with anything that is popular or trending. In the same way that everybody has gazillions of Open Source projects all of a sudden, everybody has takes on everything. My inbox is a disaster of companies sending me AI-generated nonsense and I now routinely see AI-generated blog posts (or at least ones that look like they are AI-generated) being discussed in earnest on Hacker News and elsewhere. Genuine human discourse had already been an issue because of social media algorithms before, but now it has become incredibly toxic. As more and more people discover that they can use LLMs to optimize their following, they are entering an arms race with the algorithms and real genuine human signal is losing out quickly. There are entire companies now that just exist to automate sending LLM-generated shit and people evidently pay money for it. If we take into account the idea that the highest-quality content should win out, then the speed element would not matter. If a human-generated comment comes in 15 minutes after a clanker-generated one, but outperforms it by being better, then this whole LLM nonsense would show up less. But I think that LLM-generated noise actually performs really well. We see this plenty with Open Source now. Someone builds an interesting project, puts it on GitHub and within hours, there are “remixes” and “reimplementations” of that codebase. Not only that, many of those forks come with sloppy marketing websites, paid-for domains, and a whole story on socials about why this is the path to take. I have complained before that Open Source is quickly deteriorating because people now see the opportunity to build products on top of useful Open Source projects, but the underlying mechanics are the same as why we see so much LLM slop. Someone has a formed opinion (hopefully) at lunch, and then has a clanker-made post 3 minutes later. It just does not take that much time to build it. For the tweets, I think it’s worse because I suspect that some people have scripts running to mostly automate the engagement. And surely, we should hate all of this. These low-effort posts, tweets, and Open Source projects should not make it anywhere. But they do! Whatever they play into, whether in the algorithms or with human engagement, they are not punished enough for how little effort goes into them. That increases in speed and ease of access can turn into problems is a long-understood issue. ID cards are a very unpopular thing in the UK because the British are suspicious of misuse of a central database after what happened in Nazi Germany. Likewise the US has the Firearm Owners Protection Act from 1986, which also bans the US from creating a central database of gun owners. The gun-tracing methodologies that result from not having such a database look like something out of a Wes Anderson movie . We have known for a long time that certain things should not be easy, because of the misuse that happens. We know it in engineering; we know it when it comes to governmental overreach. Now we are probably going to learn the same lesson in many more situations because LLMs make almost anything that involves human text much easier. This is hitting existing text-based systems quickly. Take, for instance, the EU complaints system, which is now buckling under the pressure of AI . Or take any AI-adjacent project’s issue tracker. Pi is routinely getting AI-generated issue requests, sometimes even without the knowledge of the author . I know that’s a lot of complaining for “I am getting too many emails, shitty Twitter mentions, and GitHub issues.” I really think, though, that now that we know that it’s happening, we have to change how we interact with people who are increasingly automating themselves. Not only do they produce a lot of shitty slop that we all have to sit through; they are also influencing the world in much more insidious ways, in that they are influencing our interactions with each other. The moment I start distrusting people I otherwise trust, because they have started picking up LLM phrasing, it erodes trust all over society. You also can’t completely ban people for bad behavior, because some of this increasingly happens accidentally. You sending Polsia spam to me? You’re dead to me. You sending me an AI-generated issue request and following up with an apology five minutes later? Well, I guess mistakes happen. Yet, in many ways, what is going on and will continue to go on is unsettling. I recently talked with my friend Ben who said he forced someone to call him to continue a conversation because he was no longer convinced he was talking to a human. Not all of us have been exposed to the extreme cases of this yet, but I had a handful of interactions in which I questioned reality due to the behavior of the person on the other side. I struggle with this, and I consider myself to be pretty open to new technologies and AI in particular. But how will my children react to stuff like this? My mother? I have strong doubts that technology is going to solve this for us. The reason I don’t think technology is going to solve this for us is that while it can hide some spam and label some generated text, it won’t fix us humans. What is being damaged here are social interactions across the board: the assumption that when someone writes to you, there is a person on the other side who has put some care into the interaction. I would rather have someone ghost me or reject me than send me back some AI-generated slop. Change has to start with awareness and an unfortunate developmend is that LLMs don’t just influence the text we rea and influence the text we write, even when we don’t use htem. Given the resulting ambiguity, we need to become more aware of how easily we can turn into energy vampires when we use agents to back us up in interactions with others. Consider that every time someone reads text coming from you, they will have to increasingly have to make a judgement call if it was you, or an LLM or you and an LLM that produced the interaction. Transparency in either direction, when there is ambiguity, can help great lengths. When someone sends us undeclared slop, we need to change how we engage with them. If we care about them, we should tell them. If we don’t care about them, we should not give them visibility and not engage. When it comes to creating platforms and interfaces where text can be submitted, we need to throw more wrenches in. The fact that it was cheap for you to produce does not make it cheap for someone else to receive, and we need to find more creative ways to increase the backpressure. GitHub or whatever wants to replace it, will have a lot to improve here and some of which might be going against it’s core KPIs. More engagement is increasingly the wrong thing to look at if you want a long term healthy platform. Whatever we can do to rate-limit social interactions is something we should try: more in-person meetings, more platforms where trust has to be earned, and maybe more acceptance that sometimes the right response is no response at all. And as for AI assistence on this blog, I have an AI transparency disclaimer for a while. In this particular blog post I used Pi as an agent to help me generate the dynamic visualization and I use the agent to write the code to analyze and scrape Google Trends.

0 views
Susam Pal 2 days ago

From RSS to Atom

Yesterday, I switched my website from RSS feeds to Atom feeds. In case you are wondering whether you have somehow landed on an ancient post from 2010, no, you have not. Yes, this is the year 2026, and I have finally switched from RSS feeds to Atom feeds. Yes, I am fifteen, or perhaps twenty, years too late. I have always wanted to do this but could never make the time for it. Finally, it happened while I was giving my brain some rest from my ongoing algebraic graph theory studies. That's when I felt like spending a little time on my website and doing a little Lisp to change the feeds from RSS to Atom. I suppose this was impulse coding , a bit like impulse buying, except that I ended up with an Atom feed instead of a new book. I find it quite surprising that when I have plenty of time, it usually does not occur to me to do these things, but when I am too busy and really short of time, these little ideas possess me during the short breaks I take. My personal website is one of my passion projects. Common Lisp is one of my favourite programming languages. So any time spent on this passion project using my favourite programming language is a very relaxing experience for me. It serves as an ideal break between intense study sessions. It took about an hour to implement the changes needed to make the switch from RSS to Atom. In the end, I could go back to my studies reinvigorated. In case you are curious, here is the Git commit where I implemented the change from RSS to Atom: 596e1dd . As you might notice, a large portion of the change consists of replacing the attribute in each post with the attribute. The attribute value was used as the value of the element in the RSS feeds. While an arbitrary short string could serve as the element for the items in an RSS feed, the element of the entries in an Atom feed needs to be a URI. It turns out UUID URNs are a common choice for such a URI. I ran the following shell command to replace all occurrences of the attribute with : The rest of the changes went into the feed templates and the Common Lisp program that statically generates the feeds along with the website. For examples of the resulting feeds, see feed.xml and absurd.xml . The first is the main website feed and the second is an example of a tag-specific feed. Yes, the aforementioned Common Lisp program generates a feed for each tag . As of today, the main feed at feed.xml contains only two entries even though this website has over 200 pages . I explain the reason later in Temporary Workaround . Here is an example Atom entry from my feeds: The ellipsis ( ) denotes content I have omitted for the sake of brevity. I like how each entry in the feed now has its own UUIDv4. I also like that timestamps in an Atom feed are in the format specified in RFC 3339 , which also happens to be a profile of ISO 8601. Further, I like that I can explicitly declare the content type to be HTML. Commonly used values for the content type attribute are , and . If it is , the content should be escaped HTML. If it is , the content should be an XHTML element containing valid XHTML. Explicit content type support is likely the biggest advantage of Atom over RSS. In comparison, RSS 2.0 does not specify any way to declare the content type. So feed readers have to inspect the content and guess what the content type might be. As I mentioned before, as of today, the main feed contains only two entries. That's because only new posts published since the migration to Atom are now included in the feed. This was done to avoid spamming subscribers. The Atom specification's requirement that each entry's ID must be a URI has caused the IDs of every entry to change. If I were to include the older posts from before the change in the feed, then those posts would appear as new unread items. Subscribers can find this quite annoying. In fact, I have received a few complaints about this in the past. So I was careful this time. I have a little one-liner workaround in my site generator to exclude posts published before this change from the feed. That was the only workaround I had to implement. Fortunately, my feed file had a neutral name like , rather than a format-specific name like , so I could avoid a URL change and the subsequent overhead of setting up redirects. Does any of this matter today? I think it does. Contrary to the recurring claim that RSS and Atom are dead, most of the traffic to my personal website still comes from web feeds, even in 2026. Every time I publish a new post, I can see a good number of visitors arriving from feed readers. From the referrer data in my web server logs (which is not completely reliable but still offers some insight), the three largest sources of traffic to my website are web feeds, newsletters and search engines, in that order. On the topic of newsletters, I was surprised to discover just how many technology newsletters there are on the Web and how active their user bases are. Once in a while, a newsletter picks up one of my silly or quirky posts, which then brings a large number of visits from its followers. Back to the topic of web feeds, there is indeed a decent user base around RSS and Atom feeds. A good number of visitors to my website arrive by clicking a feed entry that shows up in their feed reader. I know this with some confidence by looking at the (sic) headers of visits to my HTML pages and the subsequent browsing of the website, as opposed to the isolated and automated fetches of the XML feeds. So there must be a reasonably active base of users around web feeds. It is a bit like being part of an invisible social network that we know exists and that we can measure through indirect evidence. I found these three resources useful while switching to Atom feeds: Read on website | #web | #technology Impulse Coding Atom Entries Temporary Workaround Does It Matter? W3C Introduction to Atom W3C Feed Validation Service RFC 4287 : The Atom Syndication Format

0 views