A couple years ago, I discovered that visiting youtube.com/results showed a blank page—no recommendations, just an empty page with search bar. I bookmarked it. And this simple change slashed my daily YouTube binge from four hours to one. This was my first taste of how adding a bit of friction can dramatically change behavior.

However, other parts of youtube would still pull me into time-wasting rabit hole. Follolwing my friend Zelfy’s advice I tried different YT clients like Invidious (particularly yewtu.be), which cut my watchtime down to under 20 mins. PROGRESS!

But. These third-party clients are often slow, down or blacklisted.

So, I decided to create my own web extension to hide distracting elements on sites. There are some third-party solutions out there but they’re very specific to a particular site like YT or twitter. I want something that works across sites and for my particular use cases, for example, removing Discord Activity because I spent 80 hours playing Krunker Srike there lol (ノ °益°)ノ 彡 ┻━┻. Plus, I also want it to accept arbitrary CSS selectors to conceal them. Because touching the codebase everytime I want to remove something is annoying.

I get to work and here’s how it looks for now (on YouTube): Dhyan

Ofc, it shows different toggles for different sites if there’s anything it has removed there. If not it shows an empty state.

Currently it only does the basics, but I’ve meticulously spent hours making sure only the intended elements are hidden. For example, hiding right column on video watch page but not hiding the playlist or chat window or chapters that can also appear in that column.

It is on my GitHub hosted under a FOSS license. Feel free to give it a go and provide feedbacks.

This is my first extension, and in case you’re new to this as well and feel curious, here’s quick run through on how extensions work. First you need a manifest.json file for every extension. This file is needed for the browser to know the extension meta data (e.g. name, version) and the permissions it requires (e.g. scripting, activeTab, storage). The following keys are needed for any extension.

{
  "manifest_version": 2,
  "name": "Extension Name",
  "version": "0.0.1"
}

Executing script (css or js) in specific url is very easy. We can add a “content_scripts” key which lists a array of script that execute on specific url patterns. Like below:

{
  "manifest_version": 2,
  "name": "Extension Name",
  "version": "0.0.1",
  "content_scripts": [
    {
      "matches": ["*://*.youtube.com/*"],
      "css": ["css/youtube.css"],
      "run_at": "document_start"
    }
  ]
}

We can hav a “js” key instead of “css” in “content_scripts” if we want to run JS. The “run_at” key determines when the CSS or JS will be executed. It’s values can be “document_start” (before DOM load), “document_end” (after DOM load but before images, scripts etc) and “document_idle” (after all the resources have loaded).

For adding a popup toggle, we use the “action” key:

{
  "action": {
    "default_popup": "toggle.html"
  }
}

The toggle.html can be developed like any other webpage. We can throw in any css/js frameworks there as long as we don’t break any CSP rules.

The JS we bundle with toggle.html has limited access to javascript apis. For full access we use background scripts.

{
  "background": {
    "service_worker": "background.js"
  }
}

For privilege access in the popup it sends messages to the background script, and background script in turn does all the stuff with its privileged access to web extension JavaScript APIs.

That’s the basics! The new Web Extensions docs on MDN is the best resource to learn more, though at times the V3 docs seemed a bit outdated.

My goal with the extension for now is to add advanced features like accepting arbitrary CSS selectors, or block a site completely with a timer etc. I may also pay and host it on chrome web store if enough people are interested.

That’s all.

Check it out!

Published on:


If you have something in mind, please don't hesitate to reach out to me via email.