I wanted a simple thing: click a button, get a beautiful card from any news article - headline, image, source logo - ready to share. How hard could it be?

Turns out, the web is a messy, wonderful chaos. And every news site has its own special way of making your life difficult.

The Idea

I read a lot of news. I wanted to save and share articles as clean, visual cards - not ugly links or screenshots with browser chrome. Something like what Telegram does with link previews, but as a high-res image I actually control.

So I built News Card Clipper - a Chrome extension that extracts the article title, publication date, hero image, and source logo, then renders them into a polished card using Canvas API. One click, instant PNG.

The first version was about 240 lines of JavaScript. It worked. On exactly two websites.

The current version is 2,100+ lines. Here’s why.

The first big surprise came when I tested on Forbes. The card rendered perfectly - title, image, date - but where the logo should be, there was… nothing. Just white space on a white card.

Turns out, Forbes has a white logo. On their dark header it looks great. Pasted onto my white card, it’s literally invisible.

The fix: I implemented WCAG luminance contrast checking. If a logo doesn’t have at least a 2:1 contrast ratio against white, the extension draws it on a subtle gray background. Simple in hindsight, but I stared at empty cards for a while before I figured out what was happening.

I was testing during some holiday season and suddenly CNN’s logo on my cards looked… festive. Snowflakes. Special colors. Like a Google Doodle but for news.

These are the homepage logos - sites swap them for holidays, events, special occasions. Nobody wants a Christmas-themed news card in March.

The fix: Prioritize apple-touch-icon and high-resolution favicons (192x192). Those almost never get holiday treatment. They’re the boring, stable, professional versions - exactly what I need.

Fuckup #3: The Score That Wasn’t

After implementing a scoring system to rank logo candidates, I proudly set apple-touch-icons to score 100 - the maximum. Obviously the best choice, right?

Except on Gazeta.ru, the apple-touch-icon was a tiny, blurry thing with no sizes attribute. My code assumed “no size specified = must be huge” and gave it top priority, while a perfectly sharp CSS background logo sat there unused with a lower score.

The fix: No sizes attribute now gets a cautious score of 60 instead of 100. Trust, but verify.

Fuckup #4: The Image With Built-In Headlines

NSN.fm was the most creative offender. Their og:image - the standard meta tag that’s supposed to contain the article image - pointed to a “sharing” version with the article title and outlet logo baked directly into the JPEG. So my card had the headline printed twice: once in my clean typography, once burnt into the photo like a watermark.

The fix: Detect and rewrite URLs, replacing mobile_image- with image- to get the clean original. Also added filtering for any image URL containing /sharing/. Three commits over one day to fully sort this one out.

Fuckup #5: “Лента новостей” Is Not a Headline

Readability.js is great at extracting article content. But sometimes it captures the wrong title entirely. On Kommersant.ru, instead of the actual headline, I was getting “Лента новостей (Москва)” - literally “News Feed (Moscow).” Very informative. Very wrong.

The fix: A pattern-matching system that detects generic titles (news feed, home page, 404, etc.) and falls back to og:title, <h1>, or itemprop="headline" when Readability gets confused.

Fuckup #6: The World’s Tiniest Favicon

On Gazeta.ru, the logo looked like it was rendered on a Game Boy. The favicon selector was grabbing the first declaration it found - and this site listed them smallest-first. So I got a crispy 16x16 icon upscaled to logo size.

The fix: Collect all favicon declarations, score them by resolution (512px = 75 points, 64px = 55 points, PNG format = +2 bonus), pick the biggest.

How It Works Now

The extension today is basically a pile of heuristics pretending to be software:

  • Logo detection uses a 9-level fallback chain with scoring from apple-touch-icons down to plain text.
  • Image selection scores DOM images by proximity to the H1, aspect ratio, container type, and CSS class names.
  • Date parsing handles Russian, Ukrainian, and English - including relative dates like “3 дні тому”.
  • Title validation catches Readability mistakes and finds the real headline.
  • Canvas rendering does a two-pass layout - measure first, draw second - because setting canvas.height clears everything.

Every image gets fetched through the background service worker to bypass CORS - content scripts inherit the page’s restrictions, which means you can’t just fetch() a photo from another domain.

The Eternal Beta

This extension will never be “done.” It’s a perpetual beta, and I’ve made my peace with that.

Every few weeks I open some news site I haven’t tried before, click the button, and get a card with a missing logo, a wrong image, or a date from 1970. Then I sigh, open content.js, and add another ten lines of heuristics for that site’s particular flavor of HTML.

There’s no spec for “where a news site puts its logo.” There’s no standard for “how to distinguish an article photo from a social sharing card with burnt-in text.” Every site is a snowflake, and you can’t account for all of them upfront. You just keep playing whack-a-mole, one site at a time.

But that’s also what makes it fun. Every broken card is a puzzle. Every new news site is a boss fight.

240 lines -> 2,100 lines. And counting. Zero regrets.


If you want the tool itself, you can open the tool page or download the extension ZIP.