Adding a feature
A feature is a folder under src/features/ and one line in src/features/index.ts. It shows up in the popup and shuts off cleanly, and the core needs no change.
A CSS-only feature
Section titled “A CSS-only feature”src/features/seek-height/index.tssrc/features/seek-height/style.cssimport type { Feature } from '../../core/feature.ts';
export const seekHeight: Feature = { id: 'seek-height', label: 'Seek bar height', group: 'watch', defaultOn: false, options: { height: { type: 'number', label: 'Height', default: 4, cssVar: '--kyt-seek-height' } },};/* style.css: every rule gated by the feature's attribute */html[kyt-seek-height] .ytp-progress-bar { height: calc(var(--kyt-seek-height) * 1px);}import { seekHeight } from './seek-height/index.ts';export const features: Feature[] = [/* ... */, seekHeight];build.mjs picks up style.css on its own.
A feature with code
Section titled “A feature with code”Add routes and run:
export const example: Feature = { id: 'example', label: 'Example', group: 'watch', defaultOn: true, routes: ['watch'], run(ctx) { const box = document.createElement('div'); const update = () => { box.textContent = location.search; }; waitFor(S.watchMetadata, { signal: ctx.signal }).then((el) => el?.prepend(box)); document.addEventListener('kyt:navigate', update, { signal: ctx.signal }); ctx.signal.addEventListener('abort', () => box.remove()); },};- YouTube selectors used from JS go in
src/core/selectors.ts. Prefer structure and YouTube’s camelCase classes over translatedaria-labels. - Every listener and observer takes
ctx.signal. On abort, put YouTube’s page back as you found it. - Labels you draw go through
local()with a table for every language. See Languages. - If you need YouTube’s data, add a
page.ts. See Page bridge.
Checklist
Section titled “Checklist”npm run check && npm test && npm run buildtest/structure.test.ts checks that the feature is registered, that every CSS rule is gated by html[kyt-<id>], that page handler names are unique, and that every page.ts is registered. If it fails, fix the code and leave the test alone.
Before you open a PR, read YouTube quirks. Each entry there cost a debugging round.