# BetterTTV is a Vite bundle you develop against a local userscript

> BetterTTV is the browser extension that adds features and emotes to Twitch, and the interesting part for a developer is how it is built and debugged. The whole thing is bundled by Vite into a single betterttv.js, served locally on port 2888 during development, and loaded into the page by a small userscript that points at your machine instead of at the extension.

**night/betterttv** — BetterTTV enhances Twitch with new features, emotes, and more.

- Repository: https://github.com/night/betterttv
- Website: https://betterttv.com
- Stars: 1,296 · Forks: 268
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/night-betterttv

## What the project is

BetterTTV enhances Twitch with new features, emotes and more, and the project is published under the name of NightDev, LLC, with the homepage at betterttv.com. The repository is the source of the browser extension rather than a library, and the shape of the tree reflects that, with a src/ directory holding the sources, a vite.config.js for the bundling, an eslint.config.mjs and a .prettierrc for the style rules, a jsconfig.json for the editor, and the usual lockfile and metadata. The release history shows a project that ships often, with 7.7.28 published on 2026-10-06, 7.7.27 on 2026-10-05 and 7.7.26 on 2026-09-30, and the last push on 2026-10-15. The package version in the manifest matches the newest release, and the package is marked as an ES module with the built file betterttv.js as its main entry point. Translations are handled through Crowdin, and the licence is one of the custom ones that GitHub cannot classify, so the LICENSE file in the repository is the text that counts.

## The dev server on port 2888

The build documentation is short because the toolchain is conventional. You install Node.js, then run the install inside the BetterTTV directory:

```bash
npm install
```

and for development the project uses Vite to bundle all of the files and templates into one. The command to start it is:

```bash
npm start
```

That builds betterttv.js and serves it on port 2888, rebuilding on every change and reloading the page once the rebuild finishes. The one bundled file is the important design decision, because the extension ships as a single script that is injected into the page, and the same shape is used in development so that what you test locally is what users get. The package scripts make the variants explicit, with a development mode for the watch build and a production build for shipping, and the build commands differ only in the mode flag. The lint step is ESLint together with Prettier, and the internationalisation step is a separate script that extracts the messages.

## The userscript that loads your local build

Here is the part that makes the development loop work, and it is a small userscript you install in a script manager such as TamperMonkey. The metadata block tells the manager where the script should run:

```javascript
// ==UserScript==
// @name         BetterTTV Development
// @description  Enhances Twitch with new features, emotes, and more.
// @namespace    http://betterttv.com/
// @copyright    NightDev, LLC
// @icon         https://cdn.betterttv.net/assets/logos/bttv_logo.png
// @version      0.0.1
// @match        https://*.twitch.tv/*
// @match        https://*.youtube.com/*
// @grant        none
// ==/UserScript==
```

The body of the script creates a script element pointing at the local server and appends it to the page head, which is how the development build gets into Twitch. Two details are worth noting. The match patterns cover both twitch.tv and youtube.com, which tells you the bundle is expected to run on more than one site. And the documentation says that once this is installed you should disable BetterTTV's main extension, so that BetterTTV is only loaded from your computer and you are not running two copies of it at once, which would be a confusing way to spend an afternoon.

## Turning on the debug log

BetterTTV has a settings object, and the console output is off by default, so the first thing a developer does is switch it on. The documentation says that to receive debug messages inside the browser's console log you must toggle the consoleLog localStorage setting, and the way to do that is to type this in the JavaScript console:

```javascript
BetterTTV.settings.set('consoleLog', true);
```

That is a global on the page rather than a file to edit, which is convenient because the setting survives a rebuild of the bundle, so you toggle it once and it stays on while you work. The setting is named in the same style as the rest of the settings API, and the fact that it is a settings set call rather than a console flag means it goes through the same path the extension uses in production, which is the behaviour you want when you are chasing a bug that only shows up in the shipped configuration.

## Linting, and linting while you type

The project uses ESLint to ensure a consistent code style and to avoid buggy code, and the lint script runs ESLint over the tree and then asks Prettier to check formatting. The rule for contributors is stated plainly: run npm run lint, fix any errors before creating a pull request, and any warnings produced prior to your changes can be ignored. The second half of that sentence is the useful one in practice, because a large codebase accumulates warnings and the convention is that your change should not add errors without needing to clean up the whole file. The documentation then covers two ways of getting the same feedback while you type rather than at commit time. For Sublime Text, you install ESLint, then Sublime Package Control, then SublimeLinter, then the SublimeLinter-eslint package. For VSCode, you install ESLint through npm and add the ESLint extension from the extensions marketplace. Both routes run the same rules the CI will run, so the difference between a warning on screen and a failure in review disappears.

## What the dependency list says about the product

The package dependencies are a map of the feature set. The interface layer is Mantine for core, hooks and modals, Framer Motion for animation, dnd-kit for drag and drop with sortable and modifiers, Floating UI for positioning, Font Awesome for icons, classnames for conditional class names and the twemoji API for emoji rendering. The platform layer includes Sentry for browser error reporting, cookies-js for the cookies the extension has to work with, pkce-challenge for the authorisation flow, graphql-tag for the GraphQL requests, a small set of lodash utilities for chunking, debouncing, sorting and deduplication, Luxon for dates, Fuse.js for fuzzy search, file-saver for downloads, and a couple of event helpers. The internationalisation layer is @formatjs/intl, and there is a dedicated script that extracts the messages with an id interpolation pattern based on a sha512 content hash, which is what makes it safe to change the wording of a message without invalidating every translation of it.

## Conclusion

BetterTTV fits a developer who wants to work on a Twitch extension without fighting the extension packaging, since the local Vite server and the userscript loader make the edit and reload loop short, and the same source builds the shipped bundle. It does not fit someone who wants to install the extension and configure it, since the repository is a development environment rather than a user manual. It does not fit a team that cannot work with a bundled single file, because everything ends up in one betterttv.js, which is good for deployment and awkward for code review. Before you start, read the licence file, since the project does not use one of the licences GitHub can classify, and run npm run lint before you open a pull request, because the project expects errors to be fixed and only warnings ignored.

## FAQ

### What is BetterTTV?

It is a browser extension that enhances Twitch with new features, emotes and more, published by NightDev, LLC. The source is bundled by Vite into a single betterttv.js, and the package version follows the extension releases, with 7.7.28 published on 2026-10-06.

### How do I run BetterTTV from source?

Install Node.js, run npm install in the project directory and then npm start, which builds betterttv.js, serves it on port 2888 and rebuilds on every change. You then load it into the page with a TamperMonkey userscript pointing at the local server, and disable the main extension so only one copy runs.

### How do I see the debug output in BetterTTV?

Toggle the consoleLog localStorage setting by running BetterTTV.settings.set('consoleLog', true) in the browser's JavaScript console, and the debug messages then appear in the console log.

### What does the lint setup check?

ESLint is used for a consistent code style and to catch buggy code, and Prettier checks formatting, both under the lint script. Errors must be fixed before a pull request is opened, while warnings that predate your change can be ignored, and the documentation explains how to run the same checks live in Sublime Text or VSCode.

### How are BetterTTV translations handled?

Translations go through Crowdin, and the project has a script that extracts the messages with formatjs using an id interpolation pattern based on a sha512 content hash, so rewording a message does not invalidate the translations of it.

## Sources

- [Issues](https://github.com/night/betterttv/issues)
- [night/betterttv on GitHub](https://github.com/night/betterttv)
- [Project website](https://betterttv.com)
- [README](https://github.com/night/betterttv/blob/master/README.md)
- [Releases](https://github.com/night/betterttv/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/night-betterttv
