Easy Pomodoro
Pomodoro, görevler, alışkanlıklar ve istatistikler; hesap açmadan, tamamen cihazında.
Pomodoro zamanlayıcısı, görevler, alışkanlık takibi ve istatistikler bir arada. Hiçbir veri sunucuya gitmiyor, her şey cihazının yerel deposunda kalıyor. Web (Next.js), mobil (Expo / React Native) ve masaüstü (Electron) sürümleri var.

- Durum
- Yayında
- Kategori
- Mobil
- Güncelleme
- 27 Eylül 2026
- Yığın
- Next.jsTypeScriptReact NativeElectron
- Bağlantılar
- Canlı site Kaynak kod
Easy Productivity, pomodoro zamanlayıcısını, görevlerini ve günlük alışkanlıklarını tek ekranda bir araya getiriyor. Varsayılan döngü 25 dakika odak, 5 dakika kısa mola ve 15 dakika uzun mola; her 4 odak seansından sonra uzun mola geliyor. Görevlerine tahmini bir pomodoro sayısı verebilir, alışkanlıklarını seri ve ısı haritasıyla takip edebilirsin; istatistikler ayrı bir ekranda. Arayüz Türkçe ve İngilizce. Web sürümünde bunlara ek olarak 6 farklı arayüz stili, karanlık mod, ses ve bildirimler var. Uygulamayı PWA olarak kurabilirsin, çevrimdışı önbellek de var; verilerini dışa ve içe aktarmak da mümkün.
Hesap açman gerekmiyor; sunucu ya da analitik de yok. Verilerin cihazında kalıyor: web'de localStorage, mobilde AsyncStorage'da. Varsayılan görünüm açık modda, neomorphism (soft UI) tarzında ve mavi-beyaz bir paletle geliyor.
Üç uygulama, tek çekirdek
Depo bir npm workspaces monorepo'su ve içinde üç uygulama var: apps/web Next.js 16, React 19 ve Tailwind 4 ile yazılmış web uygulaması, apps/mobile Expo ile React Native, apps/desktop de bir Electron kabuğu. Web bileşenleri DOM'a bağlı olduğu için onları React Native'de yeniden kullanmadım. Ortak olan kısım zamanlayıcı, alışkanlık ve tarih matematiği: packages/shared içinde platformdan bağımsız TypeScript olarak pomodoro ve alışkanlık mantığı, ayarlar, temalar, tipler ve iki dilin mesajları duruyor.
Masaüstü uygulaması web sürümünü localhost:3000 üzerinden açıyor; web sunucusu çalışmıyorsa başlatma komutu önce onu ayağa kaldırıp hazır olmasını bekliyor. Kabuk için Tauri yerine Electron'u seçtim. Sebebi basit: geliştirme makinemde Rust ve cargo yoktu. Mobil uygulamada zamanlayıcı, görevler, alışkanlıklar, istatistikler ve iki dil var. Ses, bildirim ve veri aktarımı ise yalnızca web'de; mobilde 6 arayüz stilinin yerini palet seçimi alıyor.
Bunlardan ayrı olarak depodaki mobile/ klasöründe Flutter ile yazılmış bir mobil uygulama daha duruyor. Onda zamanlayıcı, alışkanlıklar, geçmiş, görevler ve ayarlar sekmeleri var. Neo, skeuo ve glass yüzey stillerini tek bir karışım olarak tanımladım; tema değişirken aralarında ara değer alınıyor. Fontlar paketin içinde geldiği için ilk açılışta internet gerekmiyor.
Arka planda kaymayan sayaç
Sayaç kalan süreyi bir bitiş zamanından (endTime = Date.now() + süre) hesaplıyor ve bu zamanı durumla birlikte kaydediyor. Uygulamayı yeniden açtığında kalan süre bu zamana bakılarak bulunuyor; süre o arada dolmuşsa faz hemen tamamlanıyor. Bu yüzden sekmeyi ya da uygulamayı arka planda bıraksan da sayaç kaymıyor.
Faz geçişlerini getNextPhase yönetiyor. Bir odak seansı tamamlanınca sayaç artıyor; sayaç uzun mola aralığının katıysa uzun molaya, değilse kısa molaya geçiliyor. Moladan sonra her zaman odağa dönülüyor. Atladığın bir odak seansı pomodoro sayılmıyor, doğrudan kısa molaya geçiyor. Gün anahtarlarını yerel takvime göre üretiyorum; toISOString kullanmadığım için gece yarısına yakın oturumlar yanlış güne düşmüyor. Faz geçişlerini ve yerel tarih hesabını küçük bir self-check.ts dosyası doğruluyor; bir şey bozulursa doğrudan exception fırlatıyor.
Tema değişirken
Web'de tema, <html> üzerindeki CSS değişkenleri ile data-ui-style ve data-theme öznitelikleriyle uygulanıyor. Son seçtiğin tema localStorage'a yazılıyor ve <head> içindeki küçük bir açılış betiği onu ilk boyamadan önce uyguluyor. Böylece sayfayı yenilediğinde varsayılan tema bir anlığına bile görünmüyor.
Stil, mod ve palet runThemeSwitch() ile tek adımda değişiyor. Geçiş süresince öğe animasyonlarını donduruyorum. Bunun sebebi şu: gradyan, iç gölge ve backdrop-filter ara değerlenemiyor, animasyonlar açıkken de ekranda yarım kalmış yüzeyler oluşuyordu. Tarayıcın destekliyorsa View Transitions ile, tıkladığın noktadan yayılan dairesel bir geçiş görüyorsun; prefers-reduced-motion açıksa değişim anında oluyor. Service worker ise yalnızca web'in production sürümünde etkin, Electron'da kapalı.