Latest Posts (20 found)
Susam Pal 1 weeks ago

Childhood Computing

I recently stumbled upon a nice blog post titled Childhood Computing . It made me think about my own childhood computing experience. I am much older than the author of the aforementioned post but like them, I love computers too. I have for most of my life. When I was about eight years old, my parents decided to transfer me to a new school because of its curriculum. They did not know it then, and it probably did not even matter to them, but this new school had a computer lab. That was quite remarkable for its time. I grew up in a very tiny industrial town. The computers in the lab were hand-me-downs from the silica factory around which the town was built. We got only about two hours of time per month in the computer lab but the little time I got there opened up a whole new world for me. Before entering the lab, we had to leave our shoes at the door. 'These are expensive machines. We must keep them free of dust', our teacher would say. It was a ritual. The computers were very old IBM PC compatible machines, mostly with monochrome cathode-ray tube (CRT) monitors. They had no hard disks at all. They had a few hundred kilobytes of RAM. Every time, we performed the same ritual. Insert a 5¼-inch floppy disk to load MS-DOS into memory. Then insert another disk to load LOGO. Then write small LOGO programs and watch the turtle move. I have written more about that early LOGO programming experience here: FD 100 . Further, since there were no hard disks and storage was at a premium, nothing was ever saved. The moment you turned off the computer, all your work vanished. So saving a program meant literally writing the program down in a physical notebook. Since I got so little time with an actual computer, most of my Logo programming happened with pen and paper at home. I would 'test' my programs by tracing the results on graph paper. Eventually, I would get about thirty minutes of actual computer time in the lab to run them for real. One particular Logo program I still remember very well drew a house with animated dashed lines, where the dashes moved around the outline of the house. Everyone around me loved it, copied it and tweaked it to change the colours, alter the details and add their own little touches. That must have been my first 'free and open source software'. The 'licence' was 'do whatever you want but show me if you make any interesting modifications'. Occasionally, when we successfully completed the Logo programming exercises our teacher set us as challenges, he would let us play computer games too. The first computer game I ever played was Moon Bugs. Space Invaders, Bricks, Dangerous Dave and others were some of my other favourites. Space Invaders inspired me to write my own game but the little GW-BASIC programming I knew back then and the very limited access to computers I had then were insufficient to write anything more sophisticated than simple text-based input/output programs. But eventually, as an adult, I did manage to write an invaders-like game, which you can find here: Andromeda Invaders . Writing this game fulfilled a childhood dream! One of my buddies liked the game called Digger developed by Windmill Software. It soon became my favourite as well. The game came in a self-booting disk, so we did not have to go through the elaborate ritual of first inserting a floppy disk to load DOS. We could insert the Digger floppy disk directly and the computer would boot and start the game immediately. Another computer game I remember fondly was Grand Prix Circuit by Accolade. I really loved typing the command to launch the game, knowing that in a moment I will be greeted with its excellent opening music. Grand Prix Circuit blew my mind. As a child who only knew how to draw basic two-dimensional geometrical shapes with Logo and GW-BASIC, I found it astounding that a computer program could create a projection of a three-dimensional fictional world that you could navigate with keyboard inputs. How was it even possible, I wondered. It has been over 30 years since then, but the memories and the feelings still remain fresh in my mind. There are times when I can close my eyes and recall the buzzing sound of the dozen or so computers running in the lab, the beeps from the power-on self-tests (POST) and the distinctive, strangely pleasant smell of the closed, air-conditioned room. For some reason, that smell is one of the strongest memories I have from those days. I have never been able to describe it well, but once in a while I encounter it in very unexpected places, like a corridor somewhere, or a store, and it takes me right back to those early days of childhood computing. Those childhood computing experiences form some of my strongest and most vivid memories. They were such magical experiences, full of wonder and exploration. Read on website | #miscellaneous

0 views
Susam Pal 1 weeks ago

Don't Roll Your Own ...

This is going to be a rant about modern web design practices. But before I get to that, let me begin with a familiar principle from the world of cryptography. Among software developers, and especially among those who work on security-sensitive systems, there is a well-known maxim: Don't roll your own crypto. This does not mean that nobody is allowed to write cryptographic code. Someone has to. It means that, for ordinary production software that protects sensitive data of users, we should not rely on a private, unreviewed implementation that has not been vetted by the wider software development community. We should use established, vetted software packages or tools wherever possible. Fortunately, it is now standard industry practice to avoid rolling your own crypto and instead use cryptographic algorithms and packages that have been peer reviewed and stood the test of time. It wasn't so some twenty years ago. I have seen several flawed home-grown RC4 implementations early in my career, with issues like improper initialisation vectors, predictable keystreams and partial leakage of plaintext into ciphertext, putting sensitive data of users at risk. But today, major e-commerce websites or banks typically do not use home-grown cryptography for its web services. In fact, in regulated domains such as payments, healthcare and personal data processing, doing so could violate requirements for strong cryptography, possibly leading to hefty financial penalties. Website design is obviously not cryptography. A broken scroll bar is not the same kind of failure as a broken encryption scheme. But I wish there were a similar maxim for website design as well. There are many aspects of websites where, I think, developers should not be rolling their own X, especially when X is something browsers already do well and something users depend on every day. Here I present a list of such X. Of course, there are valid scenarios where you may need to roll your own X. But here I want to focus on the cases where you should not roll your own X, and how doing so can lead to a worse user experience, at least in my experience. I am not saying that nobody should ever build anything themselves. As someone who does a lot of creative computing myself and develops fun tools from time to time, I am a big proponent of developing your own stuff. But when it comes to developing user interface features for serious websites that people need to use to get their work done, I wish the software development community were more conservative in deciding what fancy feature goes into a website and what is left out. Do keep in mind that I am no expert in user experience. Far from it. So none of what I am saying here should be taken as a recommendation. But I am a user of the Web, and as a user, I have found some modern web design patterns to be frustrating. This post is a lament from one user of the Web, not a design guide. Of all the things I mentioned above, the one that bothers me the most is custom scroll behaviour on websites. I am used to how page scrolling responds to my mouse, touchpad or keyboard input. When you override the default scrolling behaviour of the web browser with your own implementation, it 'breaks' the page for me. The page now moves too slowly or too quickly when I scroll. Keyboard scrolling may or may not work. You take something I am so familiar with that I don't even think about it, and turn it into something unfamiliar that I now have to think about. Custom link navigation is another pet peeve of mine. Web browsers can already handle links very well. You could say that this is the whole reason web browsers even exist. Following links is their bread and butter. You shouldn't have to mess with that behaviour at all. If you think you need to, reconsider what you are trying to achieve and whether it is really so important as to disrupt normal link navigation. The worst offender I have found here is GitHub. When you click on a link on GitHub, say, a file link or an issue link, it triggers a massive piece of functionality implemented in JavaScript that handles the link click for you. If you don't believe me, visit your favourite project on GitHub using Firefox or Chrome, type F12 to open the browser's developer tools, then go to the 'Debugger' or 'Sources' tab, find 'Event Listener Breakpoints' on the right sidebar, expand 'Mouse' and select 'click'. Then click on a link on GitHub and see what happens. I'm sure I am not the only one who has noticed that, on GitHub, a clicked link sometimes takes too long to load. Ironically, it is often faster to open the link in a new tab than to wait for GitHub's JavaScript code to handle the navigation in the current tab. A custom password input field is another such hazard. Fortunately, custom password input fields have become rarer over the years. The password input field that comes with the web browser is generally well equipped to handle passwords. It can offer to save passwords, fill them in later and generate strong passwords for new accounts. It can also warn when a password is submitted over an insecure HTTP connection, work well with password managers and autofill, and cooperate with mobile keyboards and accessibility tools. If you replace the browser's password field with your own fake version, you may break all of that. You may also end up using an ordinary text field and masking it yourself, in which case the password may be treated by the browser, the operating system or assistive tools as ordinary visible text rather than as a password, thereby exposing the password in ways you did not intend. Custom date pickers are another common annoyance. I know that does not help you select a date range. But that is okay. You can provide two date input fields, one for the start date and one for the end date. I am willing to pay the small price of using two different inputs to select a date range if that means I can use my favourite web browser to navigate the calendar and select dates the same way everywhere. What I am less inclined to do is to learn ten different ways of using the date selector in ten different implementations across ten different websites. Right now the implementations of date selector are all over the place. Some require you to zoom out of the month view to enter a year view, where you can select years. While you are there, you cannot change the month again until you return to the month view. Some require you to click the previous-year button literally forty times to select your year of birth if you are old enough. Some do not let you type the date at all. No. I do not want to learn your calendar widget. I just want to use the date picker in my favourite browser, which is quite sane. Saner than your custom implementation. If you need to have a calendar widget to support browsers with inadequate native date-picker support, perhaps that support can be added alongside the native date picker rather than as a replacement for it. For example, the ordinary element could be left intact, with a custom widget provided in addition to it so that users can manipulate the same field. In general, just stop messing with the form controls. They almost always introduce new problems while solving some existing ones. And while you are at it, don't keep changing your website layout and interface every few months! I may adapt to the new design, but my ageing relatives cannot. For them, every time you change the user interface, it amounts to learning a whole new tool. If every website keeps doing this every few months, they have to spend a significant amount of time relearning familiar things for no functional benefit. Please just let them enjoy their retirement. Imagine how you would feel if a Linux distribution decided to redesign all its core commands and their command-line options every few months. Or imagine how you would feel if the buttons of your washing machine were rearranged every morning. It wouldn't be pleasant! Read on website | #web | #technology Don't roll your own page scrolling. Don't roll your own link navigation. Don't roll your own text selection. Don't roll your own context menu. Don't roll your own copy and paste. Don't roll your own password field. Don't roll your own date picker.

0 views
Susam Pal 2 weeks ago

Commenting Guidelines

When commenting on this website, please keep the following points in mind: You may include HTML or Markdown in your comment. Comments are converted to HTML and sanitised before they are published on this website. All submitted comments are held for review. Whether a comment is published or not is at the discretion of the author of this website. Typically, only the following types of comments are published: Generally, rants are not published, even when the post you are commenting on is itself a rant. This website is the author's place to rant. It is not your place to rant. If you really need to rant, please do so on your own website. This guideline exists to maintain a high signal-to-noise ratio in the comments section. All comments deemed suitable for this website by its author become publicly available on this website at two places: on the comment page for the article you commented on ( example ) and on the overall comment index page at comments . Read on website | #meta You may include HTML or Markdown in your comment. Comments are converted to HTML and sanitised before they are published on this website. All submitted comments are held for review. Whether a comment is published or not is at the discretion of the author of this website. Typically, only the following types of comments are published: Comments that add new information or insight to the topic discussed in an article. Comments that provide a neutral, supporting or opposing viewpoint. Comments that report typos, errors or bugs on the website. Comments that contain good humour. Comments that express appreciation. Generally, rants are not published, even when the post you are commenting on is itself a rant. This website is the author's place to rant. It is not your place to rant. If you really need to rant, please do so on your own website. This guideline exists to maintain a high signal-to-noise ratio in the comments section. All comments deemed suitable for this website by its author become publicly available on this website at two places: on the comment page for the article you commented on ( example ) and on the overall comment index page at comments . Do not submit sensitive personal data in your comments.

0 views
Susam Pal 2 weeks ago

The Problem of Pedagogy in Advanced Mathematics

It is a commonly held opinion that educational institutions could do more to improve the pedagogy of mathematics. This is especially true in school, when students are first exposed to new subjects. Poor exposition can turn students away from mathematics for a lifetime. Only the highly motivated ones continue to engage with the subject. This is very unfortunate because mathematics is a beautiful subject and it is filled with wonder. It also teaches rigour in reasoning, clarity of thought and the discipline of constructing arguments from first principles to obtain intricate and often beautiful results. What is perhaps less known is that pedagogy is a problem even for graduate-level mathematics students and professional mathematicians. The proofs in many graduate-level mathematics textbooks are, in my humble opinion, not really proofs at all. They are closer to high-level outlines of proofs. The authors simply do not show their work. The student then has to put in an extraordinary amount of effort to understand and justify each line. Sometimes a 10-line argument in a textbook might expand into a 10-page proof if the student really wants to convince themselves that the argument works. I am not a mathematician, but out of personal interest, I have worked with professional mathematicians in the past to help refine notes that explain certain intermediate steps in textbooks (for example, Galois Theory by Stewart, in a specific case). I was surprised to find that it was not just me who found the intermediate steps of certain proofs obscure. Even professional mathematicians who had studied the subject for much of their lives found them obscure. It took us two days of working together to untangle a complicated argument and present it in a way that satisfied three properties: correctness, completeness and accessibility to a reasonably motivated student. I don't mean that the books merely omit basic results from elementary topics like group theory or field theory, which students typically learn in their undergraduate courses. Even if we take all the elementary results from undergraduate courses for granted, the proofs presented in graduate-level textbooks are often nowhere near a complete explanation of why the arguments work. They are high-level outlines at best. I find this hugely problematic, especially because students often have to learn a topic under difficult deadlines. If the exposition does not include sufficient detail, some students might never learn exactly why the proof works, because not everyone has the time to work out a 10-page proof for every 10 lines in the book. Many good universities provide accompanying notes that expand the difficult arguments by giving rigorous proofs and adding commentary to aid intuition. I think that is a great practice. I have studied several graduate-level textbooks in the last few years, and while these textbooks are a boon to the world because textbooks that expose the subject are better than no textbooks at all, I am also disappointed by how inaccessible such material often is. If I had unlimited time, I would write accompaniments to those textbooks that provide a detailed exposition of all the arguments. But of course, I don't have unlimited time. Even so, I am thinking of at least making a start by writing accompaniment notes for some topics whose exposition quality I feel strongly about, such as s-arc transitivity of graphs, field extensions and related topics. Read on website | #miscellaneous

0 views
Susam Pal 3 weeks ago

I Will Not Add Query Strings to Your URLs

Last evening, a short blog post appeared in my feed reader that felt as if it spoke directly to me. It is Chris Morgan's excellent post I've banned query strings . Chris is someone whose Internet comments I have been reading for about half a decade now. I first stumbled upon his comments on Hacker News, where he left very detailed feedback on a small collection of boilerplate CSS rules I had shared there. I am by no means a web developer. I have spent most of my professional life doing systems programming in C and C++. However, developing websites and writing small HTML tools has been a long-time hobby for me. I have learnt most of my web development skills as a hobbyist by studying what other people do: first by viewing the source of websites I liked in the early 2000s, and later by occasionally getting possessed by the urge to implement a new game or tool and searching MDN Web Docs to learn whatever I needed to make it work. One problem with learning a skill this way is that you sometimes pick up habits and practices that are fashionable but not necessarily optimal or correct. So it was really valuable to me when Chris commented on my collection of boilerplate CSS rules. It helped me improve my CSS a lot. In fact, a few of the lessons from his comment have really stuck with me; I keep them in mind whenever I make a hobby HTML project: always retain underlines in links and retain purple for visited links. I have been following Chris's posts and comments on web-related topics since then. He often posts great feedback on web-related projects. Whenever I come across one, I make sure to read them carefully, even when the project isn't mine. I always end up learning something nice and useful from his comments. Here is one such recent example from the Lobsters story Adding author context to RSS . A couple of months ago, I created a new project called Wander Console . It is a small, decentralised, self-hosted web console that lets visitors to your website explore interesting websites and pages recommended by a community of independent personal website owners. For example, my console is here: susam.net/wander/ . If you click the 'Wander' button there, the tool loads a random personal web page recommended by the Wander community. The tool consists of one HTML file that implements the console and one JavaScript file where the website owner defines a list of neighbouring consoles along with a list of web pages they recommend. If you copy these two files to your web server, you instantly have a Wander console live on the Web. You don't need any server-side logic or server-side software beyond a basic web server to run Wander Console. You can even host it in constrained environments like Codeberg Pages or GitHub Pages. When you click the 'Wander' button, the console connects to other remote consoles, fetches web page recommendations, picks one randomly and loads it in your web browser. It is a bit like the now defunct StumbleUpon but it is completely decentralised. It is also a bit like web rings except that the community network is not restricted to being a cycle; it is a graph that can take any shape. There are currently over 50 websites hosting this tool. Together, they recommend over 1500 web pages. You can find a recent snapshot of the list of known consoles and the pages they recommend at susam.codeberg.page/wcn/ . To learn more about this tool or to set it up on your website, please see codeberg.org/susam/wander . In case you were wondering why I suddenly plugged my project into this post in the previous section, it is because I recently added a dubious feature to that project that I myself was not entirely convinced about. That misfeature is relevant to this post. In version 0.4.0 of Wander Console, I added support for a query parameter while loading web pages. For example, if you encountered midnight.pub while using the console at susam.net/wander/ , the console loaded the page using the following URL: This allowed the owner of the recommended website to see, via their access logs, that the visit originated from a Wander Console. Chris's recent blog post is critical of features like this. He writes: I don't like people adding tracking stuff to URLs. Still less do I like people adding tracking stuff to my URLs. ? Did I ask? If I wanted to know I'd look at the header; and if it isn't there, it's probably for a good reason. You abuse your users by adding that to the link. I mentioned earlier that I was not entirely convinced that adding a referral query string was a good thing to do. Why did I add it anyway? I succumbed to popular demand. Let me briefly describe my frame of mind when I considered and implemented that feature. When I first saw the feature request on Codeberg, my initial reaction was reluctance. I wasn't convinced it was a good feature. But I was too busy with some ongoing algebraic graph theory research, another recent hobby, with a looming deadline, so I didn't have a lot of time to think about it clearly. In fact, everything about Wander Console has been made in very little time during the short breaks I used to take from my research. I made the first version of the console in about one and a half hours one early morning when my brain was too tired to read more algebraic graph theory literature and I really needed a break. During another such break, I revisited that feature request and, despite my reservations, decided to implement it anyway. During yet another such break, I am writing this post. Normally, I don't like adding too many new features to my little projects. I want them to have a limited scope. I also want them to become stable over time. After a project has fulfilled some essential requirements I had, I just want to call it feature complete and never add another feature to it again. I'll fix bugs, of course. But I don't like to keep adding new features endlessly. That's my style of maintaining my hobby projects. So it should have been very easy for me to ignore the feature request for adding a referral query string to URLs loaded by the console tool. But I think a tired body and mind, worn down by long and intense research work, took a toll on me. Although my gut feeling was telling me that it was not a good feature, I couldn't articulate to myself exactly why. So I implemented the referral query string feature anyway. While doing so, I added an opt-out mechanism to the configuration, so that if someone else didn't like the feature, they could disable it for themselves. This was another mistake. A questionable feature like this should be implemented as an opt-in feature, not an opt-out feature, if implemented at all. The fact that I didn't have a lot of time to reason through the implications of this feature meant that I just went ahead and implemented it without thinking about it critically. As the famous quote from Jurassic Park goes: It soon turned out that my gut feeling was correct. After I implemented that feature, a page from one of my favourite websites refused to load in the console. To illustrate the problem, here are a few similar but slightly different URLs for that page: The first and second URLs load fine, but the third URL returns an HTTP 404 error page. The website uses the query string to determine which one of its several font collections to show. So when we add an arbitrary query string to the URL, the website tries to interpret it as a font collection identifier and the page fails to load. That is why, when my tool added the query parameter to the first URL, the page failed to load. Later, with a little time to breathe and some hindsight, I could articulate why adding referral query strings to a working URL was such a bad idea. Altering a URL gives you a new URL. The new URL could point to a completely different resource, or to no resource at all, even if the alteration is as small as adding a seemingly harmless query string. By adding the referral query string, I had effectively broken a working URL from a website I am very fond of. It is also worth asking whether an HTML tool should concern itself with referral query strings at all when web browsers already have a mechanism for this: the HTTP Referer header, governed by Referrer-Policy . That policy can be set at the server level, the document level or even on individual links. The Web standards already provide deliberate controls to decide how much referrer information should be sent. Appending referral query strings to URLs bypasses those controls. It moves a privacy and attribution concern out of the referrer mechanism and embeds it into the destination URL instead. I don't think an HTML tool should do that. There is also a moral question here about whether it is okay to modify a given URL on behalf of the user in order to insert a referral query string into it. I think it isn't. In the end, I decided to remove the referral query string feature from Wander Console. One might wonder why I couldn't simply leave the feature in as an opt-in. Well, the answer is that once I had deemed the feature misguided, I no longer wanted it to be part of my software in any form. The project is still new and we are still in the days of 0.x releases, so if there is a good time to remove features, this is it. But my ongoing research work left me with no time to do it. Finally, when the post I've banned query strings appeared in my feed reader last evening, it nudged me just enough to take a little time away from my academic hobby and devote it to removing that ill-considered feature. The feature is now gone. See commit b26d77c for details. The latest release, version 0.6.0, does not have it anymore. This is a lesson I'll remember for any new hobby projects I happen to make in the future. If I ever load URLs again, I'll load them exactly as the website's author intended. I will never add query strings to your URLs. Read on website | #web | #technology Wisdom on the Web Wander on the Web Broken URLs https://int10h.org/oldschool-pc-fonts/fontlist/ https://int10h.org/oldschool-pc-fonts/fontlist/?2 https://int10h.org/oldschool-pc-fonts/fontlist/?foo

0 views
Susam Pal 3 weeks 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
Susam Pal 1 months ago

Touch Typing Number Keys

I learnt touch typing about two decades ago when I was still at university. Although I took some typewriter lessons as a child, those lessons did not stick with me. It was at university, when I found a Java applet-based touch typing tutor on the web, that I really learnt to touch type. Since then, touch typing has been an important part of my computing life. I've sometimes read arguments on the web downplaying touch typing as a skill, with claims like 'typing isn't the bottleneck, thinking is'. While that may be true, I still consider touch typing a useful skill, since it makes writing documents, code and email feel much more fluid and pleasant. It's like playing a musical instrument with the correct technique, rather than simply getting by without it. One feels smooth and expressive and the other feels raw and laboured. Later in life, I also wrote a tool named QuickQWERTY so that I could share the joy of touch typing with my friends. The tool teaches typing only with the QWERTY layout. I wrote it at a time when I did not know much about the computing world, so I was not even aware that other keyboard layouts existed. As a result, only QWERTY is supported. The tool is free and open source, so motivated individuals can modify the lessons to support other keyboard layouts. Some people have indeed done so over the years. Several of my friends used this tool. I know at least a few who benefitted from it and shared similar sentiments about how touch typing made their computing experience smoother. Back in my university days, I had learnt a method in which the digits 1 and 2 are typed with the left little finger, 3 with the left ring finger and so on. In this approach, the digits 1 to 6 are typed with the left hand and 7 to 0 with the right. There is an alternative method in which only 1 is typed with the left little finger, 2 with the left ring finger and so on. In this approach, the digits 1 to 5 are typed with the left hand and 6 to 0 with the right. Both methods require typing 1 with the left little finger. I have often felt that this may not be the most efficient way to type 1 . The little finger is shorter than the others and reaching 1 often requires shifting the whole hand slightly diagonally upwards. I have therefore felt that using the left ring finger for 1 might be more comfortable. Last month, I trained myself to use the left ring finger to type both 1 and 2 . This goes against almost every typing guide out there, but I decided to forgo established practices and explore on my own to find what feels right. At first, I was sceptical about whether I would be able to learn this method, since it meant overcoming 20 years of muscle memory that I have relied on almost every day. However, developing the new muscle memory has been surprisingly easy. In fact, both the old and the new muscle memories now coexist and I can switch between them at will without much trouble. It is remarkable how the brain can store conflicting muscle memories so effortlessly. So far, I am finding this new way of typing 1 and 2 more comfortable than either of the two popular methods I described above. I will continue typing this way for the rest of this month and see how it feels. Read on website | #miscellaneous

0 views
Susam Pal 1 months ago

QuickQWERTY 1.2.2

QuickQWERTY 1.2.2 is now available. QuickQWERTY is a web-based touch typing tutor for QWERTY keyboards that runs directly in the browser. This release includes two important changes. First, a longstanding bug in the practice pane has been fixed. While practising a lesson, a 'Restart' link appears in the practice pane. Due to a bug, clicking it incorrectly sent users to Unit 1.1 instead of restarting the current lesson. The link now correctly restarts the active lesson. As before, QuickQWERTY continues to be available under the terms of the MIT licence. The latest version remains available on this website at quickqwerty.html . Read on website | #web | #programming

0 views
Susam Pal 1 months ago

Wander Console 0.5.0

Wander Console 0.5.0 is the fourth release of Wander, a small, decentralised, self-hosted web console that lets visitors to your website explore interesting websites and pages recommended by a community of independent website owners. To try it, go to susam.net/wander/ . The big feature in this release is a built-in console crawler. To try the console crawler, go to susam.net/wander/ > Console > Crawl . You should see an output like the following: The console crawler traverses the Wander network from the base console to find other consoles directly or indirectly reachable from it. If you have set up a Wander Console instance for yourself on your website, I recommend upgrading to the latest version to use this feature. It is fun to find out just how many Wander consoles belong to your neighbourhood. To upgrade, you only need to download the Wander Console bundle mentioned here and replace your existing Wander with the new one. If you own a personal website but have not set up a Wander Console yet, I suggest that you consider setting one up for yourself. You can see what it looks like by visiting mine at /wander/ . To set up your own, follow these instructions: Install . It just involves copying two files to your web server. It is about as simple as it gets. Read on website | #web | #technology

0 views
Susam Pal 1 months ago

Wander Console 0.4.0

Wander Console 0.4.0 is the fourth release of Wander, a small, decentralised, self-hosted web console that lets visitors to your website explore interesting websites and pages recommended by a community of independent website owners. To try it, go to susam.net/wander/ . This release brings a few small additions as well as a few minor fixes. You can find the previous release pages here: /code/news/wander/ . The sections below discuss the current release. Wander Console now supports wildcard patterns in ignore lists. An asterisk ( ) anywhere in an ignore pattern matches zero or more characters in URLs. For example, an ignore pattern like can be used to ignore URLs such as this: These ignore patterns are specified in a console's wander.js file. These are very important for providing a good wandering experience to visitors. The owner of a console decides what links they want to ignore in their ignore patterns. The ignore list typically contains commercial websites that do not fit the spirit of the small web, as well as defunct or incompatible websites that do not load in the console. A console with a well maintained ignore list ensures that a visitor to that console has a lower likelihood of encountering commercial or broken websites. For a complete description of the ignore patterns, see Customise Ignore List . By popular demand , Wander now adds a query parameter while loading a recommended web page in the console. The value of this parameter is the console that loaded the recommended page. For example, if you encounter midnight.pub/ while using the console at susam.net/wander/ , the console loads the page using the following URL: This allows the owner of the recommended website to see, via their access logs, that the visit originated from a Wander Console. While this is the default behaviour now, it can be customised in two ways. The value can be changed from the full URL of the Wander Console to a small identifier that identifies the version of Wander Console used (e.g. ). The query parameter can be disabled as well. For more details, see Customise 'via' Parameter . In earlier versions of the console, when a visitor came to your console to explore the Wander network, it picked the first recommendation from the list of recommended pages in it (i.e. your file). But subsequent recommendations came from your neighbours' consoles and then their neighbours' consoles and so on recursively. Your console (the starting console) was not considered again unless some other console in the network linked back to your console. A common way to ensure that your console was also considered in subsequent recommendations too was to add a link to your console in your own console (i.e. in your ). Yes, this created self-loops in the network but this wasn't considered a problem. In fact, this was considered desirable, so that when the console picked a console from the pool of discovered consoles to find the next recommendation, it considered itself to be part of the pool. This workaround is no longer necessary. Since version 0.4.0 of Wander, each console will always consider itself to be part of the pool from which it picks consoles. This means that the web pages recommended by the starting console have a fair chance of being picked for the next web page recommendation. The Wander Console loads the recommended web pages in an element that has sandbox restrictions enabled. The sandbox properties restrict the side effects the loaded web page can have on the parent Wander Console window. For example, with the sandbox restrictions enabled, a loaded web page cannot redirect the parent window to another website. In fact, these days most modern browsers block this and show a warning anyway, but we also block this at a sandbox level too in the console implementation. It turned out that our aggressive sandbox restrictions also blocked legitimate websites from opening a link in a new tab. We decided that opening a link in a new tab is harmless behaviour and we have relaxed the sandbox restrictions a little bit to allow it. Of course, when you click such a link within Wander console, the link will open in a new tab of your web browser (not within Wander Console, as the console does not have any notion of tabs). Although I developed this project on a whim, one early morning while taking a short break from my ongoing studies of algebraic graph theory, the subsequent warm reception on Hacker News and Lobsters has led to a growing community of Wander Console owners. There are two places where the community hangs out at the moment: If you own a personal website but you have not set up a Wander Console yet, I suggest that you consider setting one up for yourself. You can see what it looks like by visiting mine at /wander/ . To set up your own, follow these instructions: Install . It just involves copying two files to your web server. It is about as simple as it gets. Read on website | #web | #technology Wildcard Patterns The 'via' Query Parameter Console Picker Algorithm Allow Links that Open in New Tab New consoles are announced in this thread on Codeberg: Share Your Wander Console . We also have an Internet Relay Chat (IRC) channel named #wander on the Libera IRC network. This is a channel for people who enjoy building personal websites and want to talk to each other. You are welcome to join this channel, share your console URL, link to your website or recent articles as well as share links to other non-commercial personal websites.

0 views
Susam Pal 2 months ago

Wander 0.2.0

Wander 0.2.0 is the second release of Wander, a small, decentralised, self-hosted web console that lets visitors to your website explore interesting websites and pages recommended by a community of independent personal website owners. To try it, go to susam.net/wander . This release brings a number of improvements. When I released version 0.1.0, it was the initial version of the software I was using for my own website. Naturally, I was the only user initially and I only added trusted web pages to the recommendation list of my console. But ever since I announced this project on Hacker News , it has received a good amount of attention. It has been less than a week since I announced it there but over 30 people have set up a Wander console on their personal websites. There are now over a hundred web pages being recommended by this network of consoles. With the growth in the number of people who have set up Wander console, came several feature requests, most of which have been implemented already. This release makes these new features available. Since Wander 0.2.0, the file of remote consoles is executed in a sandbox to ensure that it has no side effects on the parent Wander console page. Similarly, the pages recommended by the network are also loaded into a sandbox . This release also brings several customisation features. Console owners can customise their Wander console by adding custom CSS or JavaScript. Console owners can also block certain URLs from ever being recommended on their console. This is especially important in providing a good wandering experience to visitors. Since this network is completely decentralised, console owners can add any web page they like to their console. Sometimes they inadvertently add pages that do not load successfully in the console due to frame embedding restrictions. This leads to an uneven wandering experience because these page recommendations occasionally make it to other consoles where they fail to load. Console owners can now block such URLs in their console to decrease the likelihood of these failed page loads. This helps make the wandering experience smoother. Another significant feature in this release is the expanded Console dialog box. This dialog box now shows various details about the console and the current wandering session. For example, it shows the console's configuration: recommended pages, ignored URLs and linked consoles. It also shows a wandering history screen where you can see each link that was recommended to you along with the console that recommendation came from. There is another screen that shows all the consoles discovered during the discovery process. Those who care about how Wander works would find this dialog box quite useful. To check it out, go to my Wander console and explore. To learn more about Wander, how it works and how to set it up, please read the project README at codeberg.org/susam/wander . Read on website | #web | #technology

0 views
Susam Pal 2 months ago

Git Checkout, Reset and Restore

I have always used the and commands to reset my working tree or index but since Git 2.23 there has been a command available for these purposes. In this post, I record how some of the 'older' commands I use map to the new ones. Well, the new commands aren't exactly new since Git 2.23 was released in 2019, so this post is perhaps six years too late. Even so, I want to write this down for future reference. It is worth noting that the old and new commands are not always equivalent. I'll talk more about this briefly as we discuss the commands. However, they can be used to perform similar tasks. Some of these tasks are discussed below. To experiment quickly, we first create an example Git repository. Now we make changes to the files and stage some of the changes. We then add more unstaged changes to one of the staged files. At this point, the working tree and index look like this: File has staged changes. File has both staged and unstaged changes. File has only unstaged changes. File is a new staged file. In each experiment below, we will work with this setup. All results discussed in this post were obtained using Git 2.47.3 on Debian 13.2 (Trixie). As a reminder, we will always use the following command between experiments to ensure that we restore the experimental setup each time: To discard the changes in the working tree and reset the files in the working tree from the index, I typically run: However, the modern way to do this is to use the following command: Both commands leave the working tree and the index in the following state: Both commands operate only on the working tree. They do not alter the index. Therefore the staged changes remain intact in the index. Another common situation is when we have staged some changes but want to unstage them. First, we restore the experimental setup: I normally run the following command to do so: The modern way to do this is: Both commands leave the working tree and the index in the following state: The ( ) option tells to operate on the index (not the working tree) and reset the index entries for the specified files to match the version in . The unstaged changes remain intact as modified files in the working tree. With the option, no changes are made to the working tree. From the arguments we can see that the old and new commands are not exactly equivalent. Without any arguments, the command resets the entire index to , so all staged changes become unstaged. Similarly, when we run without specifying a commit, branch or tag using the ( ) option, it defaults to resetting the index from . The at the end ensures that all paths under the current directory are affected. When we run the command at the top-level directory of the repository, all paths are affected and the entire index gets reset. As a result, both the old and the new commands accomplish the same result. Once again, we restore the experimental setup. This time we not only want to unstage the changes but also discard the changes in the working tree. In other words, we want to reset both the working tree and the index from . This is a dangerous operation because any uncommitted changes discarded in this manner cannot be restored using Git. The modern way to do this is: The working tree is now clean: The ( ) option makes the command operate on the working tree. The ( ) option resets the index as described in the previous section. As a result, this command unstages any changes and discards any modifications in the working tree. Note that when neither of these options is specified, is implied by default. That's why the bare command in the previous section discards the changes in the working tree. The following table summarises how the three pairs of commands discussed above affect the working tree and the index, assuming the commands are run at the top-level directory of a repository. The command is meant to provide a clearer interface for resetting the working tree and the index. I still use the older commands out of habit. Perhaps I will adopt the new ones in another six years, but at least I have the mapping written down now. Read on website | #technology | #how-to Experimental Setup Reset the Working Tree Reset the Index Reset the Working Tree and Index

0 views
Susam Pal 2 months ago

HN Skins 0.3.0

HN Skins 0.3.0 is a minor update to HN Skins, a web browser userscript that adds custom themes to Hacker News and allows you to browse HN with a variety of visual styles. This release includes fixes for a few issues that slipped through earlier versions. For example, the comment input textbox now uses the same font face and size as the rest of the active theme. The colour of visited links has also been slightly muted to make it easier to distinguish them from unvisited links. In addition, some skins have been renamed: Teletype is now called Courier and Nox is now called Midnight. Further, the font face of several monospace based themes is now set to instead of . This allows the browser's preferred monospace font to be used. The font face of the Courier skin (formerly known as Teletype) remains set to . This will never change because the sole purpose of this skin is to celebrate this legendary font. To view screenshots of HN Skins or install it, visit github.com/susam/hnskins . Read on website | #web | #programming | #technology

0 views
Susam Pal 3 months ago

Stories From 25 Years of Computing

Last year, I completed 20 years in professional software development. I wanted to write a post to mark the occasion back then, but couldn't find the time. This post is my attempt to make up for that omission. In fact, I have been involved in software development for a little longer than 20 years. Although I had my first taste of computer programming as a child, it was only when I entered university about 25 years ago that I seriously got into software development. So I'll start my stories from there. These stories are less about software and more about people. Unlike many posts of this kind, this one offers no wisdom or lessons. It only offers a collection of stories. I hope you'll like at least a few of them. The first story takes place in 2001, shortly after I joined university. One evening, I went to the university computer laboratory to browse the Web. Out of curiosity, I typed into the address bar to see what kind of website existed there. I ended up on this home page: susam.com . I remember that the text and the banner looked much larger back then. Since display resolutions were lower, the text and banner covered almost half the screen. I knew very little about the Internet then and I was just trying to make sense of it. I remember wondering what it would take to create my own website, perhaps at . That's when an older student who had been watching me browse over my shoulder approached and asked if I had created the website. I told him I hadn't and that I had no idea how websites were made. He asked me to move aside, took my seat and clicked View > Source in Internet Explorer. He then explained how websites are made of HTML pages and how those pages are simply text instructions. Next, he opened Notepad and wrote a simple HTML page that looked something like this: He then opened the page in a web browser and showed how it rendered. After that, he demonstrated a few more features such as changing the font face and size, centring the text and altering the page's background colour. Although the tutorial lasted only about ten minutes, it made the World Wide Web feel far less mysterious and much more fascinating. That person had an ulterior motive though. After the tutorial, he never returned the seat to me. He just continued browsing the Web and waited for me to leave. I was too timid to ask for my seat back. Seats were limited, so I returned to my dorm room both disappointed that I couldn't continue browsing that day and excited about all the websites I might create with this newfound knowledge. I could never register for myself though. That domain was always used by some business selling Turkish cuisines. Eventually, I managed to get the next best thing: a domain of my own. That brief encounter in the university laboratory set me on a lifelong path of creating and maintaining personal websites. The second story also comes from my university days. I was hanging out with my mates in the computer laboratory, in front of an MS-DOS machine powered by an Intel 8086 microprocessor. I was writing a lift control program in assembly. In those days, it was considered important to deliberately practise solving made-up problems as a way of honing our programming skills. As I worked on my program, my mind drifted to a small detail about the 8086 microprocessor that we had recently learned in a lecture. Our professor had explained that, when the 8086 microprocessor is reset, execution begins with CS:IP set to FFFF:0000. So I murmured to anyone who cared to listen, 'I wonder if the system will reboot if I jump to FFFF:0000.' I then opened and jumped to that address. The machine rebooted instantly. One of my friends, who topped the class every semester, had been watching over my shoulder. As soon as the machine restarted, he exclaimed, 'How did you do that?' I explained that the reset vector is located at physical address FFFF0 and that the CS:IP value FFFF:0000 maps to that address in real mode. After that, I went back to working on my lift control program and didn't think much more about the incident. About a week later, the same friend came to my dorm room. He sat down with a grave look on his face and asked, 'How did you know to do that? How did it occur to you to jump to the reset vector?' I must have said something like, 'It just occurred to me. I remembered that detail from the lecture and wanted to try it out.' He then said, 'I want to be able to think like that. I come top of the class every year, but I don't think the way you do. I would never have thought of taking a small detail like that and testing it myself.' I replied that I was just curious to see whether what we had learnt actually worked in practice. He responded, 'And that's exactly it. It would never occur to me to try something like that. I feel disappointed that I keep coming top of the class, yet I am not curious in the same way you are. I've decided I don't want to top the class anymore. I just want to explore and experiment with what we learn, the way you do.' That was all he said before getting up and heading back to his dorm room. I didn't take it very seriously at the time. I couldn't imagine why someone would willingly give up the accomplishment of coming first every year. But he kept his word. He never topped the class again. He still ranked highly, often within the top ten, but he kept his promise of never finishing first again. To this day, I feel a mix of embarrassment and pride whenever I recall that incident. With a single jump to the processor's reset entry point, I had somehow inspired someone to step back from academic competition in order to have more fun with learning. Of course, there is no reason one cannot do both. But in the end, that was his decision, not mine. In my first job after university, I was assigned to work on the installer for a specific component of an e-banking product. The installer was written in Python and was quite fragile. During my first week on the project, I spent much of my time stabilising the installer and writing a user guide with step-by-step instructions on how to use it. The result was well received and appreciated by both my seniors and management. To my surprise, my user guide was praised more than my improvements to the installer. While the first few weeks were enjoyable, I soon realised I would not find the work fulfilling for very long. I wrote to management a few times to ask whether I could transfer to a team where I could work on something more substantial. My emails were initially met with resistance. After several rounds of discussion, however, someone who had heard about my situation reached out and suggested a team whose manager might be interested in interviewing me. The team was based in a different city. I was young and willing to relocate wherever I could find good work, so I immediately agreed to the interview. This was in 2006, when video conferencing was not yet common. On the day of the interview, the hiring manager called me on my desk phone. He began by introducing the team, which called itself Archie , short for architecture . The team developed and maintained the web framework and core architectural components on which the entire e-banking product was built. The product had existed long before open source frameworks such as Spring or Django became popular, so features such as API routing, authentication and authorisation layers, cookie management and similar capabilities were all implemented in-house by this specialised team. Because the software was used in banking environments, it also had to pass strict security testing and audits to minimise the risk of serious flaws. The interview began well. He asked several questions related to software security, such as what SQL injection is and how it can be prevented or how one might design a web framework that mitigates cross-site scripting attacks. He also asked programming questions, most of which I answered pretty well. Towards the end, however, he asked how we could prevent MITM attacks. I had never heard the term, so I admitted that I did not know what MITM meant. He then asked, 'Man in the middle?' but I still had no idea what that meant or whether it was even a software engineering concept. He replied, 'Learn everything you can about PKI and MITM. We need to build a digital signatures feature for one of our corporate banking products. That's the first thing we'll work on.' Over the next few weeks, I studied RFCs and documentation related to public key infrastructure, public key cryptography standards and related topics. At first, the material felt intimidating, but after spending time each evening reading whatever relevant literature I could find, things gradually began to make sense. Concepts that initially seemed complex and overwhelming eventually felt intuitive and elegant. I relocated to the new city a few weeks later and delivered the digital signatures feature about a month after joining the team. We used the open source Bouncy Castle library to implement digital signatures. After that project, I worked on other parts of the product too. The most rewarding part was knowing that the code I was writing became part of a mature product used by hundreds of banks and millions of users. It was especially satisfying to see the work pass security testing and audits and be considered ready for release. That was my first real engineering job. My manager also turned out to be an excellent mentor. Working with him helped me develop new skills and his encouragement gave me confidence that stayed with me for years. Nearly two decades have passed since then, yet the product is still in use. In fact, in my current phase of life I sometimes encounter it as a customer. Occasionally, I open the browser's developer tools to view the page source where I can still see traces of the HTML generated by code I wrote almost twenty years ago. Around 2007 or 2008, I began working on a proof of concept for developing widgets for an OpenTV set-top box. The work involved writing code in a heavily trimmed-down version of C. One afternoon, while making good progress on a few widgets, I noticed that they would occasionally crash at random. I tried tracking down the bugs, but I was finding it surprisingly difficult to understand my own code. I had managed to produce some truly spaghetti code full of dubious pointer operations that were almost certainly responsible for the crashes, yet I could not pinpoint where exactly things were going wrong. Ours was a small team of four people, each working on an independent proof of concept. The most senior person on the team acted as our lead and architect. Later that afternoon, I showed him my progress and explained that I was still trying to hunt down the bugs causing the widgets to crash. He asked whether he could look at the code. After going through it briefly and probably realising that it was a bit of a mess, he asked me to send him the code as a tarball, which I promptly did. He then went back to his desk to study the code. I remember thinking that there was no way he was going to find the problem anytime soon. I had been debugging it for hours and barely understood what I had written myself; it was the worst spaghetti code I had ever produced. With little hope of a quick solution, I went back to debugging on my own. Barely five minutes later, he came back to my desk and asked me to open a specific file. He then showed me exactly where the pointer bug was. It had taken him only a few minutes not only to read my tangled code but also to understand it well enough to identify the fault and point it out. As soon as I fixed that line, the crashes disappeared. I was genuinely in awe of his skill. I have always loved computing and programming, so I had assumed I was already fairly good at it. That incident, however, made me realise how much further I still had to go before I could consider myself a good software developer. I did improve significantly in the years that followed and today I am far better at managing software complexity than I was back then. In another project from that period, we worked on another set-top box platform that supported Java Micro Edition (Java ME) for widget development. One day, the same architect from the previous story asked whether I could add animations to the widgets. I told him that I believed it should be possible, though I'd need to test it to be sure. Before continuing with the story, I need to explain how the different stakeholders in the project were organised. Our small team effectively played the role of the software vendor. The final product going to market would carry the brand of a major telecom carrier, offering direct-to-home (DTH) television services, with the set-top box being one of the products sold to customers. The set top box was manufactured by another company. So the project was a partnership between three parties: our company as the software vendor, the telecom carrier and the set-top box manufacturer. The telecom carrier wanted to know whether widgets could be animated on screen with smooth slide-in and slide-out effects. That was why the architect approached me to ask whether it could be done. I began working on animating the widgets. Meanwhile, the architect and a few senior colleagues attended a business meeting with all the partners present. During the meeting, he explained that we were evaluating whether widget animations could be supported. The set-top box manufacturer immediately dismissed the idea, saying, 'That's impossible. Our set-top box does not support animation.' When the architect returned and shared this with us, I replied, 'I do not understand. If I can draw a widget, I can animate it too. All it takes is clearing the widget and redrawing it at slightly different positions repeatedly. In fact, I already have a working version.' I then showed a demo of the animated widgets running on the emulator. The following week, the architect attended another partners' meeting where he shared updates about our animated widgets. I was not personally present, so what follows is second-hand information passed on by those who were there. I learnt that the set-top box company reacted angrily. For some reason, they were unhappy that we had managed to achieve results using their set-top box and APIs that they had officially described as impossible. They demanded that we stop work on animation immediately, arguing that our work could not be allowed to contradict their official position. At that point, the telecom carrier's representative intervened and bluntly told the set-top box representative to just shut up. If the set top box guy was furious, the telecom guy was even more so, 'You guys told us animation was not possible and these people are showing that it is! You manufacture the set-top box. How can you not know what it is capable of?' Meanwhile, I continued working and completed my proof-of-concept implementation. It worked very well in the emulator, but I did not yet have access to the actual hardware. The device was still in the process of being shipped to us, so all my early proof-of-concepts ran on the emulator. The following week, the architect planned to travel to the set-top box company's office to test my widgets on the real hardware. At the time, I was quite proud of demonstrating results that even the hardware maker believed were impossible. When the architect eventually travelled to test the widgets on the actual device, a problem emerged. What looked like buttery smooth animation on the emulator appeared noticeably choppy on a real television. Over the next few weeks, I experimented with frame rates, buffering strategies and optimising the computation done in the the rendering loop. Each week, the architect travelled for testing and returned with the same report: the animation had improved somewhat, but it still remained choppy. The modest embedded hardware simply could not keep up with the required computation and rendering. In the end, the telecom carrier decided that no animation was better than poor animation and dropped the idea altogether. So in the end, the set-top box developers turned out to be correct after all. Back in 2009, after completing about a year at RSA Security, I began looking for work that felt more intellectually stimulating, especially projects involving mathematics and algorithms. I spoke with a few senior leaders about this, but nothing materialised for some time. Then one day, Dr Burt Kaliski, Chief Scientist at RSA Laboratories, asked to meet me to discuss my career aspirations. I have written about this in more detail in another post here: Good Blessings . I will summarise what followed. Dr Kaliski met me and offered a few suggestions about the kinds of teams I might approach to find more interesting work. I followed his advice and eventually joined a team that turned out to be an excellent fit. I remained with that team for the next six years. During that time, I worked on parser generators, formal language specification and implementation, as well as indexing and querying components of a petabyte-scale database. I learnt something new almost every day during those six years. It remains one of the most enjoyable periods of my career. I have especially fond memories of working on parser generators alongside remarkably skilled engineers from whom I learnt a lot. Years later, I reflected on how that brief meeting with Dr Kaliski had altered the trajectory of my career. I realised I was not sure whether I had properly expressed my gratitude to him for the role he had played in shaping my path. So I wrote to thank him and explain how much that single conversation had influenced my life. A few days later, Dr Kaliski replied, saying he was glad to know that the steps I took afterwards had worked out well. Before ending his message, he wrote this heart-warming note: This story comes from 2019. By then, I was no longer a twenty-something engineer just starting out. I was now a middle-aged staff engineer with years of experience building both low-level networking systems and database systems. Most of my work up to that point had been in C and C++. I was now entering a new phase where I would be developing microservices professionally in languages such as Go and Python. None of this was unfamiliar territory. Like many people in this profession, computing has long been one of my favourite hobbies. So although my professional work for the previous decade had focused on C and C++, I had plenty of hobby projects in other languages, including Python and Go. As a result, switching gears from systems programming to application development was a smooth transition for me. I cannot even say that I missed working in C and C++. After all, who wants to spend their days occasionally chasing memory bugs in core dumps when you could be building features and delivering real value to customers? In October 2019, during Cybersecurity Awareness Month, a Capture the Flag (CTF) event was organised at our office. The contest featured all kinds of puzzles, ranging from SQL injection challenges to insecure cryptography problems. Some challenges also involved reversing binaries and exploiting stack overflow issues. I am usually rather intimidated by such contests. The whole idea of competitive problem-solving under time pressure tends to make me nervous. But one of my colleagues persuaded me to participate in the CTF. And, somewhat to my surprise, I turned out to be rather good at it. Within about eight hours, I had solved roughly 90% of the puzzles. I finished at the top of the scoreboard. In my younger days, I was generally known to be a good problem solver. I was often consulted when thorny problems needed solving and I usually managed to deliver results. I also enjoyed solving puzzles. I had a knack for them and happily spent hours, sometimes days, working through obscure mathematical or technical puzzles and sharing detailed write-ups with friends of the nerd variety. Seen in that light, my performance at the CTF probably should not have surprised me. Still, I was very pleased. It was reassuring to know that I could still rely on my systems programming experience to solve obscure challenges. During the course of the contest, my performance became something of a talking point in the office. Colleagues occasionally stopped by my desk to appreciate my progress in the CTF. Two much younger colleagues, both engineers I admired for their skill and professionalism, were discussing the results nearby. They were speaking softly, but I could still overhear parts of their conversation. Curious, I leaned slightly and listened a bit more carefully. I wanted to know what these two people, whom I admired a lot, thought about my performance. One of them remarked on how well I was doing in the contest. The other replied, 'Of course he is doing well. He has more than ten years of experience in C.' At that moment, I realised that no matter how well I solved those puzzles, the result would naturally be credited to experience. In my younger days, when I solved tricky problems, people would sometimes call me smart. Now it was expected. Not that I particularly care for such labels anyway, but it did make me realise how things had changed. I was now simply the person with many years of experience. Solving technical puzzles that involved disassembling binaries, tracing execution paths and reconstructing program logic was expected rather than remarkable. I continue to sharpen my technical skills to this day. While my technical results may now simply be attributed to experience, I hope I can continue to make a good impression through my professionalism, ethics and kindness towards the people I work with. If those leave a lasting impression, that is good enough for me. Read on website | #technology | #programming My First Lesson in HTML The Reset Vector My First Job Sphagetti Code Animated Television Widgets Good Blessings The CTF Scoreboard

0 views
Susam Pal 4 months ago

QuickQWERTY 1.2.1

QuickQWERTY 1.2.1 is now available. QuickQWERTY is a web-based touch typing tutor for QWERTY keyboards that runs directly in the web browser. This release contains a minor bug fix in Unit 4.3. Unit 4.3 is a 'Control' unit that lets you practise typing partial words as well as full words. In one place in this unit, the following sequence of partial and full words occurs: The full word was incorrectly repeated twice. This has been fixed to: To try out QuickQWERTY, go to quickqwerty.html . Read on website | #web | #programming

0 views
Susam Pal 4 months ago

Attention Media ≠ Social Media

When web-based social media started flourishing nearly two decades ago, they were genuinely social media. You would sign up for a popular service, follow people you knew or liked and read updates from them. When you posted something, your followers would receive your updates as well. Notifications were genuine. The little icons in the top bar would light up because someone had sent you a direct message or engaged with something you had posted. There was also, at the beginning of this millennium, a general sense of hope and optimism around technology, computers and the Internet. Social media platforms were one of the services that were part of what was called Web 2.0, a term used for websites built around user participation and interaction. It felt as though the information superhighway was finally reaching its potential. But sometime between 2012 and 2016, things took a turn for the worse. First came the infamous infinite scroll. I remember feeling uneasy the first time a web page no longer had a bottom. Logically, I knew very well that everything a browser displays is a virtual construct. There is no physical page. It is just pixels pretending to be one. Still, my brain had learned to treat web pages as objects with a beginning and an end. The sudden disappearance of that end disturbed my sense of ease. Then came the bogus notifications. What had once been meaningful signals turned into arbitrary prompts. Someone you followed had posted something unremarkable and the platform would surface it as a notification anyway. It didn't matter whether the notification was relevant to me. The notification system stopped serving me and started serving itself. It felt like a violation of an unspoken agreement between users and services. Despite all that, these platforms still remained social in some diluted sense. Yes, the notifications were manipulative, but they were at least about people I actually knew or had chosen to follow. That, too, would change. Over time, my timeline contained fewer and fewer posts from friends and more and more content from random strangers. Using these services began to feel like standing in front of a blaring loudspeaker, broadcasting fragments of conversations from all over the world directly in my face. That was when I gave up on these services. There was nothing social about them anymore. They had become attention media . My attention is precious to me. I cannot spend it mindlessly scrolling through videos that have neither relevance nor substance. But where one avenue disappeared, another emerged. A few years ago, I stumbled upon Mastodon and it reminded me of the early days of Twitter. Back in 2006, I followed a small number of folks of the nerd variety on Twitter and received genuinely interesting updates from them. But when I log into the ruins of those older platforms now, all I see are random videos presented to me for reasons I can neither infer nor care about. Mastodon, by contrast, still feels like social media in the original sense. I follow a small number of people I genuinely find interesting and I receive their updates and only their updates. What I see is the result of my own choices rather than a system trying to optimise my behaviour. There are no bogus notifications. The timeline feels calm and predictable. If there are no new updates from people I follow, there is nothing to see. It feels closer to how social media services used to work originally. I hope it stays that way. Read on website | #miscellaneous

0 views
Susam Pal 4 months ago

Minimal GitHub Workflow

This is a note where I capture the various errors we receive when we create GitHub workflows that are smaller than the smallest possible workflow. I do not know why anyone would ever need this information and I doubt it will serve any purpose for me either but sometimes you just want to know things, no matter how useless they might be. This is one of the useless things I wanted to know today. For the first experiment we just create a zero byte file and push it to GitHub as follows, say, like this: Under the GitHub repo's Actions tab, we find this error: Then we update the workflow as follows: Now we get this error: Next update: Corresponding error: The experiments are preserved in the commit history of github.com/spxy/minighwf . Read on website | #technology Empty Workflow Runs On Ubuntu Latest Empty Steps Hello, World

0 views
Susam Pal 4 months ago

Circular Recursive Negating Acronyms

One of my favourite acronyms from the world of computing and technology is XINU. It stands for 'XINU Is Not Unix'. The delightful thing about this acronym is that XINU is also UNIX spelled backwards. For a given word W , a recursive acronym that both negates W and reverses it is possible when W has the form W = '?NI?' where each '?' denotes a distinct letter. Some fictitious examples make this clearer: Words of the form '?N?' also work if we are happy to contract the word 'is' in the acronym. In fact, in this case we can even obtain circular recursive acronyms: In each pair, the two acronyms negate each other, making them circular while also being reverses of one another. Such acronyms could serve as amusing names for expressing friendly banter between rival projects. Read on website | #miscellaneous LINA Is Not ANIL. TINK Is Not KNIT. ANI's Not INA. INA's Not ANI. ONE's Not ENO. ENO's Not ONE.

0 views
Susam Pal 5 months ago

My Coding Adventures in 2025

In this post, I return with a retrospective on my coding adventures, where I summarise my hobby projects and recreational programming activities from the current year. I did the last such retrospective in 2023 . So I think this is a good time to do another retrospective. At the outset, I should mention that I have done less hobby computing this year than in the past few, largely because I spent a substantial portion of my leisure time studying Galois theory and algebraic graph theory. In case you are wondering where I am learning these subjects from, the books are Galois Theory , 5th ed. by Ian Stewart and Algebraic Graph Theory by Godsil and Royle. Both are absolutely fascinating subjects and the two books I mentioned are quite good as well. I highly recommend them. Now back to the coding adventures. Here they go: MathB : The year began not with the release of a new project but with the opposite: discontinuing a project I had maintained for 13 years. MathB.in, a mathematics pastebin service, was discontinued early this year. This is a project I developed in 2012 for myself and my friends. Although a rather simple project, it was close to my heart, as I have many fond memories of exchanging mathematical puzzles and solutions with my friends using this service. Over time, the project grew quite popular on IRC networks, as well as in some schools and universities, where IRC users, learners, and students used the service to share problems and solutions with one another, much as my friends and I had done in its early days. I shut it down this year because I wanted to move on from the project. Before the shutdown, a kind member of the Archive Team worked with me to archive all posts from the now-defunct website. Although shutting down this service was a bittersweet event for me, I feel relieved that I no longer have to run a live service in my spare time. While this was a good hobby ten years ago, it no longer is. See my blog post MathB.in Is Shutting Down for more details on the reasons behind this decision. The source code of this project remains open source and available at github.com/susam/mathb . QuickQWERTY : This is a touch-typing tutor that runs in a web browser. I originally developed it in 2008 for myself and my friends. While I learned touch typing on an actual typewriter as a child, those lessons did not stick with me. Much later, while I was at university, I came across a Java applet-based touch-typing tutor that finally helped me learn touch typing properly. I disliked installing Java plugins in the web browser, which is why I later developed this project in plain HTML and JavaScript. This year, I carried out a major refactoring to collapse the entire project into a single standalone HTML file with no external dependencies. The source code has been greatly simplified as well. When I was younger and more naive, inspired by the complexity and multiple layers of abstraction I saw in popular open source and professional projects, I tended to introduce similar abstractions and complexity into my personal projects. Over time, however, I began to appreciate simplicity. The new code for this project is smaller and simpler, and I am quite happy with the end result. You can take a look at the code here: quickqwerty.html . If you want to use the typing tutor, go here: QuickQWERTY . Unfortunately, it does not support keyboard layouts other than QWERTY. When I originally developed this project, my view of the computing world was rather limited. I was not even aware that other keyboard layouts existed. You are, however, very welcome to fork the project and adapt the lessons for other layouts. CFRS[] : This project was my first contribution to the quirky world of esolangs. CFRS[] is an extremely minimal drawing language consisting of only six simple commands: , , , , , and . I developed it in 2023 and have since been maintaining it with occasional bug fixes. This year, I fixed an annoying bug that caused the drawing canvas to overflow on some mobile web browsers. A new demo also arrived from the community this year and has now been added to the community demo page. See Glimmering Galaxy for the new demo. If you want to play with CFRS[] now, visit CFRS[] . FXYT : This is another esolang project of mine. This too is a minimal drawing language, though not as minimal as CFRS[]. Instead, it is a stack-based, postfix canvas colouring language with only 36 simple commands. The canvas overflow bug described in the previous entry affected this project as well. That has now been fixed. Further, by popular demand, the maximum allowed code length has been increased from 256 bytes to 1024 bytes. This means there is now more room for writing more complex FXYT programs. Additionally, the maximum code length for distributable demo links has been increased from 64 bytes to 256 bytes. This allows several more impressive demos to have their own distributable links. Visit FXYT to try it out now. See also the Community Demos to view some fascinating artwork created by the community. Nerd Quiz : This is a new project I created a couple of months ago. It is a simple HTML tool that lets you test your nerdiness through short quizzes. Each question is drawn from my everyday moments of reading, writing, thinking, learning, and exploring. The project is meant to serve as a repository of interesting facts I come across in daily life, captured in the form of quiz questions. Go here to try it out: Nerd Quiz . I hope you will enjoy these little bits of knowledge as much as I enjoyed discovering them. Mark V. Shaney Junior : Finally, I have my own Markov gibberish generator. Always wanted to have one. The project is inspired by the legendary Usenet bot named Mark V. Shaney that used to post messages to various newsgroups in the 1980s. My Markov chain program is written in about 30 lines of Python. I ran it on my 24 years of blog posts consisting of over 200 posts and about 200,000 words and it generated some pretty interesting gibberish. See my blog post Fed 24 Years of My Posts to Markov Model to see the examples. Elliptical Python Programming : If the previous item was not silly enough, this one surely is. Earlier this year, I wrote a blog post describing the fine art of Python programming using copious amounts of ellipses. I will not discuss it further here to avoid spoilers. I'll just say that any day I'm able to do something pointless, whimsical and fun with computers is a good day for me. And it was a good day when I wrote this post. Please visit the link above to read the post. I hope you find it fun. Fizz Buzz with Cosines : Another silly post in which I explain how to compute the discrete Fourier transform of the Fizz Buzz sequence and derive a closed-form expression that can be used to print the sequence. Fizz Buzz in CSS : Yet another Fizz Buzz implementation, this time using just four lines of CSS. That wraps up my coding adventures for this year. There were fewer hobby projects than usual but I enjoyed spending more time learning new things and revisiting old ones. One long-running project came to an end, another was cleaned up and a few small new ideas appeared along the way. Looking forward to what the next year brings. Read on website | #programming | #technology | #retrospective MathB : The year began not with the release of a new project but with the opposite: discontinuing a project I had maintained for 13 years. MathB.in, a mathematics pastebin service, was discontinued early this year. This is a project I developed in 2012 for myself and my friends. Although a rather simple project, it was close to my heart, as I have many fond memories of exchanging mathematical puzzles and solutions with my friends using this service. Over time, the project grew quite popular on IRC networks, as well as in some schools and universities, where IRC users, learners, and students used the service to share problems and solutions with one another, much as my friends and I had done in its early days. I shut it down this year because I wanted to move on from the project. Before the shutdown, a kind member of the Archive Team worked with me to archive all posts from the now-defunct website. Although shutting down this service was a bittersweet event for me, I feel relieved that I no longer have to run a live service in my spare time. While this was a good hobby ten years ago, it no longer is. See my blog post MathB.in Is Shutting Down for more details on the reasons behind this decision. The source code of this project remains open source and available at github.com/susam/mathb . QuickQWERTY : This is a touch-typing tutor that runs in a web browser. I originally developed it in 2008 for myself and my friends. While I learned touch typing on an actual typewriter as a child, those lessons did not stick with me. Much later, while I was at university, I came across a Java applet-based touch-typing tutor that finally helped me learn touch typing properly. I disliked installing Java plugins in the web browser, which is why I later developed this project in plain HTML and JavaScript. This year, I carried out a major refactoring to collapse the entire project into a single standalone HTML file with no external dependencies. The source code has been greatly simplified as well. When I was younger and more naive, inspired by the complexity and multiple layers of abstraction I saw in popular open source and professional projects, I tended to introduce similar abstractions and complexity into my personal projects. Over time, however, I began to appreciate simplicity. The new code for this project is smaller and simpler, and I am quite happy with the end result. You can take a look at the code here: quickqwerty.html . If you want to use the typing tutor, go here: QuickQWERTY . Unfortunately, it does not support keyboard layouts other than QWERTY. When I originally developed this project, my view of the computing world was rather limited. I was not even aware that other keyboard layouts existed. You are, however, very welcome to fork the project and adapt the lessons for other layouts. CFRS[] : This project was my first contribution to the quirky world of esolangs. CFRS[] is an extremely minimal drawing language consisting of only six simple commands: , , , , , and . I developed it in 2023 and have since been maintaining it with occasional bug fixes. This year, I fixed an annoying bug that caused the drawing canvas to overflow on some mobile web browsers. A new demo also arrived from the community this year and has now been added to the community demo page. See Glimmering Galaxy for the new demo. If you want to play with CFRS[] now, visit CFRS[] . FXYT : This is another esolang project of mine. This too is a minimal drawing language, though not as minimal as CFRS[]. Instead, it is a stack-based, postfix canvas colouring language with only 36 simple commands. The canvas overflow bug described in the previous entry affected this project as well. That has now been fixed. Further, by popular demand, the maximum allowed code length has been increased from 256 bytes to 1024 bytes. This means there is now more room for writing more complex FXYT programs. Additionally, the maximum code length for distributable demo links has been increased from 64 bytes to 256 bytes. This allows several more impressive demos to have their own distributable links. Visit FXYT to try it out now. See also the Community Demos to view some fascinating artwork created by the community. Nerd Quiz : This is a new project I created a couple of months ago. It is a simple HTML tool that lets you test your nerdiness through short quizzes. Each question is drawn from my everyday moments of reading, writing, thinking, learning, and exploring. The project is meant to serve as a repository of interesting facts I come across in daily life, captured in the form of quiz questions. Go here to try it out: Nerd Quiz . I hope you will enjoy these little bits of knowledge as much as I enjoyed discovering them. Mark V. Shaney Junior : Finally, I have my own Markov gibberish generator. Always wanted to have one. The project is inspired by the legendary Usenet bot named Mark V. Shaney that used to post messages to various newsgroups in the 1980s. My Markov chain program is written in about 30 lines of Python. I ran it on my 24 years of blog posts consisting of over 200 posts and about 200,000 words and it generated some pretty interesting gibberish. See my blog post Fed 24 Years of My Posts to Markov Model to see the examples. Elliptical Python Programming : If the previous item was not silly enough, this one surely is. Earlier this year, I wrote a blog post describing the fine art of Python programming using copious amounts of ellipses. I will not discuss it further here to avoid spoilers. I'll just say that any day I'm able to do something pointless, whimsical and fun with computers is a good day for me. And it was a good day when I wrote this post. Please visit the link above to read the post. I hope you find it fun. Fizz Buzz with Cosines : Another silly post in which I explain how to compute the discrete Fourier transform of the Fizz Buzz sequence and derive a closed-form expression that can be used to print the sequence. Fizz Buzz in CSS : Yet another Fizz Buzz implementation, this time using just four lines of CSS.

0 views
Susam Pal 5 months ago

Mark V. Shaney Junior 0.2.0

Mark V. Shaney Junior 0.2.0 is the second release of this little Markov gibberish generator. This release brings two small changes. First, it now reads the training data from standard input instead of a hardcoded file. Second, the program filename has been changed from to to reflect that it is an executable file and can be run as on most Unix and Linux systems. The source and a detailed documentation for this project are available at github.com/susam/mvs . See also this related blog post and a discussion on Hacker News about it. Read on website | #python | #programming | #technology

1 views