PullMD Part 3: Beyond Reddit, Beyond Readability – Simply Explained
This is a story in three acts. First, a typo-laden question blows open the limits of a tool I had built for exactly one purpose. Then it grows in small steps. And at the end I find a mistake that ran silently under everything for weeks — without anyone noticing.
If you read Part 2, you know: for three weeks my little Markdown service hummed away quietly. Reddit posts only. On my phone only. Just for me.
First: what’s actually going on here?
The tool takes an internet address — a link, say, to a blog article — and gives me the text of that article back in a very simple format. The format is called Markdown, and it’s just plain text with a few asterisks for headings and lists, without all the surrounding clutter like ads, menus, or cookie banners.
Why do I want this? Because I then drop the clean text into a chat with the AI and we can talk about what it says.
Act 1: The Pivot — when the tool suddenly had to do more
On the morning of March 20, I accidentally tried to read in a perfectly normal article — a link that had nothing to do with Reddit at all. What came back was nothing. Empty result.
Fair enough. I had only ever built the service for Reddit. For anything else there simply was no path.
So I typed into my chat with Claude:
„die URL soll auch bei normalen seiten im markdown erscheinen… das war doch bisher nicht so oder?“ — [the URL should also appear as markdown for normal pages… that wasn’t the case before, was it?]
The answer was clear: no, it wasn’t. My tool was sitting in a cage I had built myself. Reddit first, I had said. But now I needed: every webpage. Not just one.
Three paths instead of one
The solution was three different paths — depending on what kind of webpage comes in:
Path one: Mozilla Readability. That’s a ready-made library Mozilla wrote for the Firefox Reader Mode — exactly the thing that pulls the article text out of a webpage and throws everything else away. A kind of “purity filter” for webpages. Plus a second small tool called Turndown that then converts the filtered text into Markdown format.
Path two: Cloudflare. Cloudflare is a company whose servers a lot of webpages run through. For some pages, Cloudflare already offers clean text out of the box — no filtering on my side required. When that’s available, I take it. Faster, more reliable.
Path three: The existing Reddit path stays unchanged for Reddit links.
Three paths where there used to be one. The cage was open.
Act 2: The Maturing Phase — small improvements in April
In April I started keeping notes for myself — not a real spec, more a collection of questions that came up as I used the thing. The main question was: What’s missing when it isn’t me reading the text, but an AI processing it further?
A human fills in gaps automatically in their head. An AI doesn’t. It needs structure.
That turned into three small improvements.
Tables that arrive as tables
The old conversion tool Turndown couldn’t handle tables at all. If a webpage had a table, the conversion produced only chaos — rows and columns flattened into a mess.
Code snippets came through without their language label too. That’s a bit like getting a quote from a book without being told what language it’s in.
We swapped the conversion tool out. The new one understands tables, keeps language labels on code, and even handles checklists. One line changed in the pipeline — but the results got noticeably better right away.
Carrying extra information along
Until then my tool only delivered the bare text. No title, no author, no date. That’s fine when I’m the one reading. But if an AI is supposed to work with the text further, it’s missing context.
So we built a small helper that pulls this extra information out of every webpage: title, description, author, publication date. These details now ride along as a short block at the start of every text.
Backup plan for when the purity filter fails
Readability — the purity filter — doesn’t work everywhere. With paywalls, with pages that only run on JavaScript, with oddly-built sites — sometimes you only get a tiny sliver of text out. Visibly too little.
Instead of giving up in those cases, there’s now a backup plan: just take the whole page content, give it a rough cleaning, and deliver that. The extra-info block then says „backup-path“, so I can later see how often that happens.
Up to here, everything was incremental. Then came April 25.
Act 3: The Bug That Lived for Weeks
Honestly, I just wanted to answer a simple question: Is Readability really the best purity filter? Or is there a better one?
So I set up a comparison. Fifteen real webpages, three different filters, all running side by side. One of the filters was Trafilatura — a library from the Python world, originally written for web archive projects, especially good at squeezing decent text even out of difficult pages.
While reviewing the results, something odd stood out. The Readability results looked different from what I had expected. Shorter, rougher, somehow clunkier. Not what I knew from Firefox Reader Mode.
I dug into the code and traced the path that every request takes. What I found was uncomfortable.
The built-in switch that was flipped wrong
For the Reddit path, you need the comments under a post. So there was a switch: „take the comments along — yes or no?“. For Reddit it was set to „yes”.
But: that switch defaulted to „yes“ — for all requests. Including normal webpages. And when it was set to „yes“, the tool skipped the purity filter entirely and took a simpler route instead — the whole page content, just roughly cleaned.
That meant: for weeks, my tool had not been running normal webpages through Readability at all. What I had thought of as „Readability output“ was actually just roughly-cleaned raw content.
For weeks, my comparison had been measuring the wrong thing against Trafilatura.
The fix was a single line of code: for normal webpages, flip the switch to „no“.
What the honest comparison showed
After the fix, the comparison finally made sense. And suddenly it was clear:
On a small personal blog page, Readability pulled out only about 100 characters of text. Trafilatura pulled almost 15,000 characters out of the same page. That’s more than a hundred times as much.
On a tech news site: about 470 characters with Readability, about 1,700 with Trafilatura. On another blog: 80 percent more content via Trafilatura.
But: on pages with tables — Wikipedia, for example, or programming documentation — Readability was better. It kept the structure cleaner.
So no either-or decision. Both filters now run in parallel. A simple rating system picks per request which result looks better — and that one gets delivered.
How the tool decides what „better“ means
The rating is deliberately simple — five rules of thumb:
- Is the text longer than 500 characters? Point.
- Is the ratio of extracted text to the original page size above two percent? Point.
- Does the original page even have an article section? Point.
- Is there at least one heading? Point.
- Are there at least three proper paragraphs? Point.
Whoever collects the most points wins. Reddit posts and Cloudflare texts get bonus points, because they’re already „clean at the source“.
The score lands in a hidden label on every response, so I can later look up how reliable the tool was for a given webpage.
What does it say when you miss a bug for weeks?
That’s the uncomfortable question at the end of this story.
The output was „good enough“. Roughly-cleaned raw content already contains most of the relevant text on a lot of pages — even without a purity filter. When the difference between „right“ and „wrong“ is hard to see, you don’t see it. Not because you’re not paying attention — but because there’s no visible signal.
I drew one conclusion from this: a small database that records, for every request, which path was taken, how many points the result scored, how long it took. After 30 days, entries get deleted automatically.
Plus a tiny query point: „show me the last seven days“. From that I can see: how many requests went through which filter? Which pages consistently score badly? Is something shifting?
The next time a setting quietly steers things onto the wrong path, I’ll see it in the stats. It’s no guarantee. But it’s a signal.
The lesson
For every self-built tool: either you build yourself a window into the machine — or you fly blind.
The window doesn’t have to be big. A small table and a simple query point are enough as a first step. But without any of it, a tool can give the wrong answer for weeks — and nobody notices.
What came next
Three paths, a rating system, an interface for AI helpers, and an app on my phone — but all of it was still running under an old codename. I had to drop it for legal reasons before the tool could go public.
→ Part 4: From My Tool to an OSS Project
Part 3 of 9 in the PullMD series.
← PullMD Part 2: From Spec to Running Container | PullMD Part 4: From My Tool to an OSS Project →