My home-cooked app for online bookmarks

A screenshot of the homepage of my DIY online bookmarking app. The page displays a search bar with the text 'font' typed in and tags 'webdesign, css' above it. Below the search bar, there are search results related to fonts, each with a title, URL, and tags. Examples include 'More than you ever wanted to know about font loading on the web' and 'Web Font Specimen.' To the right, there is a list of 'Top Tags' including 'css (117)', 'webdesign (117)', 'framework (36)', 'dev (26)', and others. At the top, there is a button labeled 'Add Bookmark.'
I did a bit of a design refresh

Two years ago this month, I decided to make my own little app for keeping bookmarks. I’m a longtime customer of Pinboard, but I was becoming frustrated with errors in its archival functionally and, in general, it felt cumbersome to browse the way I wanted to. I decided I wanted to make something myself to fill this role.

I didn’t originally plan to release the code to the public. It’s a home-cooked app and I knew it was going to be a bit rough around the edges. But as I finished it, I figured it was good enough to offer the code as-is on GitHub.

I’ve been using it ever since and over the last month or so, I’ve made some significant improvements. I think it is finally time for me to write about it.

If you don’t care to read anymore about it but want to check it out, head over to the blakewatson/bookmarks GitHub page and check out the readme. It has instructions for setting up the app.

I cover the design and intention of the app in the readme, so some of this article will come straight from that.

Features at a glance

Based on Pinboard but with some big differences

My app is somewhat modeled on Pinboard because despite wanting something of my own, I still think Pinboard is a good app. There are some pretty big differences, though.

I don’t really care about sharing my bookmarks so that social aspect is totally missing from my app. I could see myself possibly adding a way to make public listings of bookmarks at some point, though.

My app is not as robust as Pinboard. Pinboard is battle-tested and used by many. My app works for me, but is missing some of the affordances that Pinboard offers for the real pack rats out there.

For example, it just occurred to me that I don’t know what will happen if you try to add a tag with a really long name. I assume it will break the UI. Rip.

If I remember correctly, Pinboard does some cool stuff with tag groups or parent tags or something. There is none of that here. It is a simplistic tag implementation.

I have a few thousand bookmarks and the app runs fine on my admittedly high end machines. Pinboard is much more efficient at handling huge numbers of bookmarks whereas I do some inefficient things in the name of a fast frontend experience. This is something I could see myself improving over time as I accumulate more bookmarks.

How to use it

This is a NodeJS project so you will need to have a Node server. Other than that, there isn’t a lot of complicated architecture going on. It’s mostly just shuttling JSON back and forth between the server and the browser.

I have setup instructions over on the GitHub page. I recently (yesterday) added an init script that you can run to make setup as easy as possible. If you don’t care about archiving bookmarks to the Wayback Machine, you don’t need to do any configuration beyond running init.

The readme should cover it, so I won’t go into any further detail here. If you do happen to follow my instructions to set up the app, let me know if they were helpful and or how I can improve them.

Adding bookmarks quickly

Being able to quickly add bookmarks is a must-have feature. Otherwise I would never use it and this whole endeavor would be pointless. With Pinboard, there were multiple bookmarklet and browser extension options and I knew I needed something to replace those.

I decided to go with a bookmarklet. It passes info to the app via the query string. That pre-populates the create form.

Screenshot of the add-bookmark form. It is pre populated with a URL from the webcomic xkcd. The form includes fields for Title, URL, Description, and Tags. The Title field contains 'xkcd: Fluid Speech,' the URL field contains 'https://xkcd.com/2942/', the Description field contains 'A funny comic about how people streamline the pronunciation of phrases,' and the Tags field contains 'funny.' There are two buttons at the bottom: 'Cancel' and 'Save Bookmark.'

The tags field will offer autocomplete suggestions that you can select using the mouse or keyboard.

A screenshot of the tags autocompletion menu of the app. The Tags field contains the letter 'f', and the dropdown menu shows five suggestions: 'font (81)', 'framework (66)', 'fun (62)', 'friends (19)', and 'funny (10)'.

Development notes

There are probably a million different ways you could go about making something like this. As a person who enjoys the frontend more than the backend, my apps tend to have pretty simple backend architectures that are primarily trying to make data persistence as easy as possible. That’s the same for this one, with a little bit of added complexity in order to implement bookmark archival on Wayback Machine.

Backend

I usually go with PHP because I have a bit more experience with it than other backend languages. But for whatever reason I chose NodeJS and Express for this one. I can’t even remember why at this point. I’m sure there was a reason. Probably.

Mostly it’s a matter of saving everything to JSON. I didn’t really feel like passing searches to the backend, so I just pass the entire JSON data store to the frontend and perform searches on it there. I cache everything in localStorage so that startup of the app is quick. There is a point at which this method is going to fail and I’m going to have to move some stuff to the backend. But until then, weeeeeeeeee.

Frontend

I’m using Vue for rendering the frontend app. But, notably, I didn’t want to have anything to do with a build step. So I’m just grabbing Vue (the ESM one) and using it directly via template strings. Thanks to browser support for modules, I can split every Vue component into its own file. And because there are ways to get VS Code to highlight HTML inside template strings, it’s kind of like I have single-file components! Kind of.

This was my first real use of the composition API. It was… fine?. I’m so used to the options API, that I still organized my code that way, so I’m not sure I got the full benefit. It was still kind of neat, though.

I experimented with using JSDoc on this project to give myself better editor support—the kind I’m used to with TypeScript projects. I couldn’t use TS here because I was adamant about not having a build step. But JSDoc worked out pretty great. That probably deserves its own article.

Over this past weekend, I updated the styling of the site. I switched over from using Pure CSS to Chota. It’s a tiny framework that has just enough of the useful things you need.[1]

Accessibility

I still have some work to do here. When I was first building this, I didn’t even think I was going to release the code. It was just going to be my home-cooked app. As such, I fell into some lazy practices (such as using links as buttons in situations where I just wanted text without padding and such).

I did make some improvements during this redesign, but I still have a good bit of work to do in this area. If you happen to use the app and run into a problem, please create an issue and I will take a look.[2]

Things I know about are the links-as-buttons issue I mentioned, but also things like the tag autocomplete—how it works (it or most probably doesn’t) with screen readers.

Still home-cooked at heart

I decided to write about my bookmarks app and share the code. And even though I have made some recent efforts to make it better for everyone, it is still a home-cooked app at its core. And it is still designed with primarily me in mind. That means if there is a feature you want, while you are free to create an issue, I most likely won’t be incorporating it. Depending on what it is, I might be open to PRs. But really, this app will continue to grow in whatever direction my whims decide.

That said, I would be really happy to know if someone else gets any use out of it. So if you do decide to use it, let me know!


  1. I’m always on the market for easy CSS frameworks. I especially like the classless ones and, when I need to actually make a design, I like the simple ones that I can wrap my mind around and start using quickly without a build step. If you know of any, hit me up. ↩︎

  2. I realize that telling someone to create an issue if they have a problem is not a healthy long-term solution to accessibility. I just point it out because if something is actively blocking someone from using the app, I’d rather fix that problem before I tackle theoretical ones. ↩︎