Designing Nice Annotation URLs

While I’m working on web annotation for Moodle, I want the solution to be more broadly applicable. To that end, I have been working on making the service REST. A big part of that is developing sensible URLs, preferable ones that an ordinary human being can read and understand. I haven’t spent a lot of time designing URLs in the past, and I haven’t run across much in the way of good advice on the subject. One problem is that URLs shouldn’t change. This conflicts with the common Worse is Better practice of the web: first make it work, then make it work well.

URLs are used to refer to specific resources (usually web pages) in the system. Before choosing the URLs, it’s important to understand what those resources might be. In practice, users aren’t interested in individual annotations, but in lists of them. Here are some likely scenarios:

  1. a user retrieves all of his or her annotations
  2. someone lists all of the public annotations for a specific user
  3. a forum post is displayed with all associated annotations
  4. a user subscribes to a syndication feed of all public annotations in a particular discussion

These sets of annotations are all resources which deserve their own URLs. The simple approach might be to implement URLs like the following:

  1. /moodle/annotations
  2. /moodle/annotations?user=geof
  3. /moodle/annotations?forum=21&post=3
  4. /moodle/annotations.rss?forum=21

These are easy to implement, but they’re not very expressive. What if we want to annotate something that isn’t a forum post? We could end up with a huge number of confusing URL formats and query parameters, each of which requires its own implementation in the annotation service. To make annotations generic, the obvious thing to do is to associate each one with a URL. But then we end up with annotation URLs like this:


Actually, I lie. The URL would need to be encoded:


That’s nasty. Furthermore, query strings are best avoided: they’re hard to read, hard to remember, hard to predict, and they are tightly tied to the implementation. It would be cool if we could still use the URL of the annotated document, but without encoding it, like this:


This is clear and succinct. Even better, it can be extended. For example, to narrow down the list to public annotations by geof we could have a URL like this:


A more inclusive listing is easy to reference by removing part of the URL. For example, to list all annotations for posts in forum 21 the URL might look like:


I actually implemented most of this, but I unrolled it. The problem is the actual structure of Moodle URLs, like this one to forum thread 21:


I don’t see a clean way to work with URLs like this, so I reverted to the query string approach. I could have used query-free URLs internally and created mappings, but that is weird and rather presumptuous. It also requires apache mod_redirect directives to make eveyrthing work, and that could conflict with other Moodle design features. This is natural: annotations are mixins, not an independent feature. But messing with Moodle URLs is best left to the core developers.