Depatronise Patreon Userscript

Ich weiß nicht mehr genau, wann und warum, aber ich habe wohl irgendwann mal bei Patreon auf den falschen Button gedrückt und bin seitdem mit einem unveröffentlichten Patreon-Creator-Profil gestraft. 🙄

Die Navigation ist seitdem jedes Mal aufs Neue verwirrend: Das Häuschen-Icon bedeutet nicht mehr „Home“, sondern „Dein Kreativ*er-Studio“ – na klar – und führt dementsprechend zu /create. Das Welt-Icon ist hingegen der „Feed“, der unter /home zu finden ist. Ja sicher. Dazu gibt es einen „+“-Button, mit dem ich Beiträge für meine unveröffentlichte Seite anlegen kann.

Alles sehr durchdacht also. Wow.

Es wäre schön, wenn man das unveröffentlichte Profil einfach löschen könnte. Geht aber nicht. Na gut – Zeit für ein Userscript, das damit aufräumt!

// ==UserScript==
// @name         Depatronise Patreon
// @namespace    https://marcgoertz.de/
// @version      1.2.3
// @description  Hide all creator UI on Patreon: the creator-studio nav menu, the home/create link, the create-post button, the link to your own page, and the creator-settings section. Language-independent (keys off data-tags, not visible labels).
// @author       Marc Görtz
// @icon         https://www.patreon.com/favicon.ico
// @match        https://www.patreon.com/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  // ---------------------------------------------------------------------------
  // Config — tweak these if Patreon renames things or you want other locales.
  // ---------------------------------------------------------------------------

  // The home→/create link, matched by href. The responsive/mobile nav renders
  // this as a plain <a> with no data-tag, so href is the only handle. Both
  // relative and absolute forms are checked ("starts with", so any suffix hits).
  const HREF_PREFIXES = [
    '/create',
    'https://www.patreon.com/create',
  ];

  // Buttons / menu triggers to hide, matched by stable data-tag hooks (these
  // stay constant across UI languages, unlike the visible label). The create
  // button's visible text varies by variant (or is icon-only), so keying off
  // the data-tag is far more reliable than matching its label.
  const HIDE_SELECTORS = [
    '[data-tag="create-content-button"]', // create-post button, all variants
    '[data-tag="collapsible-nav-submenu-trigger"]', // creator-studio nav menu
    '[data-tag="your-page-nav-button"]', // link to your own page (belt-and-braces)
  ];

  // Creator-settings section (the sidebar group of creator-only settings).
  // Matched by stable, language-independent hooks:
  // each link has data-tag="creator_settings_*" and href="/settings-creator/*".
  // The whole section (heading + list) is the <ul>’s parent, so we hide that.
  const SETTINGS_LINK_SELECTOR =
    'a[data-tag^="creator_settings"], a[href*="/settings-creator"]';

  // ---------------------------------------------------------------------------

  // Walk up until we hit a natural nav “item” wrapper, so we hide the whole
  // entry (icon + label + padding) instead of leaving an empty gap.
  function navItem(el) {
    let node = el;
    for (let i = 0; i < 4 && node?.parentElement; i += 1) {
      if (node.tagName === 'LI') return node;
      node = node.parentElement;
    }
    return el;
  }

  function hide(el) {
    if (el && el.style.display !== 'none') {
      el.style.setProperty('display', 'none', 'important');
    }
  }

  function apply() {
    // 1) The home→/create link by href (plain <a>, no data-tag to key off).
    for (const link of document.querySelectorAll('a[href]')) {
      const href = link.getAttribute('href') ?? '';
      if (HREF_PREFIXES.some((prefix) => href.startsWith(prefix))) {
        hide(navItem(link));
      }
    }

    // 2) The create button + creator-studio menu, by stable data-tag.
    for (const el of document.querySelectorAll(HIDE_SELECTORS.join(', '))) {
      hide(navItem(el));
    }

    // 3) The creator-settings section — heading + all its links. Grab any
    //    creator-settings link, then hide the section wrapper (the <ul>’s
    //    parent, which also holds the heading).
    for (const link of document.querySelectorAll(SETTINGS_LINK_SELECTOR)) {
      const section = link.closest('ul')?.parentElement;
      hide(section ?? navItem(link));
    }
  }

  // Run now, and re-run whenever Patreon’s SPA re-renders the nav (route
  // changes, lazy-loaded menus, etc.). MutationObserver keeps it working
  // without reloads.
  const start = () => {
    apply();
    const observer = new MutationObserver(() => apply());
    observer.observe(document.documentElement, {
      childList: true,
      subtree: true,
    });
  };

  if (document.body) {
    start();
  } else {
    document.addEventListener('DOMContentLoaded', start, { once: true });
  }
})();

Und das war’s auch schon. Das Userscript entfernt das Creator-Profil aus meiner Navigation und macht Patreon damit wieder ein kleines bisschen weniger verwirrend.

Eigentlich hätte dafür ein Button mit der Aufschrift „Profil löschen“ gereicht. Aber gut – wo kämen wir denn hin, wenn eine Website einfach mal das tun würde, was man von ihr erwartet?

Gib Deinen Senf dazu

Oder hinterlasse einen guten, alten Kommentar. Bleib aber bitte höflich und beim Thema!

Meine Datenschutzerklärung nimmst Du mit dem Abschicken zur Kenntnis.