A desktop Pomodoro timer with a kanban board and focus ambience. Built with Wails (Go + web UI), Svelte 5, Tailwind CSS v4, and DaisyUI.
Author: Ankur Singh
- Pomodoro timer — Focus, short break, and long break sessions with a glass countdown UI
- Kanban board — TODO / Doing / Done columns with drag-and-drop; start a focus session from a task
- Focus ambience — Mix nature/ambient loops with per-track volume, or open a Spotify playlist
- Session history — Completed sessions stored locally
- Themes — DaisyUI themes from Settings
- Floating dock — macOS-style bottom nav, with optional auto-hide on the bottom edge
- Keyboard power-user mode — Vim-style chords (
gthent/b/s…), Space to start/pause,?for the shortcut cheat sheet - Native menus — Desktop application menu (File / Timer / View / Help, plus macOS App / Edit / Window)
- Dock menu (macOS) — Right-click the Dock icon for Show Window, timer controls, and views
- Status bar icon — Optional menu-bar icon with an app menu (Show/Hide, timer, quit); toggle in Settings
Settings, history, and tasks persist in a local SQLite database at:
{UserConfigDir}/zendoro/zendoro.db
| Layer | Tech |
|---|---|
| Desktop | Wails v2 |
| Backend | Go, modernc.org/sqlite |
| Frontend | Svelte 5, TypeScript, Vite |
| UI | Tailwind CSS v4, DaisyUI 5 |
go install github.com/wailsapp/wails/v2/cmd/wails@latestFrom the project root:
wails devThis starts the Go app and the Vite frontend with hot reload.
Frontend-only (Vite):
cd frontend
npm install
npm run devUseful frontend scripts:
npm run check # svelte-check + tsc
npm run lint # Biome
npm run format # PrettierPress ? (or Help → Keyboard Shortcuts) to open the full, scrollable shortcut list.
Highlights:
| Keys | Action |
|---|---|
Space |
Start / Pause |
h / l or 1 / 2 |
Timer / Board |
g then t / b / s / o / h |
Go to Timer / Board / Settings / Sound / History |
r / s |
Reset / Skip |
m / x |
Mark task done / unlink |
, |
Toggle settings |
d |
Toggle dock always-visible |
Esc |
Close overlays |
On macOS, right-click the Dock icon or the menu-bar status icon for the same timer and navigation actions.
Backend (Go):
go test ./...Frontend (Vitest):
cd frontend
npm testWatch mode:
cd frontend
npm run test:watchwails buildThe binary is written under build/bin/.
.
├── app.go / db.go / tasks.go # Wails app, SQLite, board APIs
├── main.go
├── wails.json
└── frontend/
├── src/
│ ├── App.svelte # Root shell
│ ├── components/ # UI components (@components/*)
│ ├── lib/ # Stores & helpers (@lib/*)
│ └── assets/audio/ # Ambient loops
└── wailsjs/ # Generated Go bindings
Import aliases (Vite + TypeScript):
import BottomNav from '@components/BottomNav.svelte';
import { timerState } from '@lib/timerStore';Contributions are welcome. A typical flow:
- Fork the repo: ankur700/zendoro
- Create a branch from
main(git checkout -b feature/your-change) - Make your changes and verify locally (
wails dev,npm run check/npm run lintinfrontend/) - Commit with a clear message
- Open a pull request against
mainand describe what changed and why
Please keep PRs focused. For larger ideas, open an issue first so we can align on approach.
Use GitHub Issues on this repository:
https://github.com/ankur700/zendoro/issues/new
When filing a bug, include:
- OS and app version (or commit)
- Steps to reproduce
- Expected vs actual behavior
- Screenshots or logs if useful
For feature requests, describe the problem you want solved and any preferred approach.
Copyright (C) 2026 Ankur Singh
This project is licensed under the GNU General Public License v3.0.
You may copy, distribute, and modify the software under the terms of the GPL-3.0. See the LICENSE file for the full text.