A dead simple time tracker that keeps everything in local storage. Next.js, no accounts and no server.
handcodedlocalstoragenextjsreactself-hostedserverlesstime-trackingtimer
1> **Archived.** This project is no longer in use and no longer maintained. Last updated July 2026.
2
3<p align="center">
4 <img src="https://raw.githubusercontent.com/overshard/timelite-nextjs/master/public/static/logo.png"
5 width="200"
6 height="200"
7 alt="Timelite Logo" />
8</p>
9
10# Timelite
11
12Why is it 5 AM? Isn't there something simple I can use to track what I'm doing
13with all this time?
14
15
16## Why?
17
18I want to casually track the time I spend on things without any overhead of
19signing into a service or even being online. All data stays in your browser
20(IndexedDB via localForage), there is no backend, and nothing is tracked or
21sent anywhere. Once the page has loaded it keeps working offline.
22
23Timelite has been a great companion alongside more aggressive team-management
24software that sometimes doesn't let me swap between projects quickly and track
25time easily. I tend to hop from project to project and task to task regularly.
26Larger solutions carry a lot of overhead for basic time tracking. I track my
27time here and then enter it into those tools at the end of the day, in
28increments that make more sense.
29
30For an overview of how to get this project running and why it's useful, check
31out the DB Tech video on it here: https://www.youtube.com/watch?v=woG6qOmxlOA
32
33
34## Privacy and offline
35
36There is no account, no server, and no network call for your data. Every entry
37lives in your browser's IndexedDB. That also means your data is tied to that
38browser on that device: clearing site data wipes it, so use the JSON export if
39you want a backup or want to move between machines. Timelite is not installable
40as a PWA; the service worker was removed, but the app still functions offline
41because the data never leaves the browser.
42
43
44## Features
45
46- **Timer** with pause/resume and `#hashtag` note support
47- **Log** with per-day grouping, tag filtering, inline edit, manual entry,
48 and import/export (CSV, JSON, Markdown)
49- **Summary** with charts for hours-per-tag and hours-per-day
50- **Keyboard shortcuts**, press `?` anywhere to see the full map
51- **Localized** in English, Japanese, and Polish (language picker on the
52 About page)
53- **Local-only and offline-capable**, all data stays in IndexedDB and never
54 leaves the browser
55
56
57## Tech stack
58
59- Next.js (Pages Router) and React, plain JavaScript (no TypeScript)
60- Bun as the runtime and package manager
61- localForage for IndexedDB persistence
62- CSS Modules with a single global theme in `styles/globals.css`
63- chart.js, react-hook-form, react-hotkeys, react-toastify,
64 react-transition-group, react-csv, and react-localization
65
66All app state (timer, log, language, edit mode, and so on) lives in one React
67Context plus reducer in `components/context.js` and is saved to IndexedDB on
68every change, so there is no save button.
69
70
71## Clone
72
73Whichever way you run Timelite, start by grabbing the repo:
74
75 git clone https://github.com/overshard/timelite-nextjs.git
76
77
78## Development
79
80You will need `bun` installed. If you don't have it yet, see https://bun.sh/
81for installation instructions. Then run:
82
83 bun install
84 bun start
85
86This serves Timelite on port 8000, reachable at `http://localhost:8000`. To
87produce a production build, run `bun run next:build`.
88
89
90## Production
91
92Install Docker and docker-compose, then run the container on any server.
93`restart: unless-stopped` is configured so the container comes back up after
94restarts or crashes. Appending `-d` runs it detached:
95
96 docker-compose up -d
97
98
99## Ports
100
101To change which ports things run on, update the scripts in `package.json`. If
102you use Docker, also update `docker-compose.yml` to publish the new port.
103
104
105## Troubleshooting
106
107Some changes won't automatically trigger a Docker rebuild. To force one:
108
109 docker-compose up -d --build
110
111Here `up` starts the server, `--build` rebuilds the container, and `-d` runs it
112detached so you can set it and forget it.
113
114If you previously used an older version and now see stale service-worker or
115filesystem errors in the console, the app now unregisters any old service
116workers on load. A hard refresh (Ctrl+Shift+R) clears them after one visit.