Thanks for considering a contribution.
This project aims to stay small, deterministic, and heavily tested. Please read the public docs before proposing API changes:
The library owns:
- timer lifecycle state
- reliable ticking
- elapsed time calculation
- pause/resume/reset/restart/cancel behavior
- once-only end callbacks
- optional schedules
- opt-in semantic debug logs
- many keyed timer lifecycles through
useTimerGroup
The library does not own:
- formatting
- timezone conversion
- localization
ampmfields- data fetching lifecycle
- retries or backoff
- sound/audio behavior
- app business state
- Open or reference an issue for non-trivial changes.
- Add or update tests first.
- Implement the smallest change that satisfies the tests.
- Update docs for public API changes.
- Add a changeset once release automation is configured.
- Run the full local validation script before opening a PR.
Expected commands after project setup:
node --version # v24.x
pnpm test
pnpm typecheck
pnpm build
pnpm docs:build
pnpm size
pnpm readme:checkUse short-lived branches:
feature/*for featuresfix/*for fixesdocs/*for docschore/*for maintenance
Alpha releases are published from next. Stable publishing is manually locked until the project intentionally switches to final releases.
Use Conventional Commits:
<type>(<scope>): <summary>Examples:
feat(timer): implement lifecycle controls
fix(group): preserve item state across rerenders
docs(release): document alpha prerelease flowCommit messages are enforced with commitlint through Husky. Changesets still own package versioning.
Prefer recipes over new API.
Before adding a new public option, ask:
- Can the user derive this from
noworelapsedMilliseconds? - Does this introduce formatting, timezone, data fetching, or business logic?
- Does this need to be supported forever?
- Can it be implemented as userland code using schedules and controls?
Do not add countdown/stopwatch/clock mode enums.
Debug logs are allowed because they help diagnose lifecycle issues, but they must stay opt-in.
Rules:
- no logs by default
- no raw timeout handles in public events
- no debug-only behavior that changes timer semantics
- tests must cover debug output
Behavior changes require tests.
Important areas:
- React Strict Mode
- rerender behavior
- unmount cleanup
- async
onEnd - async schedule overlap
- generation guards
- group item add/remove cleanup
A good PR includes:
- clear problem statement
- tests
- implementation
- docs updates when public behavior changes
- notes about any intentional non-goals
Avoid unrelated refactors in behavior PRs.