Confessions of a Link Hoarder (and the App I Built to Cope)

Are you also a link hoarder? Congratulations, we’re the same type of weird, and you might want to keep reading.

Some people keep dozens of tabs open. That stresses me out — one browser crash and there goes everything I’ve ever worked for. So I do the opposite: I like things instead. Anything on Twitter (yes, I’m still calling it Twitter) that seems even remotely useful gets a tap of the heart — a new skill, yet another UI library, a buttery animation, a landing page so good I resent not having a landing page to build. And memes. Obviously.

For years this felt like a system. I slept fine knowing it was all somewhere in there, retrievable with enough patience. Then one day it hit me that patience and thumb stamina are not a search index, and I decided I didn’t want to live like this anymore.

The moment the “system” broke

The breaking point was embarrassingly mundane. I remembered liking a perfect little component and I wanted it for something I was building. I knew it existed. I knew I’d liked it. And I spent five minutes scrolling my own likes like an archaeologist before getting discouraged and giving up. It didn’t get built, but it never stopped itching at the back of my mind either.

The itch became a plan the weekend after a frontend guild meeting, where I’d once again mentioned a great library I couldn’t quite find again. Enough was enough. Twitter’s own “Likes” tab gives you infinite scroll and exactly zero ways to search it — and a hoard with no index isn’t a collection, it’s a landfill. So I decided to build my own index.

(For the record, the hoard is 7,841 likes deep and goes back about twelve years. I regret to inform that it is not twelve years of frontend wisdom: my all-time most-liked accounts are @UberFacts, @dog_rates, the GOATs Simone Biles and Aly Raisman and a concerning number of Kardashians. These days it’s more @shadcn and @emilkowalski. We all grow up eventually.)

I wanted a way to actually use the useful half — and, let’s be honest, to finally index my memes properly — without deleting the nostalgic half. So I built one. I called it inspo.

Tags over time — a stacked bar chart of the top 3 tags for each year from 2019 to 2026
inspo's "tags over time" view — the top 3 tags per year (That blue sports block in 2021? The Tokyo Olympics. Simone Biles FTW 🥇)

What inspo is

inspo's login screen: a ransom-note-style 'inspo' logo, the tagline 'Your liked tweets, grouped into inspiration tags', and a pink 'Continue with Google' button
The app's front door. Single-user by design

inspo mirrors my Twitter likes into a Postgres database and uses a free-tier LLM to sort each one into tags I manually created like design, ui-libraries, ai, funny, and about a hundred more it invented on its own. Then it gives me a fast, filterable, searchable UI over the whole thing. Private, single-user, deployed at inspo.nitzan.fyi.

The architecture is deliberately boring in the best way:

┌──────────────────────┐
│ Python fetcher       │
│ (twikit, GH Actions) │
└───────────┬──────────┘
            │ likes
            ▼
┌──────────────────────┐
│ Postgres (Neon)      │
└───────────┬──────────┘
            │ read / tag
            ▼
┌──────────────────────┐    tag    ┌─────────────┐
│ Next.js app (Vercel) │ ◀───────▶ │    Groq     │
└──────────────────────┘           └─────────────┘

Now I’ll do the thing I always do and discuss the things worth highlighting.

Highlight: getting the likes out (twikit + GitHub Actions)

Twitter’s API pricing is, let’s say, aspirational for a personal project. So the fetcher is a standalone Python script built on twikit, which drives the timeline the way your browser does. It walks my Likes timeline, upserts each tweet into Postgres with status = 'pending', and stamps a like_seq as it goes so I can always re-sort into true “most recently liked first” order.

It runs on a GitHub Actions cron every 6 hours, which means the whole ingestion pipeline costs me exactly nothing and I never think about it. It supports incremental runs (just grab what’s new) and full backfills (--backfill 2000 to reach into the 2015 Kardashian strata).

As always, the lesson is keep it simple, stupid — a cron job and a database beat anything clever.

Highlight: an LLM as a librarian

This sounds like the part that should be hard and expensive, but it’s neither. Every pending like gets handed to an LLM with my list of tags and their descriptions, and it decides which ones apply. I run it on Groq with llama-3.1-8b-instant — a small, cheap model on the free tier, which is genuinely enough for a single user’s backlog, and it’s fast, which matters when you’re re-tagging 7,000 rows.

There’s also a backfill-on-demand button: add a new tag, and every existing like gets re-evaluated against it. Rejections are remembered, so a tag I remove doesn’t creep back on the next pass.

Tags come in two flavors:

  • Static tags — ones I define with a description that guides the model (design, eng, ai, claude, funny…).
  • Dynamic tags — ones the model is allowed to invent when a like fits nothing existing.

That second category is where it got delightful. I set it loose and it generated 112 tags. Most are sensible (design-systems, web-agenting, typography). Some are unhinged in a way that describes my psyche better than I’d like: whimsy-loaders, villain-criticism, and my personal favorite, a tag literally named gemma-theory (yes, it clustered my Severance fan-theory likes into their own category).

I have no notes. The model understood the assignment.

inspo filtered to the 'pop' and 'funny' tags, showing a tweet with a hand-drawn movie-rating scale
The whole point: filter the hoard down to pop + funny, and every card carries the tags the LLM assigned (here, pop and film). Also, this is a genuinely elite movie-rating scale and I will not apologize for keeping it.

Highlight: the app, and standing on the shoulders of design engineers

The app is a fairly modern stack — Next.js 16 (App Router), TypeScript, tRPC, TanStack Query, Drizzle ORM, Postgres on Neon, Better-auth for Google login, Tailwind v4, and nuqs for URL state. The UI is built on Base UI via the excellent @basecn registry (shadcn’s philosophy, Base UI’s foundation).

But here’s the honest part, and it’s the same confession Emil Kowalski makes about his own site: I don’t consider myself a great designer. What made inspo look good isn’t necessarily taste I was born with — it’s that a small army of design engineers packaged their taste into installable Claude skills. I just used them.

This is the thing I most want people to take away. The gap between “person who can build a thing” and “person who can build a thing that looks intentional” has never been smaller, because the taste is now a dependency you can npx into your repo.

A couple of specific shoutouts before the big lists, because they earned it:

  • tweakcn by @iamsahaj_xyz — a visual theme editor for shadcn/Base UI. This solved the pain point “all shadcn sites look the same” in about ten minutes. The exact theme I ended up shipping inspo with is this one — tweak it, copy the CSS variables, done.
  • reui.io — and specifically their Filters component. It’s TanStack-Table-friendly and handles basically any data shape.
  • Arlan’s Vault — a gorgeous collection of interaction studies. The ransom-note effect in particular lives rent-free in my head and felt like the right choice for my top bar.

The Claude skills I collected

These are the design-engineering skills I’ve been hoarding — the ones that make an AI agent produce interfaces that don’t look like AI produced them. Grouped by the people who made them:

  • Emil Kowalskiemil-design-eng, plus a whole animation set: /improve-animations, /animation-vocabulary, /find-animation-opportunities, and /apple-design.
  • Jakub Antalíktransitions-dev and transitions-polish.
  • Jakub Krehelmake-interfaces-feel-better (the one everybody seems to install) and oklch-skill, for working with colors the way you actually see them.
  • Paul Bakausimpeccable.
  • Leonxlnxtaste-skill (design-taste-frontend v2), the one with the least “AI smell”.
  • Jamie Mill — the layers-* set (9 skills: intro, orient, domain, conceptual-model, user-needs, product-strategy, interaction-flow, surface, observed-behaviour).

And a few more that kept showing up in my likes and are worth a look:

  • Matt Pocock’s mattpocock/skills/grill-me (people are apparently using it to run technical interviews), and /wayfinder, which acts as an orchestrator for your other custom skills.
    • Will Ness’s frontend variant of the grilling skill — a multi-phase approach that builds five variations and zooms in on one part of the UI at a time, in context.
  • Ibelick’s improve-ui — audits an interface against its own design language.
  • ui-ux-pro-max — the maximalist, batteries-included option, with a lot of built-in templates and rules.
  • MengTo’s open-sourced library of 75 agent skills for web design, motion, and WebGL.

The UI libraries I’ve been hoarding

This is the motherlode — the reason I built inspo in the first place. Every one of these came out of the ui-libraries tag or a “library” search across my likes. It is way too many. Keep the ones that spark joy, delete the rest, that’s the whole point. And to be clear, this is not an endorsement — I haven’t actually used most of these. It’s a bookmark pile, not a review.

shadcn-ecosystem component libraries & registries

Headless primitives

Small but mighty components / utilities

Design tools & inspiration (not code, but too good to cut)

Takeaways

A few final thoughts, in no particular order:

  • The hoard was hiding a shape. Seeing twelve years of likes tagged and counted told me more about how my interests drifted than any amount of journaling would have. Data you already generated is the cheapest self-portrait there is.
  • LLMs are shockingly good librarians. Not summarizers, not chatbots — classifiers. Handing a model a taxonomy and a pile of items and saying “sort this” is an underrated, cheap, and reliable use of the technology.
  • Taste is now installable. The single biggest quality jump in this project came from other people’s design skills and component libraries, not from me getting better at design overnight. That’s not cheating; that’s the whole point of a community.
  • Build the small thing that annoys you. I didn’t need a startup. I needed to find one tweet. The app that fixes your specific dumb problem is almost always worth an afternoon.

Now if you’ll excuse me, I have 112 tags to prune. 🐦