A TypeScript-tooled workspace for writing Tampermonkey
userscripts. It uses Vite and
vite-plugin-monkey, so you get
modern tooling: TypeScript type-checking, full autocomplete for the GM_* API,
a live-reloading dev server, and a one-command build that produces an
installable userscript.
If you have never used any of this before, don't worry — follow the steps below in order.
- Node.js 18 or newer. Check with
node --version. If you don't have it, install it from nodejs.org. - The Tampermonkey browser extension, installed in your browser. Get it from tampermonkey.net.
Install the project dependencies once:
npm installnpm run devThis starts a Vite dev server and prints a URL in your terminal. With
Tampermonkey installed, open that URL — Tampermonkey auto-detects the dev
script and offers to install it. Once installed, visit a page that matches your
script (by default https://example.com/) and your script runs there. As you
edit src/main.ts, the page live-reloads with your changes.
npm run buildThis produces an installable file at dist/*.user.js. To install it, drag that
file into your browser (or open it) and Tampermonkey will prompt you to install.
This is the file you share or keep as the finished userscript.
npm run typecheckRuns TypeScript with no output, just to catch type errors before you build.
Open vite.config.ts and edit the match array inside the userscript block.
For example, to run on GitHub:
match: ['https://github.com/*'],You can list several patterns. See the
Tampermonkey @match docs
for the pattern syntax.
Some Tampermonkey features (storage, cross-origin requests, clipboard, etc.)
require an explicit grant. Add the ones you need to the grant array in
vite.config.ts, for example:
grant: ['GM_setValue', 'GM_getValue', 'GM_xmlhttpRequest'],Then call them from src/main.ts — the types are already available.
This project builds one userscript per Vite build. The metadata for that
script lives in the userscript block in vite.config.ts. To add a second,
independent script, the simplest approach is to copy this repo's config
pattern: give the new script its own entry file (e.g. src/other.ts) and its
own userscript block, and run a separate build for it. Keep each script
self-contained so it's easy to reason about.
Use reference/ to drop in anything that helps you build: saved HTML of a
target page, existing scripts you're adapting, or plain notes. Nothing there is
bundled into your userscript — it's just a scratch area for you.
Step-by-step lessons on how userscripts, extensions, and the browser work,
built around one real project. Start with learning/README.md.