Grasp

How to capture information from your browser and stay sane

This is not the post I was gonna start writing with. It was supposed to be something a bit more abstract and pure, but oh well.

Trigger warning: if you are a kind of person that doesn’t care about their browser bookmarks at all and happily loses them after switching to new computer, you might be shocked and perhaps repulsed by the level of elaboration I’m taking up here. Please sit tight, breathe and remember that I don’t judge you!

So, let’s talk about browser bookmarks.

History

I’ve always loved my bookmarks and been keeping, rereading and moving them around since high school. I also tend to be very organized in terms of meta information, so every bookmark would eventually end up in a category/folder. Of course there are obstacles.

First of all, Chromium bookmark adding menu was a bit shit and still is. You get to choose among the five most recently used folders only; if you want anything specific, you have to mouse click all the way through (using Tab on keyboard with my 100+ folders was just not doable). You can’t search when you add bookmark either. Yes, I know, it’s not meant for geeks, it’s for normal people who love mouseclicks. I’m still puzzled by how people who develop that stuff use their own product though.

These days Chrome has got chrome.bookmarks api, which I’d imagine allows you to implement your own bookmark manager. Back in 2012, it didn’t exist though.

I was a bit less fussy back then so I was kind of okay with that. Until one day the disaster appended. I realized I couldn’t decide which folder did the bookmark belong to. That was pretty disturbing, so I started looking for alternatives. I realized I needed something like tags and turned out Firefox had that feature for ages. So I switched the browser.

Firefox was noticeably slower and greedier in terms of RAM (no Rust in Firefox in 2012!). And few months later I got my first Android phone and realized that Firefox didn’t support syncing tags with Android (it still doesn’t).

Until I found out about Pinboard! If you wanna borrow one thing from this post, please try and use that, it’s really awesome. It has solved almost all of my issues:

  • you can easily add new bookmarks, tag them and it would be synced across all your browsers and devices
  • you can mark them private and public, and search in other people’s bookmarks
  • what is more, you can add notes for some context about your bookmarks!

I’ve had few happy years with Pinboard. Until I started getting more serious about information processing and my knowledge management.

Long story short, I found out that I spend a lot of time moving bookmarks scattered across pinboard into my personal plaintext wiki to give it a bit more structure, fulltext search and easier access. I’ve also started using Org mode and in particular, capture and refile. Once you are used to that, moving information manually by copy-pasting is just plain torture. You know, life is too short for that shit.

Eh? Capture? Refile?

It’s hard to explain, for me it took several iterations to adopt these. In essence, you can ‘capture’, that is, copy/create piece of information like a url, quote, your thought or anything else and store in a text file for further processing which you can do it later. It’s meant to be with as little interruptions as possible, merely to persist the information. Typically, in emacs it’s a matter of pressing a keystroke, making you note and pressing a keystroke to finalize. You can do it as fast as you think/type and then immediately get back to what you were working on.

You can look up quite a few different setups online: typical demo (till 4:10). The concept doesn’t really have to be restricted to org mode, though. Funny enough, before I ran into org-capture, I had a keybinding to open Vim in the insert mode against my notes.txt file.

It sounds really abstract.

Sure. Let me be a bit more specific. My typical scenario is doing some research in the broad sense, e.g. shopping or looking for a property to rent or learning.

Imagine you’ve got a bit of time during your lunch break at work and want to spend it learning some representation theory. For me (and I’d imagine for many people), it makes little sense doing that just for 20 minutes, your mind is diffused, and you need time to gain back some context before doing productive learning.

But you could at least skim through some articles and highlight things to think about later when you got more time which you can dedicate solely for learning. So you read through the different articles and blog posts, and you want to highlight things and potentially add todo items for further googling/thinking. You don’t have time to think about them now, you just want to make sure you think about them later, e.g. see screenshot.

So you go through the article and annotate it/add points to think on. You want to do it as fast as you can read without distracting on copy-pasting the information and trying to organize it. Later, when you got time, you just search everything marked with the tag reprtheory and in your capture.org file you find an entry like that:

* [2019-02-09 Sat 14:54] Special unitary group - Wikipedia   :reprtheory:physics:
https://en.wikipedia.org/wiki/Special_unitary_group
Selection:
here is a 2:1 homomorphism from SU(2) to SO(3).
Comment:
Why do they always mention that? Is that important?

, which you can further action on. Perhaps you’ve figured it out already, so you can just discard it. Or you want to convert it into a TODO, give it a priority and refile somewhere more appropriate. What’s awesome is that at the time of capture it immediately becomes searchable and indexable as any plaintext would without any extra effort (unlike if you added it to browser bookmarks/pinboard).

Ok, I’m sold. How do I do it?

So, you want to integrate your browser with your knowledge repository and capture things straight into your capture.org file. Sounds trivial, right?

For a while I used org-capture extension, that was relying on setting up a special mime type handler (e.g. emacs://) and an always running emacs daemon. Until one day I got very sad when few days of captured link and selected text were gone because one of these things stopped working for some reason. People seem to have issues setting up all this to work, and of course, you can’t have feedback from OS mime handler, so you can never know whether it has succeeded at all.

I realized I didn’t want to rely on emacs running all the time, on its templates or anything like that. I just want to reliably append stuff (formatted as org-mode) to the text file, that’s not too much to ask. An obvious solution is to get rid of the mime type handler and just write to the file system from Chrome extension directly. This is, of course something you can’t do in modern browsers. There is an API in Chrome for that, and you’ve got two options:

  • write a file to a sandbox within a browser. Not an option for my purposes.
  • select a path via ‘save as’ GUI dialog and write it. Disgusting, definitely not an option.

So after a while I realized something else has to write to the file. And that something else could be a local http server. The extension sends the request, the local backend writes the entry and responds with success/error, which can be passed onto UI notification, so you will always know if something failed. After a bit of coding, Grasp was born.

What makes Grasp better?

Quite a few things actually!

  • it’s reliable and you will get an error notification if you failed to capture

  • it supports capturing selected text, adding comment and tags

  • you can capture anywhere: it doesn’t care whether you have emacs installed at all, and doesn’t have to be org mode file

  • unlike org-protocol which only supports url, title and ‘everything else’, the capture template syntax can be extended to include anything you want, e.g. currently it also supports tags, comment and selection.

  • it can run anywhere, e.g. you can run it the server on your VPS and access remotely if you are browsing on a computer you can’t sync your capture file onto.

    I might even try and see if it can be ported as Android Firefox addon.

Implementing

Few random things I learnt while implementing:

  • flow and eslint are good

    Trivial to integrate and they make the dreaded JS programming pretty manageable and akin to Python.

    Turns out Flow even it supports comment types, kinda like python/mypy. That must be very beneficial for people trying to integrate it. Just imagine that you can slowly convert your whole codebase into type safe code before your coworkers realize what’s happened!

  • Webpack is good

    Used it mainly to strip off Flow annotations and convert code into something chrome would accept. However it’s also helpful for merging the extension manifest so you could build browser-specific versions.

  • fun fact: node_modules takes almost 200Mb of disk space, and I tried my best to use as less dependencies as possible. Almost all are dev dependencies, so the extension itself is still tiny.

  • Firefox and Chrome use more or less same browser APIs these days! The only thing I had to fix while porting to Firefox were notifications.

  • publishing to Chrome store is more tedious than I imagined, e.g.
    • they want screenshots exactly 1280x800 or 640x400. Do people have some sort of scripts to cut their screenshots automatically for them or what?
    • there are two interfaces (‘old’ and ‘new’), which are sometimes doing different things
    • it’s generally pretty flaky, sometimes when you update the extension, old meta about your extension disappears and you have to copy it manually. I find it pretty mean to developers.

    I guess I should just use the API for publishing.

  • publishing to addons.mozilla.org is super fast and easy

  • firefox hotkeys are not configurable

    I still find it very hard to believe. Has it always been like that? How do people cope with it?

    UPD: it’s possible to configure them now!

  • CI is a bit tedious

    My pretty minimal config, is quite long. I’m quite used to to CIs, but I wonder how often are people discouraged by that, it’s got to be easier. Perhaps Auto DevOps from gitlab solves it?
  • communicating with localhost made everything so much simpler. I’ve already converted another thing I am working on to use that instead of trying to utilize local storage/internal database and it works flawlessly!

Feedback

I actually think it’s the first thing I solely implemented, prepared and shared for other people to use. As expected, it actually took more time than sketching a prototype that worked for me. But it feels so great when people reach you and say that they managed to run it even on Windows without any issues when no other existing methods could do that.

What’s next?

I’m gonna look up what are Markdown people using for capturing information, add few templates and spread the good stuff. I’m excited!


Discussion: