Posts in Web-development (20 found)
iDiallo Yesterday

They Prefer the App

I like building websites. But in some circles, I might as well say that I like to drive to the forest before sunrise, chop down a tree, load it in my trunk, and gather some dry wood as well, then drive back before first light. All this just to use the wood to start a fire and cook breakfast for my family in our high-rise apartment. It makes no sense. There is a large class of apps that could be replaced by a simple website, especially those made for schools that only present information. The worst part is that in those apps, most of the things we take for granted on the web are blocked. You can't copy and paste, you can't open a link in a new app, and you have to update the entire app just to get new information. For someone like me, who never updates an app until it's necessary , I usually end up with broken applications. But when I complain, I'm usually alone in those circles, because no one seems to know what a website is. The more I explain, the more I sound like a character from the 90s explaining how cool email is. They don't know what a website is. Check their phones, they have a thousand apps. The last time I blogged about just using websites , several people pointed out that they prefer using apps. My argument was that there is nothing the LinkedIn app does that necessitates an app. All its features are supported on the web. All but pervasive tracking. But I'm fighting a losing battle, because a large number of people have forgotten, or never knew, that LinkedIn is just a website. So is Reddit, Facebook, Instagram, etc. They push you toward the app only so they can better harvest information from you. So when we tell people to use the website instead of the app, they don't understand, because these services only push the app. A large number of the population has started to believe that a website is just a preview of an app, like a lightweight version. While I'm here complaining about a single app displaying an unexpected notification, people in my circle have a thousand unread notifications. It's a surprise that they somehow respond to my messages in the midst of all those alerts. I've met people who have an app for every single restaurant they go to. While I'm reading the privacy policy of a single app, trying to determine if it's worth downloading to benefit from a 20% discount, my friends are already in the loyalty program of the juice bar that opened down the street less than a day ago. People download apps, and they don't understand websites. They have a thousand apps on their screen and would rather swipe through it to find the one app they need for a single purpose. When I read Dan Q's post a few days ago, I was relieved for a second, just to know that I'm not alone. We prefer using websites, and we know most apps are oversized wrappers around a website. But I have to remember that the people with a thousand apps are not the minority. We are. We are the few who would rather use a progressive web app than download a 300 MB wrapper. I'm not prescribing a solution here, just want to remind the web community that outside of our circles, people happily download a 300 MB app that displays information already available on the web.

0 views
daniel.haxx.se 2 days ago

Workshop Basel day one

On this hot summer’s day in Basel, Switzerland, the seventh HTTP workshop started. These events tend to work roughly the same way and the people in the room are also to large extent familiar and known since previous editions. Forty people in a meeting room, where we take turns in doing short talks on HTTP and networking topics, with the following question and discussion session. The rules for the meetings are explicitly Chatham rules, which means that everything I write about the meeting will be sufficiently fuzzy and without many company or personal names. This is not the kind of meeting that can be easily summed up in a short blog post anyway. You really should be here. Present in the room were representatives from all the world’s most prominent and used HTTP deployments: clients, browsers, CDNs, proxies and servers. I’m happy to say that there were also several first-timers. We like fresh blood. (If you think I’m being overly brief or vague about specifics in this post; that is partially on purpose but primarily because I’m a lousy note-taker and mostly write this up after a busy day that also may have involved beer.) After a round of introductions, we started. REST is a set of constraints, and in this presentation it was argued that it can or maybe even should be extended to do more. A number of recent applications like Mastodon/ActivityPub, Bluesky/AT, Matrix, Nostr, IndieWeb, all currently use HTTP to do state synchronization but they all do it differently in their own unique ways. Can REST and maybe HTTP be adjusted to help this for improved interoperability? Looking at the Common Crawl data and comparing data over time, it was observed that responses use the Last-Modified header field more now than they did in the past, and there were great follow-up speculations on why this is so. Data also shows that a large share of these headers present dates that are almost identical to the time the requests were issued. With the cc-lint tool , data was gathered on how HTTP is actually used today, proving that there is work to be done: deprecated headers are used, some headers are done wrong, and many are overly big. This indicates that there are well used both servers and clients out there that would benefit from cleanup. It probably also shows that doing HTTP correctly and all the correct headers is far from an easy task. Another presentation showed data, this time from a well-known CDN, on the impact the existing AI scraper bots have on the Internet from their point of view. It showed that roughly half of the requests and half of the bandwidth are spent by scraper bots. A long discussion followed where the numbers were questioned as maybe the numbers look like this because a sufficiently large number of the “bad AI scrapers” appear as regular users to the classifiers. Speculations of different kinds were made.  As a follow-up from a presentation from a previous HTTP workshop we got to learn how the journey on developing their new HTTP stack has progressed and several fun adventures and lessons from that were shared with the audience. A look into new HTTP API development at Apple . Some discussions and lessons learned from creating new APIs for both servers and clients. We got an excellent walk-through of some details and internals of the Android networking stack. Emphasis was perhaps especially put on ECH and QUIC connection migration, and the final “don’t tell us when your connection closed” led to a long new discussion on how we really should fix the problem: when connection has been left idle for a long time and it is closed by the server, the client (mobile phones) don’t want to be told. This, because getting that RST and more, just wakes up the radio and more on the phone only to tell it to go back to sleep. It was theorized that if we could get rid of this unnecessary battery waste, the accumulated gain across billions of devices would make a serious dent. Several additional HTTP related problems were of course also subsequently solved as we then wandered into the city for dinner and maybe a beer. Of course yours truly returned back to his hotel room in good time to be able to write up this blog post. The best part of these workshops might be the (no pun intended) networking and discussions had completely outside of the agenda. End of day one. Two more to come,

0 views
Unsung 2 days ago

“Cursed knowledge we have learned that we wish we never knew.”

Immich is a self-hosted photo/​video app, and one of their side pages is Cursed Knowledge : Cursed knowledge we have learned as a result of building Immich that we wish we never knew. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/cursed-knowledge-we-have-learned-that-we-wish-we-never-knew/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/cursed-knowledge-we-have-learned-that-we-wish-we-never-knew/1.1600w.avif" type="image/avif"> There is something about this format that I really enjoyed as a reflection but also as a way to share with others – simple one sentence/​paragraph updates with links, so you can inhale quickly but also go deep if needed. There’s some overlap with bugs here, but it’s not necessarily only buggy stuff – also quirks of formats, observations, etc. I made a cursed knowledge page for Unsung – let me know! (Thanks to Casey Gollan for posting about the original page.)

0 views
Kev Quirk 2 days ago

📝 2026-07-13 23:22: Every time I look at Sven's blog I get jealous. I loved his previous design...

Every time I look at Sven's blog I get jealous. I loved his previous design so much I copied it (with his permission). His new design is so fun and it's making me want to make mine more fun (no copying this time though). I'm just not sure I have the time at the moment. 🤔 https://svbck.blog/ Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
Unsung 3 days ago

Flickr’s optimistic committing

Somewhere next to optimistic loading and optimistic saving exists another technique to make apps feel faster: optimistic committing. Flickr is a great example. After navigating to photo upload, you enter a sort of a foyer where you can drag in the photos, reorder them, name and tag them, and otherwise prepare them before pressing the big Upload button. But Flickr also optimistically assumes you will press that button, and slowly starts uploading the heavy photos in the background the moment you drag them in. Like all optimistic schemes, being friendlier toward the user complicates things for Flickr’s designers and engineers. After all, there is still a regular upload modal after you do commit to the upload… = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/flickrs-optimistic-committing/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/flickrs-optimistic-committing/2.1600w.avif" type="image/avif"> …so the two states – quiet staging area upload, and the official visible upload – have to be reconciled and kept in sync. Also, optimistic but eventually cancelled uploads have to be cleaned up from the servers. Lastly, there’s signposting. Contrary to lighter optimistic loading schemes, which typically simplify reality by pretending no data transfer is actually happening, the optimistic committing here is actually visible through small indicators: I think this transparency is welcome. In the past, Meta (who else!) got into hot water for abusing optimistic committing : Did you ever record a video on Facebook to post directly to your friend’s wall, only to discard the take and film a new version? You may have thought those embarrassing draft versions were deleted, but Facebook kept a copy. The company is blaming it on a “bug” and swears that it’s going to delete those discarded videos now. They pinkie promise this time. In this context, it’s good that Flickr conveys data is being sent to the servers; I believe this helps with building trust. On top of transparency, I think it’s also good that this process shows the progress of uploading with a lot of precision – not just between files, but also within each file. Internet connection speeds vary so much, not just geographically, but also even situationally, that this is really helpful in practice. There are many moments where auto saving to the cloud needn’t bother the user unless the connection goes offline for a longer while, but this feels like a situation where clarity is better than magic. #details #loading states

0 views
James Stanley 3 days ago

Optimistic epsilon-greedy

I've been working on optimising revenue on my Countdown website the last few days. I have had a Countdown solver tool online since about 2009. It is to this day the most popular website I have ever made, it currently gets about 70,000 pageviews per month. The site has been earning revenue from AdSense for years. Up until last week the site was just 2 static HTML pages: one for the Countdown Solver and one for the Countdown Practice game. That didn't give me much opportunity to run experiments on the site, and I never really had the inclination to try. It was basically a web program . But now, LLMs to the rescue. I now have a Python Flask application serving the site, and a lot more related information pages for people to read. And serving the site with an actual web application means I can run experiments like A/B tests to see if there are changes I can make to the site that cause people to stick around longer. And therefore look at more ads. A good alternative to A/B tests is multi-armed bandits . Instead of splitting your traffic equally between the different variants you want to try out, and then waiting to collect data, and then picking a winner, you have the site automatically determine the winner on a continuous basis, and show the winner 90% of the time (greedy), and a random selection the rest of the time (epsilon). I am using a multi-armed bandit to decide which "info" pages to suggest at the bottom of each page, and also to decide which Amazon Affiliate links to show. (Yes this is all very grubby, what can you do?). The "winner" is the choice that has the highest click-through rate. So for each choice we need to track how many times we've displayed it, and how many times it's been clicked on. If your reward function is more complicated you might find it more complicated. Steve Hanov's blog post on multi-armed bandits, linked above, goes over the case where you might worry that a particular variant gets a click early, just by random chance, which gives it an apparent high click-through rate, which then means the site is going to show that variant to everyone. And that's not actually a big deal, because showing the apparently-high-performing variant to 90% of traffic gives it a lot of opportunities to prove that it's not actually that good, and it's click-through rate will come back down. A much bigger issue, in my opinion, is when you add a new variant. Let's say you already have 9 variants that all have click-through rates around 1% and have had about 1000 views each. Then you add a new variant. This new variant starts out with 0 clicks. Now you have 10 variants, 9 of which have a CTR of 1% and your new one has a CTR of 0% (technically a degenerate case with 0 views, but becomes firmly 0% after the first view). And let's say your site expects 1000 views per day. 90% of the time your site is going to be showing one of the old variants, because no matter what happens to their CTRs, they can't go below 0% , so they will forever look better than your new variant. The remaining 10% of the time your site is going to be picking at random amongst all variants. So your new variant is going to get about 1% of your traffic. Or 10 views per day. If your new variant also has a CTR of about 1%, then you'll expect to get about 1 click per 100 views. If it is only getting 10 views per day then it could easily be 10 days before you get the first click, during which time you're not even gathering much data on it. So what I'm doing instead is defining the CTR to be (clicks+1)/(views+1) . That is, we always optimistically assume that the next view is going to get a click. That means a new variant starts out with a CTR of 1/1 = 100% . We skew the selection towards those variants that have not had many opportunities to prove themselves yet. In this case the new variant will get 91% of the traffic until its optimistic-CTR falls below that of the next best variant. That could easily happen within the first day of releasing the new variant, so this "optimistic epsilon-greedy" algorithm broadly behaves exactly the same once the number of views is high enough, but it discovers the true CTR for newly-added variants much more quickly than the standard algorithm. Even if the new variant actually never generates any clicks, its CTR drops below 1% within about 100 views ( 1/101 ) so it won't be taking much traffic away from your older variants if it doesn't work very well.

0 views

Establishing an Identity

If you’ve followed me on RSS for any amount of time, first off, thank you so much! Second, you may not have noticed how often this site changes. RSS protects you from the near-monthly changes that my mad scientist side makes to this site. This year alone, ThatAlexGuy.dev has been powered by 11ty, Hugo, plain HTML, Bear, Micro.blog , and Pure Blog. My files have sat on OpenBSD Amsterdam, DigitalOcean, and a Laravel Forge VPS. I’ve written new articles and lost old articles in migrations. My site has switched appearance more frequently than a Bian Lian (变脸) performer! I’ve come to realize I’ve been seeking both an identity and a voice. I want an outlet that reflects my interests, my background, and my day-to-day, but that’s more than what I could accomplish on something like Mastodon. All that brings us here, iteration 4 (or 8, or 15, or 16, I can’t remember). There are a few key differences and intentional choices that reflect where I want ThatAlexGuy to go. Building a new experience that will stick and satisfy the goals in my head won’t be easy, but here are the guiding pillars that are to shape what’s coming next. I have a desire to create in-depth, well-researched, and potentially interactive content. Many of my current posts come with a “1-minute read” tag. I want to change that. I’ll be digging into topics with greater detail, cross-referencing multiple sources, and (hopefully) interviewing others. As a result, I’ll be posting less frequently, but my new goal is quality over quantity. Regulars on my site will be aware of my “Photo Journal” series in which I posted a set of photos around a theme (macro, nature, Gameboy Camera ). I want to continue building my photography skills through the incorporation of high-quality photos in my articles. While text sets the tone, visuals set the atmosphere in an article. Here’s the big tomato, as they say (nobody says that): defining what this site represents. That means setting the tone and defining how topics string together to form a consistent narrative. I’ll be figuring this out for a while, but I want to leverage my interests such as indie technology, vintage computing, time away from the screen, photography, and Chinese culture. So what’s changed so far? Quite a bit! First, ThatAlexGuy.dev is now run by Ghost.org . For myself, this means less time in the technical weeds and more focus on writing. For readers, it opens the doors to a wider audience. Email newsletters are a more accessible way to stay up-to-date on new articles. Don’t worry though, RSS isn’t going anywhere! In fact, I managed to fix the broken RSS feed URLs from previous migrations (hopefully)! I’ve started to define the personality of the new site. I pulled background and accent colors from one of my favorite atmospheres in a game (Sprout Tower in Pokémon Gold). Using my iPad, I’ll be creating article images that give a calligraphy + hand-painted vibe. I’ve also brought in my Chinese name for the logo(小艾 - Little Alex). I’m working on my first longer-form article. It probably won’t be great, but first attempts never are. From there, I hope to refine my writing, researching, and supporting photography.

0 views
David Bushell 6 days ago

Astro is fine I guess

When I’m not fighting WordPress I deliver static HTML or the occasional JavaScript framework integration. For personal projects I have ‘fun’ with my own static site generator . This week was a side quest (soon to be main quest) to build my new company website. We’re talking proper business here so I can’t be messing about. I figured an off the shelf SSG would be most suitable. I asked the socials, “ 11ty or Astro ?” Both are popular but Astro had the edge. I gave Astro an early spin back in 2022 and found it slow . Maybe it’s good now? I ran with minimum release age to avoid immediately getting pwned . I selected Astro’s “Use minimal (empty) template” option and it generated both an and file — are you f — deep breaths, don’t fall for the rage bait. I code in a modern editor so I installed the recommended Astro extension. At first I struggled with Zed recognising HTML. I discovered a restart temporarily fixed the issue, but I guess I restarted one time too many because now the Astro LSP is completely broken. No modern comforts for me then. At least I can look at HTML without the red squigglies. I know what you’re going to say, “Dave bro, you’re inflicting this pain upon yourself! Just write HTML!” And I should. I just want native no-framework HTML includes , you know? Can you imagine the civilisation we’d live in if that could happen? I persevered and got my templates built with minimal fuss. I added a markdown collection and got the blog part blogging. It’s obvious that people use Astro to build real websites because all my “how do I” questions had an answer in the documentation. I’ve been forced to deploy way too many “React spaces” in my templates because Astro’s whitespace treatment is a mystery. I don’t need many components so I haven’t gone deep on Astro vs JSX . My site has zero JavaScript on the front-end. I plan to keep it that way. Edit: Christian Niklas on Mastodon shared a link to a recent Astro update where they added a option that defaults to no longer “following HTML rules.” Umm… okay. Set this to or if you’re building a website? I set it to . Minifying whitespace is over-optimisation. Astro has got the job done, despite the developer experience being broken out of the box. I dread to think what graveyard of dotfiles is installed if I choose a non-minimal start. I can easily de-Astro my templates should I need to. Right now Astro is solving the right problems and the issues are but a nuisance. Final conclusion: Astro is fine I guess. I’m not convinced Cloudflare’s acquisition is a good thing, considering their record for performative slop. I’ve lost my enthusiasm for DX and tooling to be honest. Even my own SSG experiments are collecting dust. I’d call the ecosystem a lost cause if I was being dramatic. I just try to avoid the worst of it and care about the end product: shipping a damn fine website! Which I can’t do because I’ve got more businessing to business before this particular site sets sail. Maybe in a few months? It’s looking awesome on though. Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds.

0 views

Go have fun with the web

Back in the days of Geocities, I spent a lot of time hacking away on raw HTML and CSS. I enjoyed tweaking things, making it just right and experimenting with random ideas I had. I’d sketch things out, then turn them into a close(ish) version on the web. “Under construction” gifs would hide my unlinked, mad scientist HTML files. As I grew older, the idea of “hustle” culture slowly killed out this mindset. Instead of having fun, I felt everything I do on the web had to serve a purpose. If I wasn’t building something that might make money, I was wasting my time. And guess what? In 15ish years of operating under that mindset, I’ve made maybe $500 online. Pretty terrible investment if you ask me. I’m willing to bet I’m not alone in this mindset, it seems embedded into the millennial DNA. We’ve grown up with stories of dot com entrepreneurs making it big while sipping Mojitos on the beaches of Chiang Mai. You’re always just a few more late nights from quitting your job, joining NomadsList and traveling the world! The truth is, you’d probably have a better chance winning the lottery, so why waste your time chasing the impossible? Why turn an artistic, creative outlet into a second job that doesn’t put food on the table? Embrace the web as a hobby. Like pencils, paintbrushes and clay, the web is a way to give “physical” form to the images in your head with HTML, CSS and JavaScript. When you stop building for scale, potential customers and imagined profit, you free yourself to have fun. Build silly, build simple and above all else, build for the sake of creativity.

0 views
Kev Quirk 1 weeks ago

Built for Exactly One

by Amit Gawande Amit talks about what motivated him to build his custom blogging platform, Jot. It's an interesting read that resonated with me as it aligns with why I created Pure Blog. Read post ➡ A month ago, this website moved to a custom engine that I built myself, one I call Jot. Why did I create it? Because I got tired of almost. Almost the right editor. Almost the right publishing flow. Almost the right feature set. -- Amit Gawande This is exactly why I started building Pure Blog , but the difference here is that I decided to publish it for everyone to use. Before doing so, I considered many of the same questions that Amit talks about in his post - I was concerned that the project would morph into a product for everyone , not just me. Ironically, it's been exactly 5 months since I introduced Pure Blog and since then I've done a shit tonne of work to it. But that wasn't driven by the people who use it. It was driven, almost exclusively, by me. Lots of people have contributed to Pure Blog, but there's hasn't been a single feature I've added that I won't get use from. Actually, that's a lie. The only feature I've added that I wouldn't have if I'd kept Pure Blog private is translations . But I think that's fine, as it's the community who contribute those translations. Anyway, I digress. I'm happy to see other bloggers forging their own path - I'd love to get a look at Jot to see what it does differently to Pure Blog, and if there's anything I could copy improve upon. Maybe one day Amit will release the source code for us to look at, but if he doesn't, I don't blame him. As for my use of Pure Blog - it's by far the best thing I ever did from a blogging perspective. Everything is just how I want it, and in a place that makes sense to me. If others get use from it too ( and they do ) then all the better. But I'll keep developing Pure Blog in a way that makes sense to me. Congrats, Amit. Welcome to the club. Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
Unsung 1 weeks ago

About Unsung: Recent improvements

(This is one of the meta posts about this very blog . If that’s not interesting to you, skip to the next one!) Here are some improvements I’ve made to Unsung in recent months. Always curious of your feedback or pointers to places that do these things better! Weekly emails. I made it so clicking on every (non-YouTube) video or image takes you to the equivalent of the weekly email you’re looking at, but on the web, where you can watch the videos in their natural habitat. It’s scrolled to the right position, so you can just continue reading there. I’m sorry, I know it isn’t great to shove people outside of their mailbox, but I don’t think there is any way for videos to work well inside emails, and a lot of Unsung is about precise videos. (The only thing allowed is GIFs, and they are really not up to the task.) Video playback. On that note, I improved the handling and controls of video playback. On mobile, you can tap to play/​pause and swipe left and right to move. On desktop, you can drag the handle, or also swipe left/​right. You can also use ← → keys to advance frame by frame. My goals are to have video controls that are both minimalistic (for example, never covering the contents) and precise, to match how videos are used here. (But if you tab to the video, it still shows “classic” controls for accessibility.) Blink comparators. You might have noticed that I added some blink comparators in a few posts where they seemed to be useful ( one , two , three , four ). Is that fun? Does it work for you? Because I have more ideas for light interactivity on Unsung. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/about-unsung-recent-improvements/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/about-unsung-recent-improvements/2.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/about-unsung-recent-improvements/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/about-unsung-recent-improvements/3.1600w.avif" type="image/avif"> Technical details. Some people asked technical details about specific things on this blog, so I added a technical details page with answers. Dashboard. If you are interested in that kind of stuff, I added some more charts and stats to Unsung’s internal dashboard (and deprecated sentiment, which wasn’t really working). #about unsung

0 views
Unsung 1 weeks ago

“The root of all margin-collapsing evil”

I liked this page I just learned of called Incomplete List of Mistakes in the Design of CSS . It might not mean much to you if you don’t write CSS, but could be fun to check out if you do. Here are some choice quotes: It reminded me of a similar list called Known Anomalies in Unicode Character Names . Here’s one example: U+02C7 CARON U+030C COMBINING CARON The “caron” should have been called hacek and combining hacek . The term “caron” is suspected by some to be an invention of some early standards body, but it has also been claimed by others to have been in use at Linotype before the days of digital typography. Its true origin may be lost in the mists of time. These are great because they simply say “this is how we messed up.” They are succinct and candid about problems. More work needs to be done at this point, of course – the CSS list only really contains the “simple,” low-level observations, and I think for both CSS and Unicode fixes cannot simply be made because people and systems rely on the existing behaviour – but the first step is admitting you have a problem, right? If you’re on the outside, it can be comforting to realize “oh, it wasn’t just me, other people don’t like this, too.” (Scanning bug reports from other users can help in a similar way.) If you’re on the inside, consider making a list like this for a long-standing project. It might do you or your team good! If you are aware of more documents like these, I’d love if you could send them over. #bugs #change management #process should have been . It shouldn’t be — that reads to engineers as “not important”. We should have picked another way to write this. should be .

0 views
The Jolly Teapot 1 weeks ago

A peculiar bug in Safari

On weekend mornings, I have the inescapable habit of looking at my website and seeing what I can change, what I can remove, what I can improve in terms of HTML, CSS, layout, links, etc. This Saturday, as I wanted to look closer at the way the period at the end of a sentence rendered when appearing just after a word in italic (I know), I noticed something curious. When I zoomed in the page, using “Command – Plus Sign” (⌘+), I could see that the line length was changing with the size of the text. The bigger the text, the longer the line. You see, I’m very protective of the I use on this site —  — especially for Mac users, who see it in the Charter font. *1 This value sets an ideal number of characters for each line making it, when paired with the right line height, easier to read (supposedly). Zooming in on text shouldn’t change the line length, so I looked around and realised that I was a bit clueless when it comes to identifying bugs, and even checking if they were already reported. I found a few bug reports related to zooming in, but none of them described my issue. Not only that, but I didn’t really know if this was a Webkit problem, or a Safari problem. So instead of working my way to either confirming an existing bug or filing a new one , I did what I usually do when facing a problem: I avoided it altogether rather than trying to solve it. Therefore I changed to in my CSS, resulting in a similar line length for Charter. *2 With as the unit, zooming doesn’t modify the line length, so I’m pretty happy with this easy fix. Bonus point: takes up the same number of bytes as in my default CSS, still capped at 132 bytes. Imagine the extra-byte horror if I had to use something like or ? It would have ruined my sunny Saturday morning. This little website update made me realise something: my site design is pretty much done, and I hadn’t changed anything for a few weeks or even months. I actually miss the satisfaction of changing something at the end of my little routine. Checking every detail on every page, revisiting every line of code just to see what can be improved, even if it’s just removing extra quotation marks in an attribute or an optional closing tag, is not as fun when there is nothing to do at the end. I really like my site’s current design, and even if there might be a few tiny tweaks like this one in the future, I feel that the overall look and feel is pretty much final. It’s a weird feeling, but now I have no excuse for not writing more, and publishing more posts, even if they are unfinished , or shorter than usual . For others, falling back to the default serif, usually Times New Roman, is indeed a bit narrow; or would be better, but it’s too wide for Charter.  ^ For the serif/Times New Roman fallback, creates a slightly longer line, which is atually better than what it was with .  ^ For others, falling back to the default serif, usually Times New Roman, is indeed a bit narrow; or would be better, but it’s too wide for Charter.  ^ For the serif/Times New Roman fallback, creates a slightly longer line, which is atually better than what it was with .  ^

0 views
David Dodda 1 weeks ago

Why Don’t Websites Put All Their Images Into One Giant JPEG? (Nerd-Sniped by My Brain)

I had a simple question: Why do websites load lots of individual images instead of stitching them into one giant image and cropping out the pieces they need? At first glance, an image atlas sounds great. Instead of this: You create this: Then each UI tile crops a specific region from the atlas. That would mean: fewer network requests images arrive together no staggered popping maybe better perceived loading maybe less request overhead Not a new idea by any means. Games and UI libraries have used sprite sheets and texture atlases forever. The question is: why isn’t this the default for websites? I compared three approaches: Individual optimized images 14 separate optimized JPG files rendered as normal elements Canvas atlas one stitched atlas JPG each tile rendered by cropping from the atlas into CSS background atlas one stitched atlas JPG each tile rendered with , , and The atlas was regenerated from the same optimized images, so the comparison was more fair. NOTE: I ran the experiment by hosting it locally. so all the number you see are when you have the application served using a python server running locally. If you want to poke at it yourself, the experiment is live here: https://daviddodda.com/experiments/img-atlas/ note: make sure you disable cache. try each version a couple of times. I focused on three headline metrics. How many bytes were downloaded? When did the last required image resource finish downloading? When was the image grid actually ready to see? This last one matters because network completion is not the full story. The browser still has to decode images, rasterize, paint, composite, and show pixels. On a remote machine running Chromium, all files hosted locally, 10 runs each: The surprising result: The CSS background atlas was the fastest to visible. The atlas had a clear network advantage: Well, one larger request has less overhead than many smaller requests. This effect is especially visible when the server/browser are using less optimal connection behavior. In my test, Chromium reported for the local server, so request overhead was more obvious than it would be under HTTP/2 or HTTP/3. With modern HTTP/2 and HTTP/3, many individual image requests are less painful because requests can be multiplexed over one connection. But request overhead still exists. The individual images transferred: The regenerated atlas transferred: Because an atlas is a rectangle. Real images have different aspect ratios. When you pack them into one big rectangular sheet, you often create empty space. In my case: That is about 31% extra pixel area. So even though the atlas used one request, it transferred more data and required the browser to decode a bigger image surface. The canvas atlas looked like it should be fast (thought modern hardware was fast enough). It loaded one atlas image, then cropped each tile into a canvas. But the results were poor: The breakdown showed: The actual JavaScript canvas drawing was not expensive. The expensive part was making all those canvas results visible. That means the bottleneck was not: It was the browser’s later paint/composite work. The CSS background atlas used normal DOM elements: This was much faster: The breakdown: The decode cost was still there. But paint/composite was dramatically better than the canvas version. So if you are going to do image atlasing in normal web UI, CSS backgrounds may be much better than drawing many cropped canvases. They are great for: emoji sheets game textures small repeated UI assets known fixed-size tile sets maps or tile-like interfaces cases where all assets are needed immediately They are less great for: photo galleries blog images user-generated content responsive images content-heavy websites long scrolling pages frequently changing assets now, don't go getting any ideas about rewriting your website's image pipeline to use image atlas. here are some reason why it's a really bad idea. With individual images, the browser can load only what is needed: With a giant atlas, loading one image means loading everything in that atlas. That is great if you need everything immediately. It is terrible if the user only sees 5% of the images. The web has powerful responsive image tools: The browser can choose the right image for the device, viewport, DPR, and network. With a giant atlas, this becomes much harder. You may need multiple atlases: The combinatorial complexity gets ugly quickly. Atlases require packing. Packing creates waste. If the images have different shapes, the atlas may contain a lot of empty or unused area. Even a good packing algorithm cannot always avoid this. In my test, the atlas had about 31% more pixel area than the individual images. With individual images: Only that image needs a new URL/cache entry. With an atlas: The whole atlas cache is invalidated. That is bad for websites where content changes often. Browsers are good at prioritizing resources. The hero image can be high priority. Below-the-fold images can be lazy. Tiny thumbnails can wait. With a giant atlas, everything has one priority. You cannot easily say: The atlas is all-or-nothing. A compressed JPG might be 2 MB on the network, but decoded pixels are much larger. Decoded RGBA memory is roughly: A large atlas can become a huge decoded surface. In my first broken atlas attempt, the atlas was: That is around: Even if the file downloads quickly, that is a lot for the browser to decode, rasterize, and paint. An has natural semantics: A CSS background image is decorative by default. If the image is meaningful content, you need to rebuild semantics with ARIA or hidden text. That is doable, but it is extra work and easier to get wrong. Browsers have spent decades optimizing: If you use an atlas, you bypass some of that machinery and take on more responsibility yourself. Sometimes that is worth it. Often it is not. Every approach has its niche use case (shocker). My brain nerd-sniped me into exploring and writing about this. It was fun seeing the cute animals load in though. fewer network requests images arrive together no staggered popping maybe better perceived loading maybe less request overhead Individual optimized images 14 separate optimized JPG files rendered as normal elements Canvas atlas one stitched atlas JPG each tile rendered by cropping from the atlas into CSS background atlas one stitched atlas JPG each tile rendered with , , and emoji sheets game textures small repeated UI assets known fixed-size tile sets maps or tile-like interfaces cases where all assets are needed immediately photo galleries blog images user-generated content responsive images content-heavy websites long scrolling pages frequently changing assets

0 views
Nicky Reinert 1 weeks ago

9 – Simple, Secure Browser-Based Text Sharing

9 is a free, anonymous, browser-based tool that sends text directly between two devices via encrypted WebRTC – no server, no signup.

0 views
Unsung 2 weeks ago

“That’s a big number – by almost any scale other than Google’s.”

Thirteen years ago today, Google killed Google Reader. In 2023, The Verge wrote a great piece about the shutdown : Google’s feed-reading tool offered a powerful way to curate and read the internet and was beloved by its users. Reader launched in 2005, right as the blogging era went mainstream; it made a suddenly huge and sprawling web feel small and accessible and helped a generation of news obsessives and super-commenters feel like they weren’t missing anything. It wasn’t Google’s most popular app, not by a long shot, but it was one of its most beloved. In the essay, Google Reader is presented as a victim of Google+. I was at Google when Google+ was announced and can corroborate the feeling of an end of an era at the company. The first large internal presentation was a shell shock: the arrival of secrecy, bureaucracy, corporate delusion, inevitable sycophants following not-so-inevitable bozos. But perhaps it was the opposite – Google as a company would have changed anyway, and Reader just randomly ended up being among the early beloved things that stood in the way. (I mean, arguably, Google changing for the worse destroyed even Google Search since.) I am worried about the open web , but excited seeing some resurgence in RSS usage, and more and more people wanting to come back to the feeling of control, care, and intentionality that using Reader represented. Just a few months ago, Roger Wong found himself reflecting on Reader, too : What gets me is that the vision Wetherell drew on that whiteboard—a single place to follow everything you care about, organized by your taste, shared with people you trust, and non-algorithmic—still doesn’t fully exist. RSS readers are the closest thing we have, and they’re good enough that I’ve built my entire reading and writing practice around one. But the curation layer Wetherell imagined is still unfinished. I’m introducing a new tag to Unsung, software eulogies , which right now encompasses Aperture and Reader. One has to be careful about nostalgia since it has its own gravity and can corrupt as much as a runaway World of WarCraft virus . “They don’t make them like they used to” is a potent drug that can make us disinvested in shaping the future, but it is also true that, well, we don’t make software like we used to. Part of Unsung is about finding inspiration in history, and while each one of us can miss a certain era of computing, certain machines, and certain software for whatever reasons we choose to – healthy or not – I do believe we collectively miss Aperture and Reader for the right reasons that are worth listening to. #google #software eulogies #software evolution #web

0 views
Unsung 2 weeks ago

“The evilest will-breaking browser game to exist.”

In 2023, Neal Agarwal created The Password Game , a viral browser-based game. Wikipedia has a nice summary: Although the initial requirements include setting a minimum of characters or including numbers, uppercase letters, or special characters, the rules gradually become more unusual and complex. These can involve managing having Roman numerals in the string to multiply, adding the name of a country that players have to guess from random Google Street View imagery (as a reference to GeoGuessr), inserting the day’s Wordle answer, typing the best move in a generated chess position using algebraic notation, inserting the URL of a YouTube video of a randomly generated length, and adjusting boldface, italics, font types, and text sizes. The explanation goes on for another paragraph, but I don’t want to spoil too many surprises. However, if you’re not a puzzle kind of person, you can just watch a 40-minute video of Bog trying to beat it : = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt1-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt1-play.1600w.avif" type="image/avif"> Last year, Agarwal followed The Password Game with I’m Not A Robot game , making fun of similarly onerous CAPTCHA requirements. Here’s Bog completing it once again – and you can also find other YouTube creators doing the same for both games: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt2-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt2-play.1600w.avif" type="image/avif"> In the same category, a game designer Linternet User just launched a teaser for their game CAPTCHA Hell , which has a different take and looks fun: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt3-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/the-evilest-will-breaking-browser-game-to-exist/yt3-play.1600w.avif" type="image/avif"> I need to add that underlying all of this “fun” is not just tons of frustration with passwords and CAPTCHAs, but also a genuine accessibility problem, as described by Robin Christopherson in 2019 in an article titled AI is making CAPTCHA increasingly cruel for disabled users , or by A11y Collective a few years later. I don’t know what is the absolute latest in the battle with AI bots; anecdotally, I have been seeing almost zero text CAPTCHAs and less visual CAPTCHAs, at the expense of more and more CloudFlare turnstiles (and Google’s equivalent ), which make you only click the button, and do a lot of work under the hood to determine if that button press felt human-y or robot-y: These challenges include proof-of-work (computational puzzles), proof-of-space, probing for web APIs, and various other challenges for detecting browser-quirks and human behavior. As a result, we can fine-tune the difficulty of the challenge to the specific request and avoid showing a visual or interactive puzzle to a user. There is no more explanation. I think the nature of the beast is that the actual details of how to tell one group from another cannot be shared, which is a shame – I’m very curious. #games #security #youtube

0 views
Unsung 2 weeks ago

“Invalid-reverse-solidus validation error”

In my three decades online, it has never occurred for me to try this, and I found it so delightful once I did – both Chrome and Firefox will quietly rewrite backslashes in URLs into slashes: Not Safari, however, even though the URL living standard says it should . I am very curious if the presence of backslashes in URLs is owing to Windows still showing backslashes in file paths, or just because people casually don’t see any difference between / and \, which are arguably both similar, and relatively alien in everyday typography. (“Solidus” is the proper typograpical name for this kind of a slash, partly to disambiguate it from all the other slashes with their equally fascinating names .) = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/invalid-reverse-solidus-validation-error/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/invalid-reverse-solidus-validation-error/2.1600w.avif" type="image/avif"> #keyboard #typography #web

0 views
Simon Willison 2 weeks ago

Have your agent record video demos of its work with shot-scraper video

shot-scraper video is a new command introduced in today's shot-scraper 1.10 release which accepts a file defining a routine to run against a web application and uses Playwright to record a video of that routine. I've written before about the importance of having coding agents produce demos of their work; this is my latest attempt at enabling them to do that. Here's an example video created using , exercising a still in development feature adding the ability to create new tables in Datasette from pasted CSV, TSV or JSON data: That video was created by running this command : (That JSON file contains a cookie , as described here in the documentation.) Here's the file: The video command documentation includes simpler examples, but for the purpose of this post I thought I'd go with something more comprehensive. That demo YAML storyboard was constructed entirely by GPT-5.5 xhigh running in Codex Desktop, using the following prompt run inside my checkout of this branch : Now that I've released the feature the prompt could say " " instead and it should achieve the same result. I really like this pattern where the output for a command provides enough detail that a coding agent can use it - it works kind of like bundling a file directly inside the tool. I used the same pattern for showboat and rodney . started as an experimental prototype. is built on top of Playwright , and the key feature it needed was for Playwright to be able to record video of browser sessions with enough control to create the desired demo. I first tried this a few years ago and found that the Playwright-produced videos included additional chrome that was useful for debugging a test failure but unwanted for a product demo. They fixed that a while ago, but there were still some minor blockers. In particular I was getting a few white frames at the start of the videos , since the recording mechanism kicked in before the first URL was loaded by the browser. Playwright 1.59 added a new screencast mechanism providing much more finely grained control over video recording. This was very nearly what I needed, but the resulting videos were fixed at 800px wide. I found a landed PR fixing that but it wasn't yet in a release. Then yesterday they shipped it in playwright-python 1.61.0 and I was finally unblocked to finish implementing the feature! The code itself was all written by GPT-5.5 xhigh in Codex Desktop. I had it write the documentation as well which gave me a very useful frame for reviewing the design - much of the iteration on the feature came from reviewing that documentation, spotting things that were redundant, inconsistent or confusing, and requesting (or dictating) a better design. The YAML format itself was mostly defined by the coding agent. I had it use Pydantic to both define and validate the format, partly to make the design easier to review. This is a great example of the kind of feature that I almost certainly wouldn't have taken on without coding agent support. I filed the original issue in February 2024, and had difficulty finding the necessary time to solve this in amongst all of my other projects. You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options .

0 views