Wotra — Working Time Tracker
A self-hosted working time tracker with a Go backend and a Svelte PWA frontend. Offline-capable, single-binary deploy.
Features
- Start / Stop time tracking with an optional note.
- Close days: merges all entries (worked_ms = sum of durations, breaks excluded).
- Mark days as holiday, vacation, or sick (auto-credits expected daily hours).
- Close weeks: computes overtime/undertime against a frozen snapshot of your expected hours.
- Settings history: change hours/week with an
effective_from date — past closed weeks are unaffected.
- PWA + offline: works without a network connection; syncs via IndexedDB outbox when back online.
- CSV export: entries, days, weeks.
- Midnight guard: running entries are automatically stopped at 23:59:59 if they cross midnight.
Quick Start
Development
Open http://localhost:5173, go to Settings, enter your token.
Production (single binary)
Configuration (environment variables)
| Variable |
Default |
Description |
AUTH_TOKEN |
required |
Bearer token for API access |
PORT |
8080 |
HTTP port |
DB_PATH |
wotra.db |
SQLite database file path |
TZ |
UTC |
Timezone for day/week key calculation |
API Reference
All API endpoints require Authorization: Bearer <token> except /healthz.
Entries
| Method |
Path |
Description |
| POST |
/api/entries/start |
Start tracking |
| POST |
/api/entries/{id}/stop |
Stop a specific entry |
| GET |
/api/entries?from=&to= |
List entries by date |
| PUT |
/api/entries/{id} |
Edit start/end/note |
| DELETE |
/api/entries/{id} |
Soft-delete an entry |
Days
| Method |
Path |
Description |
| GET |
/api/days?from=&to= |
List closed days |
| POST |
/api/days/{day}/close |
Close a day (merge entries) |
| POST |
/api/days/{day}/mark |
Mark as holiday/vacation/sick |
| DELETE |
/api/days/{day}/close |
Reopen a closed day |
Weeks
| Method |
Path |
Description |
| GET |
/api/weeks?from=&to= |
List closed weeks |
| POST |
/api/weeks/{week}/close |
Close a week (compute overtime) |
| DELETE |
/api/weeks/{week}/close |
Reopen a closed week |
Week key format: YYYY-Www (e.g. 2024-W03).
Settings
| Method |
Path |
Description |
| GET |
/api/settings |
Current effective settings |
| PUT |
/api/settings |
Add a new settings version |
| GET |
/api/settings/history |
All settings history |
Export
| Method |
Path |
Description |
| GET |
/api/export/entries.csv |
Export entries as CSV |
| GET |
/api/export/days.csv |
Export days as CSV |
| GET |
/api/export/weeks.csv |
Export weeks as CSV |
Sync
| Method |
Path |
Description |
| POST |
/api/sync/pull |
Pull changes since a version |
| POST |
/api/sync/push |
Push local changes (advisory) |
Health
| Method |
Path |
Description |
| GET |
/healthz |
Unauthenticated health |
Architecture
See PLAN.md for the full design document.
Development Notes
- Go module:
github.com/wotra/wotra
- SQLite driver:
modernc.org/sqlite (pure Go, no CGO)
- Day boundary: entries must not cross midnight; the server auto-stops any running entry at 23:59:59 local time.
- Settings history:
effective_from lets you change hours/week without rewriting past closed weeks.
- Overtime: stored as a signed
delta_ms on each closed_weeks row. Frozen at close time.