Fragment design questions

2016-08-05

I wanted to jot down a couple of notes from a discussion I had with Conor that aimed to solve a couple of related problems. Namely:

  1. How do we link people to a page and automatically scope the sidebar to a specific group? In particular, how do we communicate to the sidebar application which group to select?

  2. What do we want to do about the issue where visiting a Genius proxy page (which ends with the URL fragment #annotations:<annotationid>) unintentionally loads our extension?

  3. How do both of these things look in a world in which users have multiple identities active in the sidebar (in the short term, through 3rd-party groups)?

To frame the discussion, I drew a little picture of how we think our scope control might evolve as we add support for multiple accounts in the sidebar:

Diagram of Hypothesis scope control, showing checkboxes beside possible scopes to toggle them visible and hidden, and identifying the multiple identities the user has active at the same time
Diagram of Hypothesis scope control, showing checkboxes beside possible scopes to toggle them visible and hidden, and identifying the multiple identities the user has active at the same time

In this picture, you can see that annotation “groups” are now associated with an annotation service, and they can be added and removed from view independently of one another by toggling checkboxes. Each “group” has a unique id, which might be random (e.g. group:K1p4yo) or might be associated with a specific unique user (e.g. acct:jill@hypothes.is).

The idea we played around with was that this scope control is just another interface to interact with the underlying query that’s used to fetch annotations from each service.

Let’s assume that in addition to the scope selection shown in the picture, the user has also further filtered their results with the following query:

tag:foo my thoughts

That is, they only want to see annotations within the three selected scopes, which are tagged with “foo” and which match the free-text query “my thoughts”.

In this case, perhaps we’d send two queries – one to each service – which looked something like the following.

To Hypothesis:

group:K1p4yo tag:foo my thoughts

To eLife1:

group:LeZj8k group:XnGn8B tag:foo my thoughts

This got us thinking about direct link URLs. Specifically, about whether we could encode an entire query, if necessary, in the URL fragment that represents a “direct link”2.

Image showing the relationship between a search query as seen by a user, the query string as passed back to the server, and a possible condensed version of that query for use in a URL fragment. The URL fragment also contains the domain of the annotation service, hypothes.is, as a namespacing element.
Image showing the relationship between a search query as seen by a user, the query string as passed back to the server, and a possible condensed version of that query for use in a URL fragment. The URL fragment also contains the domain of the annotation service, hypothes.is, as a namespacing element.

Under this model, we could add support for a new query term which selected single annotations by ID, so that we could map the query

annotation:x5hKbFsPEeaod7cRA9bKpQ

to the fragment

...#hypothes.is:a=x5hKbFsPEeaod7cRA9bKpQ

as compared with what we use currently

...#annotations:x5hKbFsPEeaod7cRA9bKpQ

Does this make sense? Can you see major problems with this approach?


  1. An annotation necessarily cannot be in multiple groups, so the multiple “group:” predicates resolve to “either group A OR group B.”

  2. Just for the moment we’re ignoring the role of bouncer.