A developer-focused Pomodoro timer Chrome extension with Google account cloud sync.
- Pomodoro Timer β 25/5/15 focus/break cycles, fully customizable
- Google Cloud Sync β One-click Gmail login, data stored in your private Google Drive
- Statistics β Daily/weekly/monthly stats, GitHub-style heatmap
- Achievements β Unlock milestones as you build focus streaks
- Keyboard Shortcuts β Space (start/pause), S (skip), R (reset)
- Dark Theme β Easy on the eyes during long coding sessions
- Offline-First β Works fully offline, syncs when connected
- Sound Effects β Chimes on session complete (Web Audio API, no files)
- Onboarding β Guided first-time experience
npm install
npm run build- Open
chrome://extensions/ - Enable Developer mode
- Click Load unpacked β select the
dist/folder
- Go to Google Cloud Console
- Create a new project
- Enable Google Drive API (APIs & Services β Library)
- Create OAuth 2.0 credential (APIs & Services β Credentials)
- Application type: Chrome Extension
- Application ID: your extension ID (visible in
chrome://extensions/)
- Copy the Client ID into
src/manifest.jsonβoauth2.client_id - Rebuild:
npm run build
src/
βββ background/ # Service Worker (alarm-based timer)
βββ popup/ # React 18 UI
β βββ components/ # Timer, Stats, Settings, Heatmap, etc.
β βββ hooks/ # useTimer β bridge to background
βββ lib/ # Core logic (no side-effects)
β βββ timer-engine.ts # Pure state machine
β βββ storage.ts # chrome.storage wrapper
β βββ google-auth.ts # OAuth via chrome.identity
β βββ google-drive-sync.ts # Drive AppData sync
β βββ sounds.ts # Web Audio API tones
β βββ notifications.ts # Chrome notifications
βββ stores/ # Zustand state management
βββ types/ # TypeScript definitions
βββ styles/ # Tailwind CSS
| Decision | Choice | Why |
|---|---|---|
| Build | Vite + CRXJS | HMR, Manifest V3 native |
| UI | React 18 + Tailwind | Component reuse, fast styling |
| State | Zustand | Lightweight, storage persistence |
| Timer | chrome.alarms |
Survives Service Worker termination |
| Sync | Google Drive AppData | Hidden folder, user-only access |
| Auth | chrome.identity |
Native Chrome OAuth, no redirects |
Chrome MV3 Service Workers are terminated after ~30s of inactivity. This extension uses chrome.alarms for the tick mechanism instead of setInterval, ensuring the timer survives SW restarts. The timer state is persisted to chrome.storage.local on every tick.
npx vitest run # Run all tests
npx vitest run --ui # Interactive UI54 unit tests covering:
- Timer engine: all state transitions, edge cases, cycle logic
- Storage: read/write, concurrent safety, default fallbacks
- Pure functions:
formatTime,getProgress
- Create a ZIP of the
dist/folder - Go to Chrome Web Store Developer Dashboard
- Pay the one-time $5 registration fee
- Upload the ZIP, fill in store listing details
- Submit for review (typically 1-3 business days)
- All data stored locally in
chrome.storage.local - Google token managed by
chrome.identity(never exposed to the extension) - Sync uses your private Google Drive AppData folder
- No analytics, no tracking, no third-party servers
MIT