<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="./feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Susam Pal</title>
  <subtitle>Susam's Feed</subtitle>
  <link href="https://susam.net/"/>
  <link href="https://susam.net/feed.xml" rel="self"/>
  <id>urn:uuid:92c43730-c96a-44a7-a2c3-ed18dcc268f7</id>
  <updated>2026-05-24T00:00:00Z</updated>
  <author><name>Susam Pal</name></author>
  <entry>
    <title>Childhood Computing</title>
    <link href="https://susam.net/childhood-computing.html"/>
    <id>urn:uuid:61e4898d-c887-40dd-81c3-05f39045ce64</id>
    <updated>2026-05-24T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  I recently stumbled upon a nice blog post titled
  &lt;a href=&quot;https://lilysthings.org/blog/childhood-computing/&quot;&gt;Childhood
  Computing&lt;/a&gt;.  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 too love computers.  I have for most of my
  life.
&lt;/p&gt;
&lt;p&gt;
  In 1992, when I was 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.
&lt;/p&gt;
&lt;p&gt;
  Before entering the lab, we had to leave our shoes at the door.
  &apos;These are expensive machines.  We must keep them free of dust&apos;, 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&amp;frac14;-inch floppy disk to load MS-DOS into memory.
  Then insert another disk to load &lt;code&gt;LOGO.COM&lt;/code&gt;.  Then write
  small Logo programs and watch the turtle move.  I have written more
  about that early Logo programming experience
  here: &lt;a href=&quot;fd-100.html&quot;&gt;FD 100&lt;/a&gt;.  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.
&lt;/p&gt;
&lt;figure id=&quot;logo-video&quot;&gt;
  &lt;video controls src=&quot;files/blog/logo-circles.mp4&quot;
         poster=&quot;files/blog/logo-cs.png&quot;&gt;&lt;/video&gt;
  &lt;figcaption&gt;
    Video capture of IBM Personal Computer Logo
    [&lt;a href=&quot;files/blog/logo-circles.mp4&quot;&gt;MP4&lt;/a&gt;]
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
  Since I had so little time with an actual computer, most of my Logo
  programming happened with pen and paper at home.  I would &apos;test&apos; 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 alter the details and add their own
  little touches.  That must have been my first &apos;free and open source
  software&apos;.  The &apos;licence&apos; was &apos;do whatever you want but show me if
  you make any interesting modifications&apos;.  The distribution system
  was entirely analogue: classmates copied the code into their
  notebooks with pencils, then went back to their machines in the lab
  and typed it back into the computer.
&lt;/p&gt;
&lt;p&gt;
  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.  Some of my favourite games were Space Invaders, Bricks and
  Grand Prix Circuit.  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, in 2022, as an adult, I did
  manage to write an Invaders-like game, which you can find
  here: &lt;a href=&quot;invaders.html&quot;&gt;Andromeda Invaders&lt;/a&gt;.  It has an
  auto-play mode too, like some games had back when I was a kid.  If
  you wait five seconds, the game starts playing by itself.  It is
  quite fun to watch.  Although thirty years too late, writing this
  game fulfilled a childhood dream!
&lt;/p&gt;
&lt;p&gt;
  One of my buddies liked the game called Digger developed by Windmill
  Software.  It soon became my favourite as well.  The game came on 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.
&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls src=&quot;files/blog/dosbox-digger.mp4&quot;
         poster=&quot;files/blog/dosbox-digger-1.png&quot;&gt;&lt;/video&gt;
  &lt;figcaption&gt;
    Video capture of Digger
    [&lt;a href=&quot;files/blog/dosbox-digger.mp4&quot;&gt;MP4&lt;/a&gt;]
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
  Another computer game I remember fondly was Grand Prix Circuit by
  Accolade Inc.  I really loved typing the command &lt;code&gt;GPEGA&lt;/code&gt;
  to launch the game, knowing that in a moment I would 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.
&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls src=&quot;files/blog/dosbox-gpega.mp4&quot;
         poster=&quot;files/blog/dosbox-gpega.png&quot;&gt;&lt;/video&gt;
  &lt;figcaption&gt;
    Video capture of Grand Prix Circuit
    [&lt;a href=&quot;files/blog/dosbox-gpega.mp4&quot;&gt;MP4&lt;/a&gt;]
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
  It has been over thirty 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.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/childhood-computing.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/programming.html&quot;&gt;#programming&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/retrospective.html&quot;&gt;#retrospective&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Don't Roll Your Own ...</title>
    <link href="https://susam.net/do-not-roll-your-own.html"/>
    <id>urn:uuid:78208b12-52d0-473f-b325-527720307e2d</id>
    <updated>2026-05-23T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  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: &lt;em&gt;Don&apos;t roll your own crypto.&lt;/em&gt;  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.
&lt;/p&gt;
&lt;p&gt;
  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&apos;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.
&lt;/p&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    Don&apos;t roll your own page scrolling.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own link navigation.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own text selection.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own context menu.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own copy and paste.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own password field.
  &lt;/li&gt;
  &lt;li&gt;
    Don&apos;t roll your own date picker.
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  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 &lt;em&gt;user&lt;/em&gt; 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.
&lt;/p&gt;
&lt;p&gt;
  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 &apos;breaks&apos; 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&apos;t even think about it, and turn it into something unfamiliar
  that I now have to think about.
&lt;/p&gt;
&lt;p&gt;
  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&apos;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.  Let me share an example.  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.  To verify this, visit your favourite project on
  GitHub using Firefox or Chrome, type &lt;kbd&gt;F12&lt;/kbd&gt; to open the
  browser&apos;s developer tools, then go to the &apos;Debugger&apos; or &apos;Sources&apos;
  tab, find &apos;Event Listener Breakpoints&apos; on the right sidebar, expand
  &apos;Mouse&apos; and select &apos;click&apos;.  Then click on a link on GitHub and see
  what happens.
&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;files/blog/ghdbg.png&quot; alt=&quot;Screenshot of a GitHub repository page with the browser&apos;s developer tools open, paused in the JavaScript debugger on a click event listener.&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;
  I&apos;m sure I am not the only one who has noticed that, 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 the JavaScript code to
  handle the navigation in the current tab.
&lt;/p&gt;
&lt;p&gt;
  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&apos;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.
&lt;/p&gt;
&lt;p&gt;
  Custom date pickers are another common annoyance.  I know that
  &lt;code&gt;&amp;lt;input type=&quot;date&quot;&amp;gt;&lt;/code&gt; 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 &lt;code&gt;&amp;lt;input type=&quot;date&quot;&amp;gt;&lt;/code&gt; element could be
  left intact, with a custom widget provided &lt;em&gt;in addition&lt;/em&gt; to
  it so that users can manipulate the same field.
&lt;/p&gt;
&lt;p&gt;
  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&apos;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&apos;t be
  pleasant!
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/do-not-roll-your-own.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/web.html&quot;&gt;#web&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Five Minutes of Prime Time</title>
    <link href="https://susam.net/five-minutes-of-prime-time.html"/>
    <id>urn:uuid:98fe77c7-c72a-4c4a-93da-315d1342a76b</id>
    <updated>2026-05-16T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Let me share a very silly story from roughly 18 years ago!  In 2008,
  I joined
  &lt;a href=&quot;https://en.wikipedia.org/wiki/RSA_Security&quot;&gt;RSA&lt;/a&gt;, the
  network security company named after the initials of the inventors
  of the RSA algorithm, Rivest, Shamir and Adleman, who were also the
  founders of RSA, the company.
&lt;/p&gt;
&lt;p&gt;
  There was a bit of a nerd culture in the workplace where topics like
  prime numbers, combinatorics, probability theory, etc. were
  discussed fervently.  A prime-number employee number was considered
  a lucky charm.  I had a rather nice large five-digit prime number as
  my employee number, which I remember being quite pleased about.
  There were internal forums for almost all kinds of topics.  A few I
  remember fondly were a mathematics forum where colleagues would
  challenge each other with mathematical puzzles and a similar physics
  forum where, for some reason, crafting contrived paradoxes using
  special and general relativity and putting them up for debate was a
  common activity.  The participants would analyse each paradox to
  determine if it truly was one or if it could be resolved into
  something that was no longer a paradox.  I loved hanging out on
  those forums and made many friends there.  The mathematics forum, in
  particular, gave me plenty of fun problems to think about.  In fact,
  my &lt;a href=&quot;langford-pairing.html&quot;&gt;Langford Pairing&lt;/a&gt; (2011) post
  was the result of a question I had stumbled upon there.
&lt;/p&gt;
&lt;p&gt;
  The human resources (HR) department used to organise afternoon games
  once every month where people would self-organise into teams and
  solve a small challenge.  There was a cash prize for the winning
  team each time.  The HR folks were very well aware of the nerd
  culture and the fascination with prime numbers, but they probably
  did not know enough about exactly what type of problems we were
  fascinated with.  So in one of the monthly game events, the HR team
  gave us this challenge.
&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;
  Write as many prime numbers between 1 and 1000 as you can in 5
  minutes.
&lt;/p&gt;
&lt;p&gt;
  The 5-minute timer started immediately.  Really, that was the
  challenge.  We all looked at each other in surprise, wondering if
  that really was the problem.  The game was already on.  No
  constraints were set.  Were we allowed to look up a list on the web?
  Probably not, otherwise what would be the point of the game?
&lt;/p&gt;
&lt;p&gt;
  There were five or six teams with a total of about 30 or so
  participants.  We began working on the challenge.  The first thing I
  did was load up the list of all 168 prime numbers from 1 to 1000 on
  my mobile phone and begin copying them meticulously to our sheet of
  paper.
&lt;/p&gt;
&lt;p&gt;
  I would learn later that another team had followed the same approach
  too.  The person writing their list decided to omit a few numbers so
  that it did not look like they had copied the numbers verbatim from
  an external source.  I think they were being overcautious because
  there were no rules, and all is fair in love and listing prime
  numbers.
&lt;/p&gt;
&lt;p&gt;
  I completed writing our list with about half a minute to spare.  We
  turned in our sheets after the timer ran out.  The HR folks then
  evaluated the sheets.  The winner was announced.  Our team won with
  all 168 numbers written accurately.  We won the cash prize.  One of
  the HR folks asked me later what formula we had used to generate all
  the prime numbers so accurately.  I told them that we had used the
  ancient formula of looking up a list of prime numbers compiled by
  someone else and writing it down.  We spent the cash prize
  immediately and ordered pizza and soft drinks for everyone.
&lt;/p&gt;
&lt;p&gt;
  The monthly afternoon games were not usually this silly.  The other
  games were more interesting, more challenging and better designed.
  But I don&apos;t remember what those games were at all now.  It is only
  this silly game that remains etched in my memory.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/five-minutes-of-prime-time.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/miscellaneous.html&quot;&gt;#miscellaneous&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/story.html&quot;&gt;#story&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Commenting Guidelines</title>
    <link href="https://susam.net/commenting.html"/>
    <id>urn:uuid:b9d391bb-4cf2-49a8-8e7a-c5b7216bdf01</id>
    <updated>2026-05-14T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;h1&gt;Commenting Guidelines&lt;/h1&gt;
&lt;p&gt;
  This website has an active &lt;a href=&quot;comments/&quot;&gt;comments
  section&lt;/a&gt;, carefully maintained and curated by the author of this
  website.  When commenting on this website, please keep the following
  points in mind:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;
      You may include HTML or Markdown in your comment.  Comments are
      converted to HTML and sanitised before they are published on
      this website.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      All submitted comments are held for review.  Whether a comment
      is published or not is at the discretion of the author of this
      website.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Typically, only the following types of comments are published:
    &lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;
        Comments that add new information to the topic discussed in an
        article.
      &lt;/li&gt;
      &lt;li&gt;
        Comments that offer new insight on a topic.
      &lt;/li&gt;
      &lt;li&gt;
        Comments that provide a neutral, supporting or opposing
        viewpoint.
      &lt;/li&gt;
      &lt;li&gt;
        Comments that report typos, errors or bugs on the website.
      &lt;/li&gt;
      &lt;li&gt;
        Comments that contain good humour.
      &lt;/li&gt;
      &lt;li&gt;
        Comments that express appreciation.
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Generally, rants are not published, even when the post you are
      commenting on is itself a rant.  This website is the author&apos;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 &lt;a href=&quot;comments/&quot;&gt;comments&lt;/a&gt; section.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Similarly, comments containing speculation about worldly affairs
      are not published.  The intention here is to prevent the
      comments section from becoming an endless stream of speculative
      remarks.  This is especially a problem for articles discussing
      academic, professional, social or technological issues.  Such
      articles tend to attract a large number of comments speculating
      about how certain organisations may be causing those issues for
      their own benefit.  While such speculation may have merit, this
      website is not the place to discuss it.  If you feel strongly
      about such topics, please discuss them on your own website.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Comments discussing politics are not published.  Regrettably,
      many otherwise good comments have not been published because
      they contained political asides.  Allowing political discussion
      in the &lt;a href=&quot;comments/&quot;&gt;comments&lt;/a&gt; section is a
      sure way to ruin this carefully maintained section.  Therefore,
      comments containing political remarks are not published.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      When a comment reports a typo or error in an article, that
      comment is published on the &lt;a href=&quot;comments/bugs.html&quot;&gt;bugs
      page&lt;/a&gt; rather than on the comment page for the article.  This
      is done to collect contributions from kind readers on a single
      page.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      All comments deemed suitable for this website by its author
      become publicly available on this website at two places: either
      on the comment page for the article you commented on
      (&lt;a href=&quot;comments/fd-100.html&quot;&gt;example&lt;/a&gt;) or on the
      &lt;a href=&quot;comments/bugs.html&quot;&gt;bugs page&lt;/a&gt;, as well as on
      the overall comment index page at
      &lt;a href=&quot;comments/&quot;&gt;comments&lt;/a&gt;.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Do not submit sensitive personal data in your comments.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Do not publish original research in comments.  This may seem
      like a strange guideline, but there have been instances where
      people posted long comments containing mathematical material,
      claiming that they had novel results.  The author of this
      website does not have the time to review such comments.  If you
      want to share original research, please do so on your own
      website or in a more appropriate forum.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Do not link to or promote your commercial services and mobile
      apps.
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/commenting.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/meta.html&quot;&gt;#meta&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>The Problem of Pedagogy in Advanced Mathematics</title>
    <link href="https://susam.net/advanced-mathematics-pedagogy.html"/>
    <id>urn:uuid:f47ac884-f0f8-47ff-aa66-16a28ec9c980</id>
    <updated>2026-05-11T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  It is a commonly held opinion that educational institutions could do
  more to improve the pedagogy of mathematics.  This is especially
  applicable to primary and secondary schools, where students are
  first exposed to mathematics as a formal subject, along with other
  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.
&lt;/p&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  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.  There is a reason why jokes like
  &apos;proof by obviousness&apos; and &apos;proof by intimidation&apos; are so funny.
  They are funny because they are true, more true than one would like.
&lt;/p&gt;
&lt;p&gt;
  I don&apos;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.
&lt;/p&gt;
&lt;p&gt;
  The situation is even more dire when it comes to research papers but
  that would be a topic for another discussion.  I&apos;ll focus on books
  for now.  I completely understand why an advanced textbook cannot
  provide a justification for every argument, because if a textbook
  tries to do so, then a 200 page book would turn into a 2000 page
  book.  No student or teacher has the time or patience to read
  through thousands of pages of uninteresting &apos;technical&apos; arguments.
  So the authors choose to focus on the interesting parts and expect
  the student to work out all the elisions.  Even so, I find it
  painful to see just how many such elisions exist in a typical
  textbook and how big they can sometimes be.
&lt;/p&gt;
&lt;p&gt;
  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.  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&apos;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.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/advanced-mathematics-pedagogy.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/miscellaneous.html&quot;&gt;#miscellaneous&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>I Will Not Add Query Strings to Your URLs</title>
    <link href="https://susam.net/no-query-strings.html"/>
    <id>urn:uuid:60101ca6-f872-4062-8101-1735dcfd7b9b</id>
    <updated>2026-05-09T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Last evening, a short blog post appeared in my feed reader that felt
  as if it spoke directly to me.  It is Chris Morgan&apos;s excellent post
  &lt;cite&gt;&lt;a href=&quot;https://chrismorgan.info/no-query-strings&quot;&gt;I&apos;ve banned
  query strings&lt;/a&gt;&lt;/cite&gt;.
&lt;/p&gt;
&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#wisdom-on-the-web&quot;&gt;Wisdom on the Web&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wander-on-the-web&quot;&gt;Wander on the Web&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#misfeature&quot;&gt;Misfeature&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#broken-urls&quot;&gt;Broken URLs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#qualms&quot;&gt;Qualms&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wisdom-on-the-web&quot;&gt;Wisdom on the Web&lt;/h2&gt;
&lt;p&gt;
  &lt;a href=&quot;https://chrismorgan.info/&quot;&gt;Chris&lt;/a&gt; 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 &lt;a href=&quot;https://news.ycombinator.com/item?id=25321222#25322611&quot;&gt;feedback&lt;/a&gt;
  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
  &lt;a href=&quot;twenty-five-years-of-computing.html&quot;&gt;professional life&lt;/a&gt;
  doing systems programming in C and C++.  However, developing
  websites and writing
  &lt;a href=&quot;tag/html.html&quot;&gt;small HTML tools&lt;/a&gt; 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
  &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML&quot;&gt;MDN Web
  Docs&lt;/a&gt; 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
  &lt;a href=&quot;more-purple-links-please.html&quot;&gt;retain purple&lt;/a&gt; for
  visited links.
&lt;/p&gt;
&lt;p&gt;
  I have been following Chris&apos;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&apos;t mine.  I always end up
  learning something nice and useful from his comments.  Here is one
  such recent example from the Lobsters story
  &lt;cite&gt;&lt;a href=&quot;https://lobste.rs/s/crcktq/adding_author_context_rss#c_wb5ryy&quot;&gt;Adding
  author context to RSS&lt;/a&gt;&lt;/cite&gt;.
&lt;/p&gt;
&lt;h2 id=&quot;wander-on-the-web&quot;&gt;Wander on the Web&lt;/h2&gt;
&lt;p&gt;
  A couple of months ago, I created a new project called &lt;em&gt;Wander
  Console&lt;/em&gt;.  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:
  &lt;a href=&quot;wander/&quot;&gt;susam.net/wander/&lt;/a&gt;.  If you click the &apos;Wander&apos;
  button there, the tool loads a random personal web page recommended
  by the Wander community.
&lt;/p&gt;
&lt;p&gt;
  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&apos;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 &apos;Wander&apos;
  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
  &lt;a href=&quot;https://en.wikipedia.org/wiki/StumbleUpon&quot;&gt;StumbleUpon&lt;/a&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  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
  &lt;a href=&quot;https://susam.codeberg.page/wcn/&quot;&gt;susam.codeberg.page/wcn/&lt;/a&gt;.
  To learn more about this tool or to set it up on your website,
  please see &lt;a href=&quot;https://codeberg.org/susam/wander#readme&quot;&gt;codeberg.org/susam/wander&lt;/a&gt;.
&lt;/p&gt;
&lt;h2 id=&quot;misfeature&quot;&gt;Misfeature&lt;/h2&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  In version 0.4.0 of Wander Console, I added support for
  a &lt;code&gt;via=&lt;/code&gt; query parameter while loading web pages.  For
  example, if you encountered &lt;a href=&quot;https://midnight.pub/&quot;&gt;midnight.pub&lt;/a&gt;
  while using the console at &lt;a href=&quot;https://susam.net/wander/&quot;&gt;susam.net/wander/&lt;/a&gt;,
  the console loaded the page using the following URL:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://midnight.pub/?via=https://susam.net/wander/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  This allowed the owner of the recommended website to see, via their
  access logs, that the visit originated from a Wander Console.
  Chris&apos;s recent &lt;a href=&quot;https://chrismorgan.info/no-query-strings&quot;&gt;blog
  post&lt;/a&gt; is critical of features like this.  He writes:
&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    I don&apos;t like people adding tracking stuff to URLs.  Still less do I
    like people adding tracking stuff to &lt;em&gt;my&lt;/em&gt; URLs.
  &lt;/p&gt;
  &lt;p&gt;
    &lt;code&gt;https://chrismorgan.info/no-query-strings?ref=example.com&lt;/code&gt;?
    Did I ask?  If I wanted to know I&apos;d look at the
    &lt;code&gt;Referer&lt;/code&gt; header; and if it isn&apos;t there, it&apos;s probably
    for a good reason.  You abuse your users by adding that to the
    link.
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  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
  &lt;a href=&quot;https://codeberg.org/susam/wander/issues/1#issuecomment-11795493&quot;&gt;feature
  request&lt;/a&gt; on Codeberg, my initial reaction was reluctance.  I
  wasn&apos;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&apos;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.
&lt;/p&gt;
&lt;p&gt;
  Normally, I don&apos;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&apos;ll fix bugs,
  of course.  But I don&apos;t like to keep adding new features endlessly.
  That&apos;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.
&lt;/p&gt;
&lt;p&gt;
  Although my gut feeling was telling me that it was not a good
  feature, I couldn&apos;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&apos;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&apos;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:
&lt;/p&gt;
&lt;blockquote&gt;
  Your scientists were so preoccupied with whether or not they could
  that they didn&apos;t stop to think if they should.
&lt;/blockquote&gt;
&lt;h2 id=&quot;broken-urls&quot;&gt;Broken URLs&lt;/h2&gt;
&lt;p&gt;
  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:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://int10h.org/oldschool-pc-fonts/fontlist/&quot;&gt;https://int10h.org/oldschool-pc-fonts/fontlist/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://int10h.org/oldschool-pc-fonts/fontlist/?2&quot;&gt;https://int10h.org/oldschool-pc-fonts/fontlist/?2&lt;/a&gt;
  &lt;li&gt;&lt;a href=&quot;https://int10h.org/oldschool-pc-fonts/fontlist/?foo&quot;&gt;https://int10h.org/oldschool-pc-fonts/fontlist/?foo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  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 &lt;code&gt;via=&lt;/code&gt; query parameter to
  the first URL, the page failed to load.
&lt;/p&gt;
&lt;p&gt;
  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 &lt;em&gt;new&lt;/em&gt; 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 &lt;a href=&quot;https://news.ycombinator.com/item?id=39419054#39439453&quot;&gt;fond&lt;/a&gt;
  of.
&lt;/p&gt;
&lt;h2 id=&quot;qualms&quot;&gt;Qualms&lt;/h2&gt;
&lt;p&gt;
  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 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referer&quot;&gt;Referer&lt;/a&gt;
  header, governed by &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy&quot;&gt;Referrer-Policy&lt;/a&gt;.
  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&apos;t think an HTML tool should do that.
&lt;/p&gt;
&lt;p&gt;
  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&apos;t.
&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
  In the end, I decided to remove the referral query string feature
  from Wander Console.  One might wonder why I couldn&apos;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
  &lt;cite&gt;&lt;a href=&quot;https://chrismorgan.info/no-query-strings&quot;&gt;I&apos;ve
  banned query strings&lt;/a&gt;&lt;/cite&gt; 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
  &lt;a href=&quot;https://codeberg.org/susam/wander/commit/b26d77c4da9ec11b655ba64a4ae4f3af56e06370&quot;&gt;b26d77c&lt;/a&gt;
  for details.  The latest release, version 0.6.0, does not have it
  anymore.
&lt;/p&gt;
&lt;p&gt;
  This is a lesson I&apos;ll remember for any new hobby projects I happen
  to make in the future.  If I ever load URLs again, I&apos;ll load them
  exactly as the website&apos;s author intended.  I will never add query
  strings to your URLs.
&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;files/blog/chalkboard-no-query-strings.png&quot;
       alt=&quot;Bart Simpson-style chalkboard meme saying, &apos;I will not add query strings to your URLs.&apos;&quot;&gt;
  &lt;figcaption&gt;
    Created using &lt;a href=&quot;https://enufstyle.com/generators/bart/&quot;&gt;Simpsons
    Chalkboard Generator&lt;/a&gt; and &lt;a href=&quot;https://www.gimp.org/&quot;&gt;GIMP&lt;/a&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/no-query-strings.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/web.html&quot;&gt;#web&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Wander Console 0.6.0</title>
    <link href="https://susam.net/code/news/wander/0.6.0.html"/>
    <id>urn:uuid:800b3a89-946c-4c78-b575-4262f7589885</id>
    <updated>2026-05-08T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Wander Console 0.6.0 is now available.  This is the sixth release of
  Wander, a small, decentralised, self-hosted web console that lets
  visitors to your website discover interesting websites and pages
  recommended by a community of independent website owners.  To try
  it, go to &lt;a href=&quot;../../../wander/&quot;&gt;susam.net/wander/&lt;/a&gt;.
  To learn how it works and how to set it up on your own website, see
  the project
  &lt;a href=&quot;https://codeberg.org/susam/wander#readme&quot;&gt;README&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  The main change in this release is the removal of support for the
  &lt;code&gt;via&lt;/code&gt; referral query parameter, which was added to
  recommended URLs so that website owners could identify visits coming
  from a Wander Console in their access logs.  The &lt;code&gt;via&lt;/code&gt;
  query parameter was introduced in version
  &lt;a href=&quot;0.4.0.html&quot;&gt;0.4.0&lt;/a&gt; in response to
  &lt;a href=&quot;https://codeberg.org/susam/wander/issues/1#issuecomment-11795493&quot;&gt;community
  demand&lt;/a&gt;, but it turned out to be a misfeature.  Some websites
  refuse to serve web pages when arbitrary query parameters are added
  to URLs.  Although it was possible to turn this feature off via
  configuration, I would rather not keep a dubious feature that may
  prevent some pages from loading successfully.  This feature has now
  been completely removed.  See
  &lt;a href=&quot;https://chrismorgan.info/no-query-strings&quot;&gt;this excellent
  article by Chris Morgan&lt;/a&gt; to learn more about why adding arbitrary
  query parameters to URLs is a bad idea.  Commit
  &lt;a href=&quot;https://codeberg.org/susam/wander/commit/b26d77c4da9ec11b655ba64a4ae4f3af56e06370&quot;&gt;b26d77c&lt;/a&gt;
  has more details about the removal of this feature.
&lt;/p&gt;
&lt;p&gt;
  Apart from this change, there are a few minor user interface
  adjustments and fixes.  See the
  &lt;a href=&quot;https://codeberg.org/susam/wander/src/branch/main/CHANGES.md&quot;&gt;changelog&lt;/a&gt;
  for more details.
&lt;/p&gt;
&lt;p&gt;
  If you own a personal website but have not set up a Wander Console
  yet, I suggest that you consider setting one up.  You can see what
  it looks like by visiting mine at
  &lt;a href=&quot;../../../wander/&quot;&gt;/wander/&lt;/a&gt;.  To set up your
  own, follow the
  &lt;a href=&quot;https://codeberg.org/susam/wander#install&quot;&gt;installation
  instructions&lt;/a&gt; in the README.  It only involves copying two files
  to your web server, so the installation is very straightforward.
&lt;/p&gt;
&lt;p&gt;
  Also, check out our new community page called
  &lt;a href=&quot;https://susam.codeberg.page/wcn/&quot;&gt;Wander Console
  Network&lt;/a&gt;.  This page shows a recent snapshot of all known Wander
  Console instances along with the web pages they recommend.  We have
  an IRC channel too at &lt;a href=&quot;http://web.libera.chat/#wander&quot;&gt;#wander&lt;/a&gt;
  on &lt;code&gt;irc.libera.chat&lt;/code&gt; in case you are looking for a place
  to hang out with the community.
&lt;/p&gt;
&lt;p&gt;
  &lt;strong&gt;Update on 09 May 2026:&lt;/strong&gt; See the post
  &lt;a href=&quot;../../../no-query-strings.html&quot;&gt;I Will Not Add Query
  Strings to Your URLs&lt;/a&gt; for an account of how the misguided
  referral query string feature was added and how it was removed.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/code/news/wander/0.6.0.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/web.html&quot;&gt;#web&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>From RSS to Atom</title>
    <link href="https://susam.net/from-rss-to-atom.html"/>
    <id>urn:uuid:02ace576-3514-4a90-bb09-d8641aec617e</id>
    <updated>2026-05-04T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#impulse-coding&quot;&gt;Impulse Coding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#atom-entries&quot;&gt;Atom Entries&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#temporary-workaround&quot;&gt;Temporary Workaround&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#does-it-matter&quot;&gt;Does It Matter?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;impulse-coding&quot;&gt;Impulse Coding&lt;/h2&gt;
&lt;p&gt;
  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 &lt;a href=&quot;26c.html&quot;&gt;ongoing&lt;/a&gt; algebraic graph theory studies.
  That&apos;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 &lt;em&gt;impulse coding&lt;/em&gt;, a bit like impulse buying, except
  that I ended up with an Atom feed instead of a new book.
&lt;/p&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  In case you are curious, here is the Git commit where I implemented
  the change from RSS to Atom:
  &lt;a href=&quot;https://codeberg.org/susam/susam.net/commit/596e1dd&quot;&gt;596e1dd&lt;/a&gt;.
  As you might notice, a large portion of the change consists of
  replacing the &lt;code&gt;key&lt;/code&gt; attribute in each post with
  the &lt;code&gt;uuid&lt;/code&gt; attribute.  The &lt;code&gt;key&lt;/code&gt; attribute
  value was used as the value of the &lt;code&gt;&amp;lt;guid&amp;gt;&lt;/code&gt; element
  in the RSS feeds.  While an arbitrary short string could serve as
  the &lt;code&gt;&amp;lt;guid&amp;gt;&lt;/code&gt; element for the items in an RSS feed,
  the &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; 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 wrote the following shell command to replace all
  occurrences of the &lt;code&gt;key&lt;/code&gt; attribute
  with &lt;code&gt;uuid&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -type f -name &apos;*.html&apos; -exec sh -c &apos;
  for f do
    sed &quot;s/^&amp;lt;!-- key: .* --&amp;gt;/&amp;lt;!-- uuid: $(uuidgen) --&amp;gt;/g&quot; &quot;$f&quot; &amp;gt; tmp &amp;amp;&amp;amp;
    mv tmp &quot;$f&quot;
  done
&apos; sh {} +&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  The rest of the changes went into the
  &lt;a href=&quot;https://codeberg.org/susam/susam.net/src/tag/0.8.0/layout/tag/feed.xml&quot;&gt;feed&lt;/a&gt;
  &lt;a href=&quot;https://codeberg.org/susam/susam.net/src/tag/0.8.0/layout/tag/item.xml&quot;&gt;templates&lt;/a&gt;
  and the Common Lisp &lt;a href=&quot;https://codeberg.org/susam/susam.net/src/tag/0.8.0/site.lisp&quot;&gt;program&lt;/a&gt;
  that statically generates the feeds along with the website.
&lt;/p&gt;
&lt;p&gt;
  For examples of the resulting feeds, see
  &lt;a href=&quot;feed.xml&quot;&gt;feed.xml&lt;/a&gt; and
  &lt;a href=&quot;tag/absurd.xml&quot;&gt;absurd.xml&lt;/a&gt;.  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 &lt;a href=&quot;tag/&quot;&gt;tag&lt;/a&gt;.  As of today, the main feed
  at &lt;a href=&quot;feed.xml&quot;&gt;feed.xml&lt;/a&gt; contains only two entries even
  though this website has over &lt;a href=&quot;pages.html&quot;&gt;200 pages&lt;/a&gt;.  I
  explain the reason later in
  &lt;a href=&quot;#temporary-workaround&quot;&gt;Temporary Workaround&lt;/a&gt;.
&lt;/p&gt;
&lt;h2 id=&quot;atom-entries&quot;&gt;Atom Entries&lt;/h2&gt;
&lt;p&gt;
  Here is an example Atom entry from my feeds:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;entry&amp;gt;
  &amp;lt;title&amp;gt;A4 Paper Stories&amp;lt;/title&amp;gt;
  &amp;lt;link href=&quot;https://susam.net/a4-paper-stories.html&quot;/&amp;gt;
  &amp;lt;id&amp;gt;urn:uuid:06e5304d-c242-481c-bf94-e23b019b0a36&amp;lt;/id&amp;gt;
  &amp;lt;updated&amp;gt;2026-01-06T00:00:00Z&amp;lt;/updated&amp;gt;
  &amp;lt;content type=&quot;html&quot;&amp;gt;
    &amp;amp;lt;p&amp;amp;gt;I sometimes resort to a rather common measuring ...
  &amp;lt;/content&amp;gt;
&amp;lt;/entry&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  The ellipsis (&lt;code&gt;...&lt;/code&gt;) denotes content I have omitted for
  the sake of brevity.
&lt;/p&gt;
&lt;p&gt;
  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
  &lt;code&gt;date-time&lt;/code&gt; format specified in
  &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc3339.html&quot;&gt;RFC 3339&lt;/a&gt;,
  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 &lt;code&gt;text&lt;/code&gt;,
  &lt;code&gt;html&lt;/code&gt; and &lt;code&gt;xhtml&lt;/code&gt;.  If it is
  &lt;code&gt;html&lt;/code&gt;, the content should be escaped HTML.  If it is
  &lt;code&gt;xhtml&lt;/code&gt;, the content should be an
  XHTML &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element containing valid XHTML.
  Explicit content type support is likely the biggest advantage of
  Atom over RSS.  In comparison,
  &lt;a href=&quot;https://www.rssboard.org/rss-specification&quot;&gt;RSS 2.0&lt;/a&gt;
  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.
&lt;/p&gt;
&lt;h2 id=&quot;temporary-workaround&quot;&gt;Temporary Workaround&lt;/h2&gt;
&lt;p&gt;
  As I mentioned before, as of today, the
  &lt;a href=&quot;feed.xml&quot;&gt;main feed&lt;/a&gt; contains only two entries.  That&apos;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&apos;s requirement that each entry&apos;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
  &lt;a href=&quot;https://news.ycombinator.com/item?id=40680890&quot;&gt;complaints&lt;/a&gt;
  about this in the past.  So I was careful this time.  I have a little
  &lt;a href=&quot;https://codeberg.org/susam/susam.net/src/tag/0.8.0/site.lisp#L1520-L1525&quot;&gt;one-liner
  workaround&lt;/a&gt; in my site generator to exclude posts published before
  this change from the feed.
&lt;/p&gt;
&lt;p&gt;
  That was the only workaround I had to implement.  Fortunately, my
  feed file had a neutral name like &lt;code&gt;feed.xml&lt;/code&gt;, rather than
  a format-specific name like &lt;code&gt;rss.xml&lt;/code&gt;, so I could avoid a
  URL change and the subsequent overhead of setting up redirects.
&lt;/p&gt;
&lt;h2 id=&quot;does-it-matter&quot;&gt;Does It Matter?&lt;/h2&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  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.
&lt;/p&gt;
&lt;p&gt;
  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 &lt;code&gt;referer&lt;/code&gt; (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.
&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;
  I found these three resources useful while switching to Atom feeds:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;a href=&quot;https://validator.w3.org/feed/docs/atom.html&quot;&gt;W3C Introduction to Atom&lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a href=&quot;https://validator.w3.org/feed/&quot;&gt;W3C Feed Validation Service&lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc4287&quot;&gt;RFC 4287&lt;/a&gt;: The Atom Syndication Format
  &lt;/li&gt;
&lt;/ul&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/from-rss-to-atom.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/web.html&quot;&gt;#web&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>QuickQWERTY 1.2.3</title>
    <link href="https://susam.net/code/news/quickqwerty/1.2.3.html"/>
    <id>urn:uuid:d1c2f6bb-8a47-4785-959b-167b8c1fa13a</id>
    <updated>2026-05-03T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  &lt;a href=&quot;../../../quickqwerty.html&quot;&gt;QuickQWERTY 1.2.3&lt;/a&gt; is now
  available.  QuickQWERTY is a web-based touch typing tutor for QWERTY
  keyboards that runs directly in the browser.
&lt;/p&gt;
&lt;p&gt;
  This release includes two small bug fixes.  In the
  &lt;a href=&quot;1.2.2.html&quot;&gt;previous release&lt;/a&gt;, QuickQWERTY source code
  management moved from GitHub to Codeberg.  During that update, the
  licence link in the footer was updated incorrectly.  The broken
  licence link has now been fixed.
&lt;/p&gt;
&lt;p&gt;
  Further, there was a minor bug that caused a redundant dialog box to
  appear while switching between 6-7 split and 5-6 split.  Units 16 to
  20 contain two links labeled &apos;6-7 split&apos; and &apos;5-6 split&apos; which allow
  you to select how you want to split the number keys between left and
  right hands.  Clicking either of those links brings up a dialog that
  explains what the two splits mean and prompts you to confirm in
  order to make the switch.  Say, the &apos;6-7 split&apos; was already the
  chosen split.  Clicking the &apos;6-7 split&apos; label triggered the dialog
  box unnecessarily.  A dialog was unnecessary in that case since if
  you were already on the &apos;6-7 split&apos;, clicking the &apos;6-7 split&apos; label
  resulted in no switch.  This unnecessary dialog has now been
  eliminated.
&lt;/p&gt;
&lt;p&gt;
  To try out QuickQWERTY, please visit
  &lt;a href=&quot;../../../quickqwerty.html&quot;&gt;quickqwerty.html&lt;/a&gt;.  The
  source code of QuickQWERTY is available under the terms of the MIT
  licence at &lt;a href=&quot;https://codeberg.org/susam/quickqwerty&quot;&gt;codeberg.org/susam/quickqwerty&lt;/a&gt;.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/code/news/quickqwerty/1.2.3.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/web.html&quot;&gt;#web&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/programming.html&quot;&gt;#programming&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
</feed>
