Skip to content

Instantly share code, notes, and snippets.

@aleclarson
Last active June 17, 2026 11:40
Show Gist options
  • Select an option

  • Save aleclarson/d91b3f022b877ceee4ec225f1513b3a6 to your computer and use it in GitHub Desktop.

Select an option

Save aleclarson/d91b3f022b877ceee4ec225f1513b3a6 to your computer and use it in GitHub Desktop.
TamperMonkey script for automatic redirects from npmjs.org packages to their npmx.dev equivalents

npmjs to npmx Tampermonkey Scripts

Two Tampermonkey userscripts that make npm package browsing default to npmx.dev, while still allowing you to intentionally open the original npm package page from npmx.

Scripts

npmjs-to-npmx.js

Redirects npm package URLs to the same path on npmx.dev.

Runs on:

  • https://www.npmjs.com/package/*
  • https://npmjs.com/package/*
  • https://www.npmjs.org/package/*
  • https://npmjs.org/package/*

Behavior:

  • Runs at document-start.
  • Redirects npm package pages to https://npmx.dev.
  • Redirects when activeTab is absent or set to readme.
  • Preserves pathname, query string, and hash when redirecting.
  • Skips redirecting when activeTab is present and set to anything other than readme.
  • Skips redirecting when the npm page was opened from npmx.dev.

Example:

https://www.npmjs.com/package/typescript?activeTab=readme

becomes:

https://npmx.dev/package/typescript?activeTab=readme

npmx-preserve-npm-referrer.js

Allows npm links clicked from npmx.dev to send a referrer, so npmjs-to-npmx.js can detect that the visit came from npmx and avoid redirecting back.

Runs on:

  • https://npmx.dev/*

Behavior:

  • Finds links to npm package pages.
  • Removes only noreferrer from matching links' rel attribute.
  • Leaves noopener and any other rel values intact.
  • Rechecks links when the page changes and immediately before pointer or keyboard activation.

This is needed because npm links on npmx.dev may use rel="noopener noreferrer". The noreferrer value prevents document.referrer from being set on npm, which would make the redirect script unable to know that the visit came from npmx.

Installation

Install both .js files as separate Tampermonkey scripts:

  • npmjs-to-npmx.js
  • npmx-preserve-npm-referrer.js

Caveat

The skip behavior depends on the browser sending a referrer from npmx.dev to npm. Removing noreferrer from the link is usually enough, but a site-wide Referrer-Policy: no-referrer from npmx.dev would still prevent this from working.

// ==UserScript==
// @name npmjs Package Redirect to npmx.dev
// @namespace https://www.npmjs.com/
// @version 0.1
// @description Redirects npmjs package pages to npmx.dev with the same path
// @match https://www.npmjs.com/package/*
// @match https://npmjs.com/package/*
// @match https://www.npmjs.org/package/*
// @match https://npmjs.org/package/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
"use strict";
if (!isPackageOverviewPath(window.location.pathname)) {
console.debug("[npmjs-to-npmx] Skipping redirect because path is not a package overview", {
pathname: window.location.pathname,
});
return;
}
if (isFromNpmx()) {
console.debug("[npmjs-to-npmx] Skipping redirect because referrer is npmx.dev", {
referrer: document.referrer,
});
return;
}
const activeTab = new URL(window.location.href).searchParams.get("activeTab");
if (activeTab && activeTab !== "readme") {
console.debug("[npmjs-to-npmx] Skipping redirect because activeTab is not readme", {
activeTab,
href: window.location.href,
});
return;
}
const target = new URL(window.location.href);
target.hostname = "npmx.dev";
target.protocol = "https:";
window.location.replace(target.href);
function isFromNpmx() {
try {
return new URL(document.referrer).hostname === "npmx.dev";
} catch {
return false;
}
}
function isPackageOverviewPath(pathname) {
const parts = pathname.replace(/\/+$/, "").split("/").filter(Boolean);
return parts[0] === "package" && (parts.length === 2 || (parts.length === 3 && parts[1].startsWith("@")));
}
})();
// ==UserScript==
// @name npmx Preserve npm Referrer
// @namespace https://npmx.dev/
// @version 0.1
// @description Allows npm package links from npmx.dev to send a referrer
// @match https://npmx.dev/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
"use strict";
const NPM_PACKAGE_LINK_SELECTOR =
'a[href^="https://www.npmjs.com/package/"], a[href^="https://npmjs.com/package/"], a[href^="https://www.npmjs.org/package/"], a[href^="https://npmjs.org/package/"]';
patchLinks();
const observer = new MutationObserver(patchLinks);
observer.observe(document.documentElement, { childList: true, subtree: true });
document.addEventListener("pointerdown", patchLinks, true);
document.addEventListener("keydown", patchLinks, true);
function patchLinks() {
document.querySelectorAll(NPM_PACKAGE_LINK_SELECTOR).forEach((link) => {
const rel = link.getAttribute("rel");
if (!rel) return;
const values = rel
.split(/\s+/)
.filter((value) => value && value.toLowerCase() !== "noreferrer");
if (values.length === rel.split(/\s+/).filter(Boolean).length) {
return;
}
if (values.length > 0) {
link.setAttribute("rel", values.join(" "));
} else {
link.removeAttribute("rel");
}
});
}
})();
@angeloanan

Copy link
Copy Markdown

Thanks a lot for the script, it works well 🎉

Would you mind editing the file name to end with .user.js so that the web extension "catches" the raw file as an user script? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment