Building a Reddit add-on: what Reddit's page taught us

SynthStamp’s add-on does something that sounds simple: find every username, post, comment and image on a Reddit page, and put a small flag next to each. Getting that right took most of the first week. These are the problems we hit, in case you’re building something that lives inside someone else’s page.

There are two Reddits

Reddit serves two completely different sites. New Reddit is built from web components with names like shreddit-post and shreddit-comment, which carry useful attributes such as the author and the time the comment was posted. Old Reddit, still loved by a lot of long-time users, is classic server-rendered HTML from another era: div.thing, a.author, p.tagline.

We support both, through two adapters that share one core. The adapter’s only job is to answer questions like “where is this comment’s author link?” and “where does the comment’s text start?”. Everything else, from the badges to the tag menu to talking to the server, lives in the shared core and doesn’t know which Reddit it’s on.

Every comment has two author links

The first real test on new Reddit showed two flags on every comment. Each comment has two links to the author’s profile, one around their avatar and one around their name. We now skip links that wrap only an image and badge the name.

Hover cards open under your badge

Put a badge inside the username link and hovering it opens Reddit’s profile card, right on top of the menu you were trying to use. The username sits inside a hover-card trigger element, and anything inside it triggers the card. The badge now goes after that element, not inside it, on comments and on the post’s byline.

The comment isn’t where you think

We expected a comment’s text and its byline to be direct children of the comment element. They aren’t: both are nested inside a details element that makes collapsing work. Worse, a comment contains its replies, so a careless search for “the text of this comment” finds a reply’s text instead. The fix is to resolve every part to its nearest enclosing comment, so each comment owns only its own byline and body.

Old Reddit scales everything

Subreddits on old Reddit can restyle the page, and some scale the byline text up or down. A badge sized in pixels ended up floating above or below the line. Sizing everything in em, relative to the text around it, keeps the badge sitting on the line whatever the subreddit does.

Stay out of the page’s styles

The tag menu is drawn inside a shadow root, so none of Reddit’s styles leak into it and none of ours leak out. The badges can’t be isolated that way, since they have to sit in Reddit’s own text, so every rule is namespaced and, where Reddit’s reset would win, marked important. It isn’t pretty, but it holds.

The browser does the heavy work

Image fingerprints are computed in the add-on’s background script, not in the page. The page can’t read the pixels of images served from another domain, and the background script can fetch them. Results are cached by image address, so scrolling back up doesn’t redo the work. How the fingerprints work has its own post.

You can’t automate your way onto Reddit

Our end-to-end tests load the real add-on into a real browser and click through it. Reddit, reasonably, shows every automated browser a “prove your humanity” page. We don’t try to get around that. Instead the tests run against saved copies of real Reddit markup, new and old, and each time real Reddit showed us something new, it went into those copies first, so the test broke before the fix went in.

The server side

The server is a Phoenix application built on PhoenixKit, which gave us accounts, sign-in, the admin and settings out of the box, so the work went into the parts that are actually SynthStamp. The API the add-on talks to is small: register an install, send what a page shows, cast or change a tag, look up tags in batches.

If you use Reddit, try the add-on. If you build things that live inside other people’s pages, we hope some of this saves you a week.