- pnpm
- WXT extension framework
- Svelte 5 (content scripts and popup)
- TypeScript (100% type safety, let TypeScript infer return types)
- @ffmpeg/ffmpeg for video/audio processing
- @webext-core/messaging for message passing
- Chromium (Chrome, Edge, Opera) MV3 + Firefox MV3
- Single shared code path; branch only when an API genuinely diverges
- Offscreen API is Chrome-only; Firefox falls back to a hidden iframe hosted by the background event page (see
background/handlers/processor.ts) - Firefox manifest is emitted via the
manifestfunction inwxt.config.ts(nooffscreenpermission, nominimum_chrome_version, getsbrowser_specific_settings.gecko)
- Use the
browsernamespace - Use early returns for readability and maintainability
- Use functional programming
- Use async/await whenever possible
- Use DRY with separation of concerns, prioritizing readability
- Minimize indentations
- Use
for-ofinstead of.forEach - Use modern browser and CSS features
- Avoid
window.prefixes unless it increases readability - Avoid
setTimeoutunless absolutely necessary - Avoid comments unless absolutely necessary - prefer descriptive names
- Don't use em dashes - use regular hyphens
- If a callback arrow function has a typed param, don't annotate the type explicitly
- Avoid nested try/catch - flatten with early returns or extracted functions
- Apply parallel modifications whenever possible
- Variables and functions:
camelCase, full words (no abbreviations) - Module-level constants:
SCREAMING_SNAKE_CASE - Exception: event handler first parameter is always
e
- Element:
elprefix (e.g.elButton) - Index:
iprefix (e.g.iItem), or bareiwhen iterating in a for loop/higher-order function - Boolean:
isprefix (e.g.isLoading)
- Strings: use enums; if no enum fits, use a descriptive
SCREAMING_SNAKE_CASEconstant - Numbers: use a descriptive
SCREAMING_SNAKE_CASEconstant
- Single-use functions: inline them
@attacharrow functions in templates: extract to named functions in the script block
- Don't automatically persist to storage - rely on fallback values; only use storage when the user has explicitly set something
- No full stops at end of messages
- Informal tone
After each modification, lint with oxlint, ESLint, Stylelint, svelte-check, and npx fallow audit.
scripts/dev-server.ts auto-rebuilds and reloads the extension and every YouTube page on any file change under src/.