Otter

An introduction to my side-project

For the past year, I’ve been building an app in my own time; the sort of app that I used to use 3 other apps to achieve the same thing. It has bookmarking, notes & some other useful features - not particularly “exciting”, but extremely useful, at least to me.

I also made it to scratch an itch I’ve had for a long time - to create something useful that I would use daily. I always intended to document my progress, a la #buildinpublic, but never got around to it.

Now is as good a time as any to start I guess, so here goes… by the way, the app is called Otter 🦦.

The name was chosen when I asked my wife which animal emoji she liked best. I think Otter’s are pretty cool too..

Progress has been slow because I typically work on it late at night or first thing in the morning before my family wakes up.. 🥱 which has meant I’ve fallen asleep while coding numerous times!

Otter is built with React + next.js, a pair that I’ve had a lot of experience with over the years; TypeScript; Supabase for authentication and database; and it’s hosted on Vercel.

React Query is used for all data fetching; Stitches and Radix UI are used for styling and components.

Bookmarking was the first big feature, it was fairly easy, surprisingly nuanced, but there’s so much more to be added. In the meantime, Pipedream and IFTTT are used to integrate with various other services that I use and trigger workflows to add items to Otter.

I want Otter be the home for all my online activity, with feeds of my “actions” or activity across the web (Twitter likes & posts, Mastodon toots & likes, GitHub stars & many more) and where I eventually consume undiscovered content from too.

Each instance of Otter is self-hosted & will likely only have one user per instance, so is private & secure by design. I’ve purposely reduced the number of 3rd party services so setup is fairly straightforward if/when it is ready for others to use.

Although I create apps using these technologies by day, it has been quite a learning curve. I hadn’t used Supabase before, and I certainly hadn’t fooled around with Postgres databases either - there’s a lot I still need to learn there!

Many things have changed throughout development - it started out using Sveltekit. The Supabase integration, in particular auth, has been iterated on a lot. Initially I created my own implementation but an official next.js integration was released which standardised everything. 👌

Ultimately it has to be super simple to save & search things in to Otter, so it is an API-first app. I’ve made bookmarklets, Apple Shortcuts, a Chrome extension, a Raycast extension & Scriptable widgets to make it easy to add, search & display items depending on my device.

I like being in control of my app’s data; having the API there to use however I see fit has been incredibly empowering.

There are no plans for a native mobile app because I believe that the web is perfect for this kind of app. One of my favourite services, Mailbrew also happens to be “non-native” and it has really made me appreciate the power of the web even more.

In the making of Otter, there have been so many small hurdles and challenges, things that I got stuck on for one reason or another. For example: scraping, or fetching info/metadata on a link has been tricky. Not all pages want to be scraped, so workarounds were needed.

For an important, but “hidden” feature like this, it has gone through quite a few iterations to where it is today and I spent a sizeable amount of time working on this aspect of the backend. There are a bunch of other aspects that I’ll dive into someday. #todo

I used Open AI’s Dall•E to help create a logo for Otter. Emojis are cool, but AI generated (or inspired) logos are even better.. This one is supposed to be the letter O like an otter’s face.. not sure why it looks like a Q, but it’s a pretty good starting point I think.

Making Otter has been a labour of love, but it has definitely made me a better developer. I can bring learnings and experience from this into the work I do for my clients. I’m excited to see where this takes me.


This was originally posted as a Twitter thread