Feedstand
April 22, 2026 · feature · auth

Auth improvements and passkey support

The authentication screens got a long-pending visual refresh. During development they were always second priority and never truly finalized, so I gave them a proper pass this time around. All the auth flows now share one consistent look.

Email verification after signup is wired up, and password reset links go out by email. Plain text for now.

Sign-in screen

Another recent improvement is support for passkey login. You can now register passkeys in the settings and use them the next time you sign in. To learn more about passkeys, visit the official website.

April 20, 2026 · feature · discovery

Feed discovery optimizations

Add Source screen

When you paste a site URL into Feedstand to add a feed, there used to be a short wait while it visited the site, scanned the page, and figured out which feed was the right one. That wait is gone for sites that were already seen. The feed shows up right away.

Given that Feedstand has a large collection of feeds already, there's a good chance the site you're pasting is one of them. When it is, the feeds come back straight from what's stored, no visit to the site needed.

March 31, 2026 · throwback · frontend

Extracting Feedsweep and frontend optimizations

This month I extracted yet another chunk of the feed processing into its own package.

Most feeds need work to display properly in a reader — fixing lazy-loaded images, resolving relative URLs, normalizing broken markup, embedding media, and similar de-quirking. The code for all of that (and more) has been growing inside Feedstand for a while. Recently, this special treatment of feeds got quite big, so I cut it out and shipped it as Feedsweep.


The frontend got a polish pass: virtualized sidebar with section headers and keyboard navigation, optimistic interactions, a full settings dialog, and React Compiler taking over manual memoization.

February 28, 2026 · throwback · architecture

Hooks architecture and Feedmatch

This month I built an internal hooks system to separate the core reader logic from platform-specific behavior. The feed processing pipeline now exposes 20+ named lifecycle points where extensions can hook in. YouTube and GitHub integrations, logging, metrics — all of them moved out into standalone extensions on top of the same machinery.

Down the line, the same surface could be opened up so anyone can write their own extensions for Feedstand.


As somewhat of a tradition now, I've decided to extract the item deduplication logic into a separate package to make it more manageable. I've released it as Feedmatch.


The frontend got another push: OPML import with a progress dialog, infinite-scroll pagination, channel favicons, and a per-source layout system with cascading overrides.

On the API side: rate limiting, auth on feed routes, a per-user source cap, and ID encryption so internal numeric IDs don't leak in URLs.

January 31, 2026 · throwback · frontend

Frontend takes shape

Now that the backend part is stable and robust, it's time for me to build the actual reader interface.

Since Feedstand is meant to be a traditional feed reader in the UI sense, I've built the sidebar, reader view with split-pane, source management, sign in and sign up, mark-as-read, starring, and tags.

I also rewrote item deduplication from scratch. The old approach matched items on a single identifier and kept quietly falling apart in real feeds — publishers change guids between fetches, the same item shows up under several identifiers, and what counts as "the same item" varies between sources. The new logic OR-matches across guid, link, title-with-date, and a normalized identifier hash.

December 31, 2025 · throwback · infra

Extracting Feedcanon

Another month, another new package. I've extracted the canonical URL resolution logic into a standalone library which I called Feedcanon.

The same feed is often accessible through different URLs — mixed schemes, trailing slashes, query params. The logic for collapsing those duplicates has been growing inside Feedstand for a while.

The more I worked on it, the more it looked like a problem worth solving in isolation, the same approach as Feedsmith and Feedscout earlier.

Feedcanon now resolves a candidate URL down to its canonical form before subscription, so duplicates collapse into a single feed instead of slipping through as separate ones.


On the internal tooling side, the project migrated fully from npm to Bun, took a shot at upgrading Drizzle to 1.0 beta, and removed a pile of unused packages.

November 30, 2025 · throwback · performance

Performance work and Feedscout

I got back to Feedstand after the Feedsmith push over the past few weeks.

Went deep into improving the performance across the entire feed processing pipeline (what actually gets and stores the content from feeds). It is now significantly faster and uses less memory, enabling the processing of more feeds in the same amount of time.

I also decided to extract the feed discovery logic into a new package, Feedscout. As a separate project, it gets more room to grow and to support various methods of feed discovery. All while keeping the feed reader codebase lean.

October 31, 2025 · throwback · libraries

Work on Feedsmith continues

Over the last few months, Feedstand sat untouched as I dedicated all my time to Feedsmith. What started as a feed parser can now generate feeds, support OPML, and handle many feed namespaces.

Feedsmith is now effectively production-ready. It feels great to build a library that is faster and robust than many alternatives.

Time to bring it back into Feedstand and finally replace the internal feed handling.

May 31, 2025 · throwback · libraries

Building the feed parser

I've decided to move away from rss-parser. It can't handle the variety of real-world feeds and it's quite slow. Rather than keep patching around its limitations, I started building my own parser.

This is how Feedsmith came to be. It's designed from the ground up to handle the mess that real-world feeds are. It's also very extensible to allow me to add more custom namespaces in the future. It got a nice reception on Hacker News, too.

Now, a general note. The more I work on Feedstand, the more I realize that a feed reader is more like a stack of separate problems pretending to be one project: fetching, parsing, discovery, content cleanup.

February 28, 2025 · throwback · infra

Scaling and feed engine

Came back to the project after a three-month break. I've spent a week or so on the deployment plumbing: CI for Docker images, routing, database migrations, plus a reworked fetch layer with conditional requests so unchanged feeds get skipped. Date parsing keeps growing in scope… feeds use every imaginable format.

As usual at the start of each project, you need to think about scaling it! I've configured multiple worker replicas, database connection pooling, memory limits, and job queuing. I also implemented basic item deduplication via content checksums, and added a feed fix suggestions system that flags broken channels and proposes corrections.

The system now reliably scans thousands of feeds across 2 replicas of the same Docker container of the backend.

October 31, 2024 · throwback

Project bootstrap

After contemplating the idea of creating my own feed reader for a while, I finally took the plunge. I've set up the React frontend and the monorepo plumbing, and gone through three backend frameworks before settling on Hono.

I spent a big part of the time on the feed engine: parsing XML-based and JSON feeds, discovering them from arbitrary URLs (including YouTube). Real-world feeds turn out to be much messier than I expected. They feature non-standard date formats, numerous namespaces, and feeds that technically violate the specifications yet still need to function. Each one needs its own little patch, and the pile of custom treatments is already starting to feel like its own thing.

The core pipeline now runs end to end: discover a feed, subscribe to it, scan for new items on a schedule, and serve them as API responses.