A simple, mobile-first game clock for Go and chess. Supports Fischer time and Japanese Byo-yomi time controls, with audible byo-yomi announcements and a buzzer when a player loses on time.
The app is a static, single-page Svelte build with no backend server. Place your phone on the table beside the board, set the time control, and start playing.
# 1) Install dependencies
npm install
# 2) Start the dev server
npm run devThen open the URL printed in your terminal (typically http://localhost:5180/).
# Create an optimized static build
npm run build
# Optional: preview the production build locally
npm run previewProduction files are emitted to dist/ and can be hosted on any static hosting service.
- Two time controls
- Fischer: main time + per-move increment.
- Japanese Byo-yomi: main time + N periods of fixed length.
- Several presets per mode (plus full custom configuration).
- Two large clocks; the top clock is rotated 180° so the player on the far side of the board reads it right-side-up.
- Tap your side of the screen to end your turn.
- Pause / resume any time.
- Reset (same settings) or return to configuration.
- Audio
- Spoken "Byo-yomi" when overtime begins.
- Spoken countdown (10 → 1) for the last 10 seconds of each byo-yomi period.
- Loud buzzer when a player loses on time.
- Mute toggle in the control bar.
- Screen Wake Lock keeps the phone awake while the game is running.
- Settings and active games are saved to
localStorage. A game in progress is restored paused, so you can decide whether to resume.
npm install
npm run devThen open the Local URL printed by Vite (e.g. http://localhost:5180/).
Vite is configured with host: true so it is also reachable from a
phone on the same network at the printed Network URL.
npm run buildThe built static site is written to dist/. Upload its contents to any
static host (GitHub Pages, Netlify, Vercel, S3, etc.).
To preview the production build locally:
npm run previewAfter deploying to a URL over https://, install the app from your phone's browser.
- Open your deployed Game Clock URL.
- Tap the browser menu (
⋮) and choose Install app or Add to Home screen. - Confirm install.
- Launch from the Home Screen icon to run without browser trim.
- Open your deployed Game Clock URL in Safari.
- Tap the Share button.
- Choose Add to Home Screen and confirm.
- Launch from the Home Screen icon to run in standalone mode.
Notes:
- Full-screen/standalone behavior applies when launched from the installed/Home Screen icon, not from a normal browser tab.
- If icon or install metadata does not update right away, close the tab and refresh once.
src/
├─ App.svelte - top-level screen switcher
├─ main.js
├─ lib/
│ ├─ components/
│ │ ├─ ConfigScreen.svelte - mode + presets + custom inputs
│ │ ├─ GameClock.svelte - dual clocks + control bar + overlay
│ │ ├─ PlayerClock.svelte - one player's display
│ │ ├─ ControlBar.svelte - settings / reset / pause / mute
│ │ └─ PauseMenu.svelte - overlay for paused / lost-on-time
│ ├─ stores/
│ │ ├─ settings.js - persisted config + presets
│ │ └─ gameState.js - game logic (Fischer & byo-yomi)
│ ├─ utils/
│ │ ├─ timer.js - rAF ticker + time formatting
│ │ ├─ wakeLock.js - Screen Wake Lock helper
│ │ └─ persistence.js - localStorage read/write
│ └─ audio/
│ ├─ voiceAnnouncer.js - Web Speech API
│ └─ sounds.js - Web Audio API (buzzer, chimes, etc.)
└─ styles/
└─ global.css
- iOS/Safari requires a user gesture before audio plays. The Start Game button and the first tap during play prime both the speech synthesizer and the audio context, so subsequent announcements work.
- Time accounting always uses wall-clock deltas, so the timer remains
accurate even when the browser throttles
requestAnimationFramein the background.