Iurii RoguliaIurii Rogulia
AboutServicesPricingProjectsStackReviewsPhrasesBlog
Contact
Iurii ships.

Iurii Rogulia, IT partner for business & fractional CTO. Professionally building software since 2001.

Think of a number
PricingQuality checklistPrivacy PolicyCookie Policy

Business

TMI Iurii Rogulia
VAT ID: FI29845875
DUNS: 368664211
Lappeenranta, Finland 🇫🇮

[email protected]
  1. Home
  2. /
  3. Blog
  4. /
  5. I Built a 30-Line Chrome Extension to Kill the YouTube Feed

Iurii Focuses: I Built a 30-Line Chrome Extension to Kill the YouTube Feed

A Manifest V3 content script that redirects only the YouTube homepage — before YouTube's feed has a chance to render, with two permissions and zero tracking.

June 8, 2026· 6 min read

How I built a tiny Manifest V3 Chrome extension that redirects the YouTube homepage feed without breaking search, videos, or subscriptions — document_start injection, exact-path guard, and a trust surface you can read in a minute.

Stack

JavaScriptHTMLCSS

Topics

Chrome ExtensionManifest V3Browser APIProductivity
I Built a 30-Line Chrome Extension to Kill the YouTube Feed

On this page

  • Why Not an Existing Extension?
  • Three Constraints That Shape Everything
  • Beating the Feed to the Paint
  • Why location.replace(), Not location.href =
  • One Setting, Synced, Owned by the User
  • A Trust Surface You Can Read in a Minute
  • What This Deliberately Doesn't Handle
  • Results
  • Takeaways

I open youtube.com to grab one specific video, and forty minutes later I'm three recommendations deep into something I never went there for. The homepage feed is one of the platform's most effective attention traps, and it's designed to keep you watching.

The obvious fixes all overreach. Block the whole domain and you lose search, video pages, subscriptions, and watch history along with the feed. Install a heavyweight "site blocker" and you hand it broad permissions, a background worker on every tab, and usage tracking to justify a subscription. I wanted the opposite: remove only the home feed, leave the rest of YouTube fully working, and ask for the least a user has to trust. That turned into a Manifest V3 extension that's about 30 lines of vanilla JS — no build step, no dependencies, no background service worker. Here's how it works and the few decisions that actually mattered.

Why Not an Existing Extension?

Plenty of tools touch this problem, and for many people one of them is the right answer. Unhook and DF Tube hide YouTube UI elements — the feed included — behind a rich options panel. uBlock Origin can do the same with a single cosmetic filter rule. LeechBlock and Redirector are general-purpose site blockers and URL rewriters you can configure to cover this case.

Every one of them is more capable than what I built — which is exactly why I passed. Unhook, DF Tube, and uBlock Origin solve a broader class of problems than I needed to; uBlock in particular runs everywhere and carries a large, general-purpose engine. Redirector would do the job too, but as a tool I configure rather than one that does this out of the box. I wanted the smallest possible artifact: behaviour I can hold in my head and a permission list I can justify line by line. For one sharp itch — remove the home feed, touch nothing else — 30 lines I fully understand beat a powerful tool I've half-configured. If you already run one of the above, there's no reason to switch; this is for the case where you'd rather own the whole thing.

Three Constraints That Shape Everything

Before any code, the requirements pin down the whole design:

  1. No flash of feed. If the recommendations render and then the page navigates away, the distraction already won — your eyes caught it. The redirect has to fire before the feed paints.
  2. Surgical scope. Only the exact homepage (/) redirects. /watch, /results, /feed/subscriptions, /@channel — every other path stays exactly as it is.
  3. Minimal trust surface. A focus tool that quietly phones home is self-defeating. It should request the fewest permissions that make it work and keep the user's one setting on the user's machine.

Each constraint maps to one specific technical choice. None of them needs a framework.

Beating the Feed to the Paint

Related service

MVP Development

Have a small product or internal tool that needs to ship — properly built and packaged, not a weekend hack? I take focused ideas from zero to released.

More about this service →

The "no flash" requirement comes down to two words in the manifest: "run_at": "document_start". A content script with that setting runs before YouTube's own application code initializes, while the page is still effectively blank — so in practice the redirect fires before the homepage feed renders, and you never see the wall of recommendations flash up and disappear.

It's worth being precise about what this guarantees. document_start is the earliest hook Chrome offers, but it isn't a promise of zero visual artifact: the browser may already have painted a blank frame, and a future change to how YouTube boots could reintroduce a flicker. What it does reliably is run ahead of YouTube's own scripts — early enough that, in months of daily use, I've never caught the feed rendering before the redirect.

// content.js — runs at document_start, redirects only the exact homepage
chrome.storage.sync.get({ redirectUrl: "https://app.todoist.com/app/today" }, (data) => {
  if (location.hostname === "www.youtube.com" && location.pathname === "/") {
    location.replace(data.redirectUrl);
  }
});

That location.pathname === "/" check is the whole of constraint #2. Match the root path and only the root path, then hand off. Visit any other YouTube URL and the guard is false, so the script does nothing and the page loads untouched. There's no allowlist to maintain, no regex to get wrong — just one exact-string comparison.

Why location.replace(), Not location.href =

The redirect uses location.replace() on purpose. The difference is what happens to the browser's history:

  • location.href = url pushes a new entry. The YouTube homepage stays in history, so the very next Back press bounces the user straight into the feed they were trying to skip.
  • location.replace(url) swaps the current entry in place — the homepage never lands in history. Back goes to wherever they came from, not into the trap.

It's a one-word change that decides whether the tool actually holds the line or just adds a speed bump. This is the kind of detail that doesn't show up in a feature list but is the entire difference between "works" and "works the way you'd want."

One Setting, Synced, Owned by the User

The destination is the only state the extension keeps, and it lives in chrome.storage.sync. That choice does a lot of quiet work: the setting follows the user across their signed-in Chrome browsers — no account, no server, and not a single network call from the extension itself. Chrome handles the sync; the extension just reads and writes a key.

The popup is the entire settings surface. Load the current value into an input on open, write it back on Save:

// popup.js — load the saved URL, persist edits on Save
chrome.storage.sync.get({ redirectUrl: "https://app.todoist.com/app/today" }, (data) => {
  input.value = data.redirectUrl;
});
 
save.onclick = () => {
  chrome.storage.sync.set({ redirectUrl: input.value.trim() }, () => {
    save.textContent = "Saved ✓";
    setTimeout(() => (save.textContent = "Save"), 1500);
  });
};

The default is the Todoist Today view — open YouTube on autopilot and you land on your task list instead of the feed. Change it to a calendar, a blank tab, a Kanban board, anything. The same redirectUrl key is read by both files, so the popup and the content script share one source of truth with no message passing between them.

A Trust Surface You Can Read in a Minute

The strongest privacy claim is the one a user can verify for themselves. With this extension, the manifest is the whole story:

// manifest.json — the entire permission surface
{
  "manifest_version": 3,
  "permissions": ["storage"],
  "host_permissions": ["https://www.youtube.com/*"],
  "content_scripts": [
    {
      "matches": ["https://www.youtube.com/*"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ]
}

Two grants: the storage permission and host access to www.youtube.com. No tabs, no scripting, no analytics endpoint, no background service worker watching anything. Could a content script with DOM access on youtube.com exfiltrate data in principle? Yes — that's what host access means, and it would be dishonest to claim otherwise. The point is narrower and verifiable: the current implementation makes zero network requests, and you can confirm that by reading the two short scripts yourself.

The guarantee isn't "it can't." The guarantee is that you can verify exactly what it does in under a minute.

When the Chrome Web Store review page lists "This extension can read and change your data on youtube.com," that single line is the entire capability — and the code shows it uses almost none of it.

Manifest V3 gets criticized for the friction it adds, but for a tool like this its constraints are a feature. This extension doesn't include a background service worker at all, so there's no separate execution context running outside the page. The smaller the surface, the easier it is to trust — and a focus tool that you don't fully trust is one you'll uninstall.

What This Deliberately Doesn't Handle

A tool this focused earns its keep by being honest about its edges. A few cases it intentionally leaves alone:

  • In-app navigation to the homepage. YouTube is a single-page app. Click the logo or the Home button while you're already on the site and it's a client-side route change — the content script doesn't re-run, so that path isn't redirected. The redirect fires on full page loads and direct visits to youtube.com, which is exactly where the "open YouTube on autopilot" habit lives. Supporting in-app navigation is entirely possible — listen for YouTube's yt-navigate-finish event, or patch the History API — but it requires a long-lived script observing route changes, complexity I intentionally chose not to add.
  • Mobile and alternate hosts. Host access is scoped to www.youtube.com. m.youtube.com and other variants are out of scope by design.
  • YouTube relocating the feed. The exact-path guard assumes the feed lives at /. If YouTube ever moves it, the guard is a one-line change — a deliberate trade for the simplicity of matching one exact path instead of maintaining a pattern.

None of these are oversights. Each is a place where handling the case would cost more complexity or more permissions than it's worth for a single-purpose tool.

Results

MetricValue
Codebase~30 lines of vanilla JS across two scripts — no build, no deps
ManifestV3, no background service worker
Permissions2 — storage + www.youtube.com host access
Injectiondocument_start, before YouTube's app code initializes
ScopeExact / path only; every other YouTube page untouched
Storagechrome.storage.sync — syncs across browsers, no server
TelemetryNone — no tracking, no accounts, no network calls
LicenseMIT, open-source

Takeaways

  1. run_at: document_start runs ahead of the page's own code. If you need to intervene before a site's scripts boot, inject the content script at document_start — it's the earliest hook Chrome gives you and, in practice, early enough that the content typically hasn't rendered yet. It's not a hard guarantee against any flicker, but it's the right lever.

  2. An exact-path guard beats an allowlist. When you want to act on one route and leave everything else alone, location.pathname === "/" is simpler and safer than enumerating the paths to skip. There's nothing to forget.

  3. location.replace() keeps the trap out of history. For a redirect the user shouldn't be able to Back into, replace the current entry instead of pushing a new one.

  4. chrome.storage.sync gives you cross-device settings for free. No backend, no account — Chrome handles the sync entirely.

  5. The smallest trust surface wins. Request only the permissions you genuinely need. For anything privacy-adjacent, "you can read the entire thing in a minute" is a stronger guarantee than any privacy policy.

The discipline in a tool like this is in what it doesn't do. It removes one feed and touches nothing else. The code is on GitHub, and the full project write-up is in the YouTube Home Blocker project card.

If you've got a small, sharp tool that needs to actually ship — built properly, packaged, and put in front of users rather than left sitting in a scratch folder — that's exactly the kind of focused build I take from zero to released.

Iurii Rogulia

Working on something like this?

MVP Development

Need a small, focused tool shipped end to end — built, packaged, and put in front of users? Shipping tight, trustworthy software is what I do.

More about this service

Relevant client work

View all projects
YouTube Home Blocker — Manifest V3 Chrome Extension
YouTube Home Blocker — Manifest V3 Chrome Extension
June 5, 2026
YouTube Home Blocker — Manifest V3 Chrome Extension

A Manifest V3 Chrome extension that redirects the YouTube homepage to any URL you choose — so you skip the recommendations feed without losing search, videos,

Wrongulator — The Calculator That Is Confidently Incorrect
Wrongulator — The Calculator That Is Confidently Incorrect
May 31, 2026
Wrongulator — The Calculator That Is Confidently Incorrect

A joke calculator that returns a deterministically wrong answer with a straight-faced reason — built as a share machine.

EU VAT Rates for WooCommerce — WordPress Plugin
EU VAT Rates for WooCommerce — WordPress Plugin
August 5, 2026
EU VAT Rates for WooCommerce — WordPress Plugin

WordPress plugin that keeps WooCommerce EU tax rates current from the European Commission and applies the B2B reverse charge from a VIES-verified VAT number at

Related articles

Programmatic SEO with hreflang: One Joke, 17 Languages, Server-Rendered
July 29, 2026· 7 min
Programmatic SEO with hreflang: One Joke, 17 Languages, Server-Rendered

Programmatic SEO with hreflang: how each wrong answer in a viral toy is a server-rendered page with localized meta and JSON-LD, across 17 languages.

Stack

JavaScriptNode.js

Libraries

Express

Topics

Programmatic SEOi18nOpen GraphViral Product
Isomorphic Canvas Rendering: One draw() in Browser and Node
July 10, 2026· 7 min
Isomorphic Canvas Rendering: One draw() in Browser and Node

Isomorphic canvas rendering: one drawCard() runs in the browser and on the server via @napi-rs/canvas, so the share image and in-app card never drift.

Stack

JavaScriptNode.js

Libraries

@napi-rs/canvasExpress

Topics

Open GraphViral ProductWeb Development
When AI Beats a Senior Developer — and When It Doesn't
July 3, 2026· 8 min
When AI Beats a Senior Developer — and When It Doesn't

AI vs senior developer is the wrong question. The right one is which class of task — by type, not difficulty — is faster to delegate to an AI agent.

Topics

AI CodingEngineeringProductivity
Deterministic Wrong: Why a Viral Web Toy Must Be Wrong the Same Way Every Time
June 29, 2026· 7 min
Deterministic Wrong: Why a Viral Web Toy Must Be Wrong the Same Way Every Time

Deterministic random in JavaScript: why a viral web toy dies if it uses Math.random(), and how FNV-1a + mulberry32 make the same wrong answer reproducible

Stack

JavaScript

Topics

Viral ProductAlgorithmsWeb Development