Thanks for your interest. PRs and issues are welcome.
Requirements: Node 20+, pnpm 9+.
pnpm install
pnpm icons # generate icon PNGs (one-time)
pnpm dev # HMR build; load dist/ as unpacked extension in ChromeFor a production build:
pnpm buildAfter either command, in chrome://extensions:
- Enable Developer mode.
- Click Load unpacked and select the
dist/folder. - Pin the extension to the toolbar.
- TypeScript strict mode — no
anywithout a comment justifying it. - Run
pnpm typecheckandpnpm lintbefore pushing. Both must pass. - Run
pnpm formatto apply Prettier; CI will not auto-fix. - Keep components focused; split when a file gets >250 lines.
- Use the existing
Primercolor tokens (bg-canvas,text-fg,text-fg-muted,border-border, etc.) instead of hard-coded hex.
- The background service worker is the only place that mutates timing state. Don't track timestamps in content scripts or the popup.
- Listeners must be registered synchronously at top level of
service-worker.tsso the SW can wake on events. - Tab state lives in
chrome.storage.sessiononly — never module-level Maps; the SW gets terminated. - Use
chrome.alarms, neversetInterval/setTimeoutfor periodic work.
-
pnpm typecheckpasses -
pnpm lintpasses - Tested manually: load
dist/in Chrome, exercise the changed surface (popup / banner / refresh / reminder). - Updated README / docs if behavior changed.
- No secrets, telemetry endpoints, or remote calls added.
Open an issue with:
- Browser + version (e.g. Chrome 131, Brave 1.72)
- OS + version
- Extension version (popup footer)
- Steps to reproduce
- Expected vs. actual behavior
- Screenshots if visual
User-visible changes go in CHANGELOG.md under the ## [Unreleased] section. Use the Keep a Changelog categories: Added, Changed, Deprecated, Removed, Fixed, Security. Internal-only changes (refactors, CI tweaks, doc fixes) don't need an entry.
See RELEASING.md — pnpm release:patch|minor|major then git push --follow-tags triggers the Release workflow.
By contributing, you agree your contributions will be MIT-licensed.