Geekmarks

Hi everyone! So I wrote a new bookmarking service: Geekmarks, it's free and open-source (GitHub).

We already have a lot of bookmarking services, so why bother writing another one? Good question.

Rationale

In short, I want my bookmarking service:

  • To be very quick to use;
  • To provide a way to organize my bookmarks in a powerful way.

I tried a lot of existing bookmarking services, and I wasn't satisfied by any of them, for a variety of reasons.

Let me elaborate on the organization part first. The simplest way to organize bookmarks is to introduce folders to group them. This still poses a well-known problem though: some bookmarks can logically belong to multiple folders. In order to address this issue, some services use tags: now we can tag a bookmark with more than one tag. So far so good.

Now, assume I have a generic tag programming, and a couple of more specific tags: python and c. I definitely want my bookmarking service to be smart enough to figure that if I tag some article with either python or c, it means programming as well; I don't want to add the tag programming manually every single time. So, what we need is a hierarchy of tags. Surprisingly enough, I failed to find a service which would support that.

This hierarchical tags thing was a major motivation for me to start Geekmarks.

Another important thing is that I want bookmarking service to be very quick to use. I don't want to go through these heavy user interfaces and look at all the eye candy. In my daily life I just want to either add a bookmark or find one, and I want to do that quickly: like, just a few keystrokes, and I'm done.

And last but not least, I love open-source. So, meet Geekmarks! A free, open-source, API-driven bookmarking service.

Overview

There's a backend (written in Go and PostgreSQL) which exposes a RESTful API, and various clients which talk to the backend.

Data storage

All the data is stored on the server; client does not store anything. Even when the user enters a tag name, and UI shows the autocomplete menu with matching tags, the menu contents are loaded from the server.

Of course, this has both advantages and disadvantages.

The good thing is that the arcitecthure is “clean”: clients are dumb, server is the one who does all the job. Among other things, this simplifies the process of writing new clients, and all the data is automatically synchronized between all user's clients with no extra effort.

Now let me consider disadvantages and argue why I still opted to use this design.

  • Some users might have a strong opinion against storing their bookmarks (as well as any other data) on a third-party server; they want to control the data storage. This part is solved by the fact that everything in Geekmarks is open-source: one can easily deploy the backend to their own server, or even run it locally on the laptop; and adjust the backend URL in the client settings. Now, everything is under the user's control.
  • Other users might be fine with storing bookmarks on a third-party sever, but they might be afraid of losing all their data if the service stops working for whatever reason. In order to address this issue, I'm going to implement import/export of all the account's data. So, one might write a short script with a single curl command which fetches JSON data with all tags and bookmarks and saves it locally, and run this script regularly (via crontab or similar things). Now, the data is backed up, and if something bad happens with the server, the user can resort to deploying Geekmarks backend to their own server or locally, and import all the data there.
  • One more possible claim is that the tool won't work offline. While this is true, it shouldn't be a major concern, because the whole point of Geekmarks is to store URLs, so even if you can get the previously saved URL offline, you'll anyway need the Internet connection in order to visit the webpage by this URL!
  • And the last thing I can think of is that constantly accessing the server for this and that is slower than just storing everything locally. Of course it is slower, but it doesn't affect user experience too much: all the communication is going via the websocket, and, from my experience, the user rarely needs to wait more than 150ms (for me, it's usually less than 70ms actually).

Project status

Backend is thoroughly tested and is very stable. API will be also frozen soon.

Client implementation, however, is not in a particularly good shape: it's a Chrome extension, and it's only a proof of concept. It's just barely good enough: it provides all the features and it's completely usable, but it's written in probably not a very good manner, its appearance is kinda rough, etc.

My plan is to rewrite the client in Angular 2, or maybe React, and hopefully I'll be able to factor out the most part and reuse it for many kinds of clients: web interface, browser extensions, and mobile phone apps (via Native Script or React Native). But that will be a long story, since I'm not really a frontend guy, and I'll need to learn a lot.

Demo

After installing the Chrome extension, click on the “g” icon:

Log in (via Google account), and when it's done, menu will look as follows:

Now, on any page you want to bookmark, click “Create bookmark” from the menu (or use a hotkey; I personally use Shift+Ctrl+B), enter tags for your new bookmark, and save it. Tags which don't yet exist will be created on the fly.

When you do that for the first time, it might look as follows:

Later, when you have more tags, the process of adding a new bookmark will be faster, like this:

And this is how you find your bookmarks, after all (I use a Ctrl+B hotkey for that):

Tips

Untagged bookmarks

Being able to organize bookmarks with hierarchical tags is really nice, but sometimes I'm too busy and I don't want to think carefully about where to put my bookmark; instead, I just want to quickly add it somewhere, and postpone the proper tagging for later. This is supported: when one wants to add current page as an untagged bookmark, it's as easy as Ctrl+Shift+B, Enter (provided that the keyboard shortcut is Ctrl+Shift+B).

Next time, when “Find bookmark” dialog is opened, all untagged bookmarks are shown immediately, before the user enters any tag; so, the user won't forget to tag them properly later.

Tag aliases

When editing a tag, one can specify multiple comma-separated names, and all of them will refer to the same tag. It's convenient in many cases, e.g. go and golang, jobs and careers, etc.

Note on hierarchical tags

I really love the hierarchical tags idea, and as I said, it was a major motivation for me to start Geekmarks. However, one should not misuse it.

For example, it's perfectly fine to place golang under programming, because Go, indeed, always implies programming.

But consider the case when we want to store something about terminal emulators, and we want to be more specific: terminal emulators which work under Linux. It would be a bad idea to create a hierarchy like /terminal/linux, because linux, of course, does not necessarily imply terminal. If we go with this, then we'll eventually end up with a bunch of tags like /terminal/linux, /programming/linux, /whatever-else/linux; and when we type linux in the tags input field, we'll get multiple tags with the same name, and we won't be able to just get “everything related to Linux”.

Instead, /linux should be a standalone tag, and the URL which describes something about terminal emulator under Linux should be tagged with both /terminal and /linux.

So, the rule of thumb is: before placing a tag foo under bar, ask yourself: does foo always imply bar? If yes, then go on. If no, then foo should be a separate tag.

That said, if you're unsure about how to arrange your tags, don't worry too much about it, since you can easily move your tags around later, and your bookmarks will be retagged appropriately.

Plans

I don't really know when I'll be able to implement all of it, but nevertheless, this is what I'd like to have sooner or later:

  • Firefox extension;
  • Client for Android (and probably iOS);
  • Authentication via something other than Google;
  • Filter bookmarks not only by tags, but also by title/url;
  • Export/Import of all the account's data;
  • Add numeric “rating” to tags, and sort bookmarks accordingly to the rating of the tags it's tagged with.

Discussion

Karan Rajpal, 2017/02/15 06:14

This is pretty cool. Just what I was looking for :D Will start migrating to it now!

Dmitry Frank, 2017/02/15 09:36

Glad you liked, thanks for the comment! :)

David Sandquist, 2017/02/15 11:15

This looks great! I badly need a working firefox front end though to be able to move over to this. Secondly, is it possible to make snapshots of the bookmarks for backups/history etc?

Dmitry Frank, 2017/02/15 11:25

Thanks for the feedback!

Yeah I plan to implement a firefox extension as well, not sure how should I prioritize things though.

W.r.t. snapshots: as I indicated in the article, export/import is surely planned, and will be implemented rather soon: one will be able to write a script with basically a single curl command which will fetch all the account's data and store locally. Then, this script can be executed via cron or similar things.

Kim Meisel, 2017/02/15 11:25

is a bookmarklet out there?

Dmitry Frank, 2017/02/15 11:27

Sorry, what exactly do you mean by bookmarklet?

Kim Meisel, 2017/02/15 17:17

https://de.wikipedia.org/wiki/Bookmarklet

Nikita Voloboev, 2017/02/15 11:57

Interesting idea. I decided to keep all my bookmarks and notes in a mind map. (https://github.com/nikitavoloboev/research).

I really like the format of it as I can have both tags and structure and everything is connected and public to the world.

Martin Clausen½, 2017/02/15 13:13

Import from Pinboard would be greatly appreciated. Their support is unresponsive and the API is broken. Renaming of tags would also be very useful.

Dmitry Frank, 2017/02/15 13:15

Thanks for the comment. Honestly, I've never heard of Pinboard before, so I can't say anything about it at the moment, I'll look into this.

Renaming of tags is surely possible: you can open tags tree, then mouseover your tag, and click the “edit” icon which will appear at the right side. You can change the name, or even specify multiple names (aliases).

Habib Alamin, 2017/02/15 16:44

I've been thinking about the same idea of “hierarchical tags” in the context of OS X's tags feature. I wonder if that just brings up the same problems as direct hierarchies, or if moving the hierarchy to the tag level fixes a lot of those problems.

Dmitry Frank, 2017/02/15 16:55

To me, it does solve these problems: if I understand you correctly, the problem with direct hierarchy you're talking about is that the item might belong to many places. By tagging the item with a few tags, we effectively put the item in many places in the hierarchy. It's a kind of equivalent of (hard) links in the filesystem.

AxelTheGerman, 2017/02/15 18:16

really like the concept of hierarchical tags (and open source which allows self hosting - even though I'm not intending to do so right now) Been using Pinboard so far - fairly similar - but would consider switching. Keep up the good work. UI looks definitely good enough for now. Firefox/mobile(android) access would be great

Dmitry Frank, 2017/02/15 23:48

Thanks for the feedback.

It's actually weird that I missed pinboard before, but you mentioned that you would consider switching. Of course I'm curious to hear the reasons: what's about pinboard that you aren't satisfied with?

As to other clients, yeah, hopefully I'll get time for that.

Tom Fawcett, 2017/02/15 21:36

This looks very good! But considering that it's free and it consumes your server-side resources, will it remain free?

Dmitry Frank, 2017/02/15 23:54

Hi, thanks for the feedback!

I can't say 100% sure that my hosted server will remain free, but one of the good parts about open source thing is that people can self-host it. As I mentioned in the article, one could deploy it to their own server, or even locally to the laptop, and don't rely on my server.

The only missing piece to be implemented for it is export/import, and it definitely will be implemented: one can start with my server, and if later they decide to move to the self-hosted one, for whatever reason, they could export all the data from my server, then import to theirs, and that's it.

LucStepniewski, 2017/02/16 07:19

Geekmarks looks like a total copy of Shaarli: https://github.com/shaarli/shaarli/

Dmitry Frank, 2017/02/16 09:01

As far as I know, there's no hierarchical tags in Shaarli. And one has to install it on their own server, whereas with Geekmarks one can, but does not have to.

Olivier Mengué, 2017/02/16 09:07

I can't wait for the Swagger spec for your API!

A major feature for a bookmark service is to help to keep the bookmarks relevant: check availability, report 404s to the user, replace permanent redirects (301), detect duplicates and save the canonical one (rel=“canonical”).

Dmitry Frank, 2017/02/20 08:16

Unfortunately, Swagger is too limited: firstly, it does not support multiple schemas for the request (which depend on query parameter, shape in my case), and secondly, it does not support wildcard paths (e.g. in Geekmarks /api/tags, /api/tags/foo and /api/tags/foo/bar/baz are all valid paths).

The former could be worked around (see https://github.com/OAI/OpenAPI-Specification/issues/146#issuecomment-117288707), the latter cannot, and it's even unclear if it will be supported in the future (see https://github.com/OAI/OpenAPI-Specification/issues/892).

Maybe I'll have to deviate from the spec and use modified version of swagger-ui… But I'm not sure if it's a good idea.

Dmitry Frank, 2017/04/23 19:33

Done :) https://geekmarks.dmitryfrank.com/swagger/

Nachiket Vartak, 2017/02/16 11:04

Are the bookmarks encrypted server side ?

Dmitry Frank, 2017/02/16 11:24

No.

Julyan Davey, 2017/02/17 08:23

Love it! Started putting in a load of bookmarks already. One improvement that would be amazing is if you could search generally and not just by tag.

Dmitry Frank, 2017/02/17 10:51

Thanks for the feedback! Yes, as I mentioned in the Plans section, I want to implement bookmarks filtering not only by tags, but also by the title and/or URL.

Julyan Davey, 2017/02/20 11:18

Great stuff!

I look forward to it.

If you want any contributions I can help out!

Cheers

Enter your comment (please, English only). Wiki syntax is allowed:
   __      __  ____    ____     __
  / /  __ / / / __ \  / __/ __ / /
 / /__/ // / / /_/ / _\ \  / // / 
/____/\___/  \___\_\/___/  \___/
 
projects/geekmarks/article.txt · Last modified: 2017/04/23 19:32 by dfrank
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0