YouTube Fixed
| // URL of the hosted selectors.json — update if the repo moves | ||
| const SELECTORS_URL = | ||
| "https://raw.githubusercontent.com/liquidcode7/yt-fixed/main/selectors.json"; | ||
| const CACHE_KEY = "selectorCache"; | ||
| const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours | ||
| async function fetchAndCache() { | ||
| try { | ||
| const res = await fetch(SELECTORS_URL); | ||
| if (!res.ok) throw new Error(`HTTP ${res.status}`); | ||
| const data = await res.json(); | ||
| await browser.storage.local.set({ | ||
| [CACHE_KEY]: { ...data, cachedAt: Date.now() }, | ||
| }); | ||
| } catch (err) { | ||
| console.warn("[yt-fixed] Selector fetch failed:", err.message); | ||
| // Cached version (or hardcoded fallback in content.js) will be used | ||
| } | ||
| } | ||
| async function maybeRefresh() { | ||
| const result = await browser.storage.local.get(CACHE_KEY); | ||
| const cache = result[CACHE_KEY]; | ||
| if (!cache || Date.now() - cache.cachedAt > CACHE_TTL_MS) { | ||
| await fetchAndCache(); | ||
| } | ||
| } | ||
| // On install: create the daily alarm and do an immediate fetch | ||
| browser.runtime.onInstalled.addListener(() => { | ||
| browser.alarms.create("refreshSelectors", { periodInMinutes: 1440 }); | ||
| fetchAndCache(); | ||
| }); | ||
| // On browser startup: refresh if cache is stale | ||
| browser.runtime.onStartup.addListener(maybeRefresh); | ||
| // Daily alarm fires even when the background is sleeping (event page) | ||
| browser.alarms.onAlarm.addListener((alarm) => { | ||
| if (alarm.name === "refreshSelectors") fetchAndCache(); | ||
| }); |
| { | ||
| "version": 1, | ||
| "js": [ | ||
| "ytd-reel-shelf-renderer", | ||
| "ytd-reel-item-renderer", | ||
| "ytd-compact-autoplay-renderer", | ||
| "ytd-search-pyv-renderer", | ||
| ".ytp-ce-element", | ||
| ".ytp-endscreen-content", | ||
| "ytm-shorts-lockup-view-model-v2", | ||
| "grid-shelf-view-model", | ||
| "ytd-merch-shelf-renderer", | ||
| "ytd-primetime-promo-renderer", | ||
| "ytd-statement-banner-renderer", | ||
| "ytd-donation-shelf-renderer", | ||
| "ytd-brand-video-shelf-renderer" | ||
| ], | ||
| "css": [ | ||
| "ytd-reel-shelf-renderer", | ||
| "ytd-guide-entry-renderer a[href=\"/shorts\"]", | ||
| "tp-yt-paper-tab:has(> .tab-content[aria-label=\"Shorts\"])", | ||
| "ytd-reel-item-renderer", | ||
| "yt-chip-cloud-chip-renderer:has([title=\"Shorts\"])", | ||
| "ytd-guide-entry-renderer a[href=\"/gaming\"]", | ||
| "yt-chip-cloud-chip-renderer:has([title=\"Gaming\"])", | ||
| "ytd-autoplay-config-renderer", | ||
| ".ytp-ce-element", | ||
| ".ytp-endscreen-content", | ||
| "ytd-compact-autoplay-renderer", | ||
| "ytd-search-pyv-renderer", | ||
| "ytd-rich-shelf-renderer", | ||
| "ytd-merch-shelf-renderer", | ||
| "ytd-primetime-promo-renderer", | ||
| "ytd-statement-banner-renderer", | ||
| "ytd-donation-shelf-renderer", | ||
| "ytd-brand-video-shelf-renderer" | ||
| ] | ||
| } |
+40
-9
@@ -1,2 +0,3 @@ | ||
| const SELECTORS_TO_REMOVE = [ | ||
| // Hardcoded fallback — used when cache is empty or storage is unavailable | ||
| const FALLBACK_JS_SELECTORS = [ | ||
| "ytd-reel-shelf-renderer", | ||
@@ -10,12 +11,19 @@ "ytd-reel-item-renderer", | ||
| "grid-shelf-view-model", | ||
| "ytd-merch-shelf-renderer", | ||
| "ytd-primetime-promo-renderer", | ||
| "ytd-statement-banner-renderer", | ||
| "ytd-donation-shelf-renderer", | ||
| "ytd-brand-video-shelf-renderer", | ||
| ]; | ||
| let activeSelectors = FALLBACK_JS_SELECTORS; | ||
| function removeJunk() { | ||
| for (const selector of SELECTORS_TO_REMOVE) { | ||
| document.querySelectorAll(selector).forEach(el => el.remove()); | ||
| for (const selector of activeSelectors) { | ||
| document.querySelectorAll(selector).forEach((el) => el.remove()); | ||
| } | ||
| // Remove Shorts from sidebar by href | ||
| document.querySelectorAll("ytd-guide-entry-renderer a").forEach(a => { | ||
| if (a.href.includes("/shorts")) { | ||
| // Remove Shorts and Gaming from sidebar by href | ||
| document.querySelectorAll("ytd-guide-entry-renderer a").forEach((a) => { | ||
| if (a.href.includes("/shorts") || a.href.includes("/gaming")) { | ||
| a.closest("ytd-guide-entry-renderer")?.remove(); | ||
@@ -26,7 +34,30 @@ } | ||
| // Run once immediately when page loads | ||
| function injectCSS(cssSelectors) { | ||
| const style = document.createElement("style"); | ||
| style.textContent = | ||
| cssSelectors.join(",\n") + " { display: none !important; }"; | ||
| (document.head || document.documentElement).appendChild(style); | ||
| } | ||
| // Run immediately with hardcoded fallback selectors | ||
| removeJunk(); | ||
| // Then keep watching for new elements being injected | ||
| // Observe from documentElement — body may not exist yet at document_start | ||
| const observer = new MutationObserver(removeJunk); | ||
| observer.observe(document.body, { childList: true, subtree: true }); | ||
| observer.observe(document.documentElement, { childList: true, subtree: true }); | ||
| // Async: load cached selectors and apply them | ||
| // Falls back silently to the hardcoded list if storage is unavailable | ||
| browser.storage.local.get("selectorCache").then(({ selectorCache }) => { | ||
| if (!selectorCache) return; | ||
| if (selectorCache.js) { | ||
| activeSelectors = selectorCache.js; | ||
| removeJunk(); // Re-run with updated list | ||
| } | ||
| if (selectorCache.css) { | ||
| // Injects supplemental CSS on top of the hardcoded style.css | ||
| injectCSS(selectorCache.css); | ||
| } | ||
| }); |
+8
-4
| { | ||
| "manifest_version": 2, | ||
| "name": "YouTube Fixed", | ||
| "version": "1.0", | ||
| "description": "No Shorts, no algorithm noise, subscriptions as home.", | ||
| "version": "1.1", | ||
| "description": "No Shorts, no Games, no algorithm noise. YouTube the way it should be.", | ||
| "permissions": [ | ||
| "webNavigation", | ||
| "tabs", | ||
| "https://www.youtube.com/*" | ||
| "storage", | ||
| "alarms", | ||
| "https://www.youtube.com/*", | ||
| "https://raw.githubusercontent.com/*" | ||
| ], | ||
@@ -27,3 +30,4 @@ "content_scripts": [ | ||
| "scripts": [ | ||
| "redirect.js" | ||
| "redirect.js", | ||
| "selector-fetcher.js" | ||
| ], | ||
@@ -30,0 +34,0 @@ "persistent": false |
+1
-15
@@ -1,15 +0,1 @@ | ||
| browser.webNavigation.onCommitted.addListener((details) => { | ||
| // Only act on the main frame (not iframes) | ||
| if (details.frameId !== 0) return; | ||
| const url = new URL(details.url); | ||
| // Redirect bare homepage to subscriptions | ||
| if (url.pathname === "/" || url.pathname === "") { | ||
| browser.tabs.update(details.tabId, { | ||
| url: "https://www.youtube.com/feed/subscriptions" | ||
| }); | ||
| } | ||
| }, { | ||
| url: [{ hostEquals: "www.youtube.com" }] | ||
| }); | ||
| // No redirects — home stays home. |
+15
-0
@@ -10,2 +10,8 @@ /* ── Shorts: nuke from orbit ─────────────────────── */ | ||
| /* ── Gaming: also no ─────────────────────────────── */ | ||
| ytd-guide-entry-renderer a[href="/gaming"], | ||
| yt-chip-cloud-chip-renderer:has([title="Gaming"]) { | ||
| display: none !important; | ||
| } | ||
| /* ── Autoplay & end screen junk ──────────────────── */ | ||
@@ -24,1 +30,10 @@ ytd-autoplay-config-renderer, | ||
| } | ||
| /* ── Merch, promos, and other bullshit ───────────── */ | ||
| ytd-merch-shelf-renderer, | ||
| ytd-primetime-promo-renderer, | ||
| ytd-statement-banner-renderer, | ||
| ytd-donation-shelf-renderer, | ||
| ytd-brand-video-shelf-renderer { | ||
| display: none !important; | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| # Firefox web-ext build artifacts | ||
| web-ext-artifacts/ | ||
| *.zip | ||
| *.xpi | ||
| # OS junk | ||
| .DS_Store | ||
| Thumbs.db |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet