Runarchy Koşu Kulübü Uygulaması: Canlı Harita, SOS, Rozetler

Yazar tarafından hazırlanmış görsel.
20 Kasım 2018, Şişhane. Bir iş arkadaşımın ısrarıyla koşuya gelmişim; onun dışında kimseyi tanımıyorum. O akşam tanıştığım ve kanatlı Runarchy çanta rozetini utanmadan istediğim Kaptan Yasin, yıllar sonra nikâh şahidim oluyor.
Yasin'le 2019'da bir koşu grubu mobil uygulaması yapmayı denemiştik. Birkaç ekran hazırladık. Ben o zamanlar sadece Android geliştiricisiydim; sunucu, veri tabanı, kullanıcı girişi ve şifre sıfırlama sistemleri derken bir kişiye daha ihtiyacımız vardı. O kişi bulunamayınca proje de bir yerde durdu. Salı koşuları, perşembe pist antrenmanları, pazar sabahları yapılan Sunday Shiftler devam etti. Kulübün Instagram hesabı on iki bin takipçiye ulaştı...
mixletics.com ve yazıyı okuduğunuz bilim kurgu blogum devdiscipline.com'u bitirdikten sonra aklıma yeniden o yarım kalan uygulama düştü. Yapay zekâyla çalışırken, 2019'da eksik kalan tarafları artık tek başıma tamamlayabileceğimi görmüştüm. “Ben niye Runarchy'nin mobil uygulamasını yapmıyorum?” diye düşündüm. Bir de Yasin'e yıllar önce verdiğim söz vardı.
Mayıs 2026'da Antigravity ve Gemini'yle uygulama üzerinde yeniden çalışmaya başladım. Supabase, veri tabanını, giriş sistemini ve dosya depolama altyapısını sağlıyordu.
Başlangıçta istediğim şuydu: Haftanın koşu gönderisi açılsın, insanlar katılacaklarını işaretlesin, tempo gruplarını seçsin. Koşuya çıkınca kayıt başlasın; mesafeyi, süreyi ve Runarchy rotalarını görelim. Sonra o koşu profilimizde kalsın, mesafesi de ayakkabının kilometresine eklensin. Yasin de bunları yönetmek için her seferinde bana yazmak zorunda kalmasın.
Claude'a planlar ve analizler yaptırdım. GPT-6 Astra'yla da epey mesai yaptık: KVKK ve sağlık bilgisi dokümanlarını hazırladık, güvenlik incelemeleri yaptık, özellik önerilerini değerlendirdik. Bazen bir özelliği nasıl yapacağımızı, bazen de onu uygulamaya koymanın gerekip gerekmediğini tartışıyorduk.
Gündüz işim olduğu için Runarchy'ye geceleri vakit ayırdım. Sonradan baktım: Beş ayda attığım commitlerin yüzde kırk üçü gece yarısıyla sabah altı arasına denk gelmiş. En yoğun saat 01.00. Daha önce “Ağladım, Güldüm, Çözdüm” yazısında anlattığım çalışma düzenini tanıyanlara bu saat yabancı gelmeyecektir. Ertesi sabah spor yapacağım günlerde dört beş saatlik uykuyla yetindim. Eksik kalan uykuyu öğle aralarında ya da hafta sonları tamamlamaya çalıştım.
Gece “şunu da bitireyim” derken ertesi sabahki kendime pek danışmıyordum.
Yapay zekâyla çalışmanın kendi disiplini var. Projenin kural dosyası zamanla şişti; içine veri tabanı şemasının kopyaları, kod parçaları, eski kararlar doldu ve kırk kilobaytı geçti. Bir Markdown dosyası için bu rakam biraz fazla arkadaşlar. Her oturumda önce bu dosya okunuyordu, yani her işe eski bir ansiklopediyle başlıyordum. Ekimde dosyayı elden geçirip boyutunu dokuz kilobayta indirdim. Artık dosya yalnızca kural tutuyor: şemanın doğru hâli migration dosyalarında, temanın doğru hâli tema dosyasında. Aynı dönemde yüz otuz dosyadaki kod içi açıklama yorumlarını da kaldırdım.
Kod kendini anlatmıyorsa eksik olan yorum değil, fonksiyonun adı.
Bir de kendi oturum kayıtlarımı inceledim. 5 haftada 1000'i aşkın kez elle tip kontrolü çalıştırmışım; iki yüzden fazla kez de sürüm numarasına bakmışım. Aynı şeyi bin kez yapıyorsanız onu bir komuta bağlamanın zamanı gelmiş demektir. Tek komutluk bir sürüm öncesi kontrol yazdım: Tip hatası var mı? Unutulmuş console.log var mı? Türkçe ve İngilizce çeviri anahtarları birebir mi? Sürüm numarası üç dosyada aynı mı? Eksik native paket var mı? Kırmızı varsa sürüm çıkmıyor. İlk TestFlight denemesinde build siyah ekranda çökmüştü; sebebi tam olarak bu listenin son maddesiydi.
Zamanla haritada koşan Runarchy üyelerini görmek, rotadan çıkınca uyarılmak, Be OWL! ile koşu fotoğrafının üstüne verileri, rotayı ve kulübün baykuşlarını koyup paylaşabilmek ve gerektiğinde konum bilgisiyle SOS çağrısı göndermek de eklendi.

Haftanın koşusu detayı ve Be OWL! ile koşu fotoğrafının üstüne veriler ve rota.
SOS'un bir yan etkisi var: Bütün üyelerin telefonları sessizde olsa bile çalıyor. Her şeyi gece yazıyorum ama SOS'u gece test edemiyorum.
Runarchy test grubunda biri:
“SOS'a basarsak ne oluyor?” diye sordu. Bir arkadaş:
“Normalden arayacaksın,” dedi. Öbürü:
“Uygulama içinden arasak ya,” diye ekledi. Ben de
“Yavaşın, arkadaşlar, ben bir kişiyim,” diye cevap verdim.
Test grubundakiler birlikte koştuğum Runarchydaşlarım. Mesafesi yanlış hesaplanan, kaydı yarım kalan insanları şahsen tanıyorum; salı akşamı yine karşılaşacağız. Bir hatayı düzeltip yeni sürümü göndermek işin bir kısmı. Bir de arkadaşına neden koşusunun kaybolduğunu anlatmak var.
Alt çubuk da ayrı bir dert oldu. Yedi düğme: Koşular, Kulüp, Yarışlar, ortada KOŞ, Rotalar, Be OWL!, Profil. Yedinin çok olduğunu biliyorduk ama hiçbirinden vazgeçemedik, kıyamadık bildiğin vallahi bak. Sonra gözleri yorulan üyelerimizin telefon ayarlarından yazı boyutunu büyüttüğünü öğrendik; attıkları ekran görüntüsünde çubuktaki yazılar birbirinin üstüne binmişti. Çözüm, ortadaki KOŞ düğmesini esas alarak çubuğu yeniden çizmek ve uygulama içindeki yazı ölçeğini belli bir sınırın üstüne çıkarmamak oldu. Yedi düğme hâlâ orada; artık okunuyor.

Yedi düğmeli alt çubuk: Rota Detayı ve Koşular ekranları.
Bir yandan da bunları kulüp büyüdüğünde sürdürebilmek gerekiyordu. İlk bildirim sisteminde Yasin bir koşu açınca her üye için ayrı kayıt oluşturuluyordu. Üç yüz kişi varsa aynı duyuruyu üç yüz kez saklıyordum. Bunu tek kayda indirdim; üyelerin yalnızca en son hangi bildirime kadar baktığını tuttum. Zilin üzerindeki sayı ekrana dönünce yenilense de olurdu; koşunun haberi zaten telefon bildirimiyle geliyordu. Fotoğrafları da yüklemeden önce telefonda küçülttüm.
Aynı refleks başka yerlere de yayıldı. Canlı haritada herkes beş saniyede bir kendi konumunu tek satır olarak yazıyor ve tek sorguyla diğerlerinin konumunu okuyor; yüz kişi de koşsa bin kişi de koşsa kişi başına düşen sorgu sayısı değişmiyor. Yük aynı hızla büyüyor, kat kat değil. Koşu duyurularındaki emoji tepkilerini canlı yayından çıkardım; veri tabanının en pahalı işi o yayınları hazırlamakmış ve kimse tepkinin bir saniye geç görünmesini fark etmiyor.
Eski koşuların GPS izleri iki yüz megabaytlık bir bütçeyle arşivleniyor; bütçe dolunca en eski izler haritadan çekiliyor, mesafe ve süre kalıyor. Supabase'in ücretsiz planı bir gün yetmezse sistemi kendi sunucuma taşımanın adımlarını da yazdım, tuzaklarıyla birlikte. Umarım o dosyayı açmam gerekmez.
Sekizinci Kilometrede Görüşürüz
Koşu uygulaması yazmanın en güzel yanı, test etmek için koşmanız gerekmesi. En kötü yanı da bu.
Kendi telefonum Xiaomi Redmi Note 9S. 2020'de tanıtılmış bir model. “Bugün bu cihazda çalışan uygulama her cihazda çalışır,” diyerek kendimi teselli ediyorum.
Sekiz on kilometre koşunca uygulama kapanıyordu. Konum izni açık, pil tasarrufu kapalı; yine de Xiaomi'nin MIUI yazılımı arka plandaki uygulamayı bir noktada sonlandırıyordu. Telefonu cebinizden çıkarıyorsunuz, kayıt gitmiş. Az önce koştuğunuz kırk dakika bacaklarınızda var, ekranda yok.
Bunu ilk kez Beşiktaş'ta yaşadım. Eve daha sekiz kilometre vardı; o sekiz kilometreyi kendi uygulamama söylene söylene koştum.
Telefonda bir ayar değiştirmek beş saniye. O ayarın işe yarayıp yaramadığını görmek sekiz kilometre sürebiliyor.
Telefon ayarlarından uygulamaya istisna tanımak yardımcı olabiliyor ama herkesin o menüleri bulmasını bekleyemezdim. Kapanmaması için elimden gelen tüm iyileştirmeyi yaptıktan sonra, kapanma ihtimalini de hesaba katıp koşuyu yine de korumaya çalıştım. Artık uygulama sekiz saniyede bir o ana kadarki kaydı telefona yazıyor. On dakika içinde yeniden açarsanız devam edebiliyorsunuz; daha geç açarsanız on iki saat içinde yarım kalan koşuyu bulup kaydetmenizi öneriyor.
Uygulamanın kapalı kaldığı sırada ölçemediği mesafe ise bu kayda dâhil değil ne yazık ki.
6.16 Kilometre Koştuk, 12.27 Çıktı
Ekim başında uygulamanın farklı Android cihazlardaki davranışını görebilmek için Runarchy koşu grubumuzdaki Android kullanıcılarından bir test grubu oluşturduk. Birkaç arkadaşımızın koşusu, uygulamaya gerçek mesafenin yaklaşık iki katı olarak kaydedildi. Keşke koşmak gerçekten bu kadar kolay olsaydı.
Android, arka planda biriktirdiği konumları yeniden gönderiyordu. Uygulama da daha önce işlediği noktaları tekrar hesaba katıyordu. Aynı yolu iki kere sayınca kilometre artıyor, tempo güzelleşiyor, arkasından hak edilmemiş rozetler geliyordu.
Konumların zamanına bakarak tekrar gelenleri ayıkladım. Ardından yanlış mesafeleri düzelttim, bu koşulardan kazanılan rozetleri geri aldım ve arkadaşlarımıza ne olduğunu anlattım. Birine fazladan altı kilometre verip sonra geri almak da koşu uygulaması geliştirmenin sosyal tarafıymış.
GPS’in binaların arasında sağa sola sıçraması da mesafeyi olduğundan uzun gösterebiliyor. Bunun için düşük doğruluklu ölçümleri, küçük konum oynamalarını ve aşırı hızlı görünen sıçramaları eleyen kontroller ekledim.
Rozetlerin hiç kazanılmadığı bir dönem de oldu. İnsanlar salı akşamı gelmiş, koşmuş, evlerine dönmüş; fakat kimse koşu kaydı başlatmadığı için uygulama açısından ortada koşu yok. Bir süre “Katıl” düğmesine basmayı yeterli saydım. Bu kez de gelmeyi planlamakla gerçekten koşmak aynı hesaba girdi.
Sistemi üç kez elden geçirdikten sonra lansman için kuralı belirledim: Rozetler uygulamayla canlı kaydedilmiş ve sonradan değiştirilmemiş koşulardan kazanılıyor. Elle mesafe ekleyebilirsiniz ama bu mesafe rozet hesabına girmiyor. Profildeki küçük bir simgenin hangi davranışı ödüllendireceğine karar vermek, o simgeyi ekrana koymaktan uzun sürdü.
2018’de Kaptan’dan utanmadan rozet isteyen bendim. Sonradan iki Runarchy rozeti daha geldi; ikisi de düşüp kayboldu. O ilk rozet hâlâ çantamda duruyor, inanır mısınız? Şimdi yıllar sonra mobil uygulamamızda hangi koşudan hangi rozet kazanılacak diye kural yazıyorum. Rozetlerin arasında bir de Gece Kuşu var. Onu koyarken kendimi düşünmedim desem yalan olur.

Profil ekranındaki rozetler ve kulübün haftalık sıralaması.
Yarış Radarı da Nereden Çıktı?
Temmuzda Yarışlar sekmesini genişletmek istedim. Türkiye'deki yarışları bir araya getiren, Runarchy koşu kulübüne üye olmadan da bakılabilecek bir takvim olsun.

Yarışlar sekmesi (Türkiye'deki yarışların takvimi) ve Rotalar sekmesi.
Yarış verilerini başından beri bir toplayıcı (crawler) çekiyordu. Geliştirme boyunca onun üzerinde çalıştım; farklı sitelerden gelen bilgileri toplama, tekrarları ayıklama ve takvimi güncel tutma işini sürekli iyileştirdim.
Mixletics'te de yarış verilerini çekmeye ihtiyaç duyunca “Bu toplayıcıyı neden kendi sitesi ve veri servisi olan ayrı bir ürüne dönüştürmüyorum?” diye düşündüm. Şu yazıda da ayrıntılarını anlattığım gibi Yarış Radarı böyle doğdu.
İki hafta sonra Runarchy'nin içindeki toplayıcıyı kaldırıp uygulamayı bu servise bağladım. Runarchy'nin takviminde yanlış bilgi görürsem Yarış Radarı'nda düzeltiyorum; böylece aynı veriyi iki ayrı yerde güncel tutmaya çalışmıyorum.
Takvimin ardından yarış sonuçlarına geçtim. Ekim ortasında yüz altmış dokuz yarışın sonuç sayfalarını inceledim; yüz on yedisinde sonuç vardı. Mesele, her yarışın sonucunun hangi zamanlama şirketinin hangi sayfasında olduğunu bulmaktı.
O gece tasarımı iki kez değiştirdim. Saat 23.52'de on dakikada bir çalışan, bütün yarışların sonuçlarını kendi kendine tarayan bir görev yazdım. 01.36'da sildim. Arada şunu fark etmiştim: Kimsenin bakmayacağı bir sonucu her on dakikada bir aramak hem zamanlama şirketlerinin sunucusunu yoruyor hem benim kotamı tüketiyordu. Sonuç ancak biri istediğinde aranacaktı. Yarışın durumu ortak bir önbellekte on beş dakika tutuluyor; aynı yarışa aynı anda yüz kişi baksa da sunucuya tek istek gidiyor. Zamanlayıcı yok, kişi başına yoklama yok.
İnsanlar yarış bittikten sonra göğüs numaralarını hatırlamıyor. Ben de hatırlamıyorum. Sonuca ulaşmak için önce eski fotoğraflarda göğüs numarası bulmak gerekiyorsa işin en can sıkıcı kısmı kullanıcıya kalacaktı.
Ad ve soyada göre aramayı ekledim. Uygulama eşleşen kişileri bulup en fazla beş aday gösteriyor ve “Bu sen misin?” diye soruyor. Sonuçlar ekran açıldığında veya kullanıcı istediğinde getiriliyor; kesinleşmiş bir sonucu tekrar tekrar aramıyoruz.
Bazı zamanlama şirketleri de sunucudan gelen istekleri engelliyor, telefondan gelenleri engellemiyor. Böyle bir yarışta telefon sonuç sayfasını kendisi okuyor, sonucu yalnızca o kişinin kaydına yazıyor ve kimseyle paylaşmıyor.
Federasyonun herkese açık bir API uç noktası ise kimlik numarası ve doğum tarihi döndürüyordu. Türkiye Atletizm Federasyonu'nu hemen aradım ve bu önemli veri açığını kapattık.
Yarış Takvimim ekranının fikri gruptaki bir arkadaştan geldi. Katıldığınız yarışlar bir zaman çizelgesinde sıralanıyor: sıradaki yarış bir start takının altında geri sayımla bekliyor; Gelecekte koşulacak yarışlar çengelli iğneli, yırtma çizgili göğüs numarası kartları olarak diziliyor; iptal edilen yarışın üstünde kırmızı İPTAL damgası duruyor. Uygulamada en çok sevdiğim ekran bu oldu; fikir benim değildi.

Yarış Takvimim ekranı ve yeni koşulan İstanbul Maratonu'nun detayı: kulübün en hızlıları ve katılımcılar.
“Sık Sık Koşuyorum” Yazabilmek
Kulüp sohbetine bir kelime filtresi ve yapay zekâ moderasyonu ekledim.

Canlı koşu ekranı: harita üstünde kulüp sohbeti; sağda yarış modunda canlı koşu.
“Bugün kendimi öldürdüm, harika tempo.”
Denediğim model bu cümleye kendine zarar kategorisinde 0,77 puan veriyordu. Modelin genel kararını olduğu gibi uygulamak yerine kategorileri ayrı değerlendirdim. Şiddet için eşik belirledim; kendine zarar skorunu tek başına mesajı reddetmek için kullanmadım.
Yazımı biraz değiştirilmiş küfürleri yakalamak için bazı harfleri eşdeğer saymak gerekiyor. Fakat “ı” ile “i”yi de aynı kabul edince “sık sık koşuyorum” ifadesi filtreye takılabiliyordu. Koşu kulübü uygulamasında insanların bunu söyleyebilmesine öncelik verdim.
Runarchy'yi Yayımlamaya Doğru
Mağaza hazırlığında konum izni metinlerinden hesap silmeye kadar birçok şeyi elden geçirdim.
Birkaç şey de sonraya kaldı. Strava ve Garmin bağlantıları yok. HealthKit ve Health Connect ilerisi için listede.
App Store, 1.0.0 sürümünü ilk gönderimde onayladı. Google Play tarafında ise bireysel hesabımla yaptığım başvuruda on iki testçinin on dört gün boyunca kapalı testte yer alması gerekiyordu. Kulüpten arkadaşlara bu kez koşu duyurusu yerine test bağlantısı gönderdim.
Mağaza ekran görüntüleri için telefonun saatini sabitleyen demo modunu açmıştım. Kapatmayı unutunca saat bir süre 08.16'da kaldı. Koşu uygulaması yazan birinin telefonunda saatin durması, ironi olarak bile fazla.
Runarchy'den Beş Aydan Kalanlar
Butonu gizlemek kullanıcı deneyimidir, güvenlik değil. Yasin'in yönetim paneline giden buton yalnızca ona görünüyor; ama asıl koruma veri tabanındaki satır bazlı izinler. Okuma herkese açık, yazma yalnızca yöneticiye. Butonu bir şekilde bulsanız da bir şey yapamazsınız.
Bir özelliğin maliyetini bir kişi için değil, bütün üyeler için hesaplayın. Her üyeye ayrı bildirim kaydı yazmak üç yüz kişide fark edilmiyor, üç bin kişide bütçeyi bitiriyor. Üç yüz kişiye göre yazılan kod kulüp büyüyünce yeniden yazılıyor; ilk seferde doğru yazmak daha ucuz. Üniversitede bir hocamın dediği gibi: " Daha akıllı bir yazılımla donanım maliyetini çok azaltabilirsiniz. "
Simülatörde her şey çalışıyor. Rozetlerin hiç tetiklenmemesi, mesafenin ikiye katlanması, sonuçların bulunamaması, uygulamanın sekizinci kilometrede kapanması… Bunların hiçbirini simülatör göstermedi. Hepsi gerçek koşularda, gerçek telefonlarda, gerçek insanlarla ortaya çıktı.
Koşu uygulaması yazıyorsanız koşacaksınız.
Bu yazıyı hazırlarken lansman için ekibin tanıtım videosunu bekliyorduk. App Store hazırlığında yaptığım değişiklikleri de ayrı bir yazıda anlattım. Üç ay sonra da uygulamayı kaç kişinin düzenli kullandığına, koşuya “Katıl” diyenlerin kaçının kayıt açtığına ve hangi özelliklerin kullanıldığına bakmak istiyorum.
Benim Redmi de hâlâ görevde.
Salı akşamı görüşürüz.
Sıkça Sorulan Sorular
▸Runarchy uygulaması nasıl ortaya çıktı?
Runarchy, 2018'de Şişhane'de başlayan bir koşu kulübü deneyiminden doğdu. Geliştirici, o gece tanıştığı kaptan Yasin ile yıllar sonra uygulamayı hayata geçirdi. Fikrin temeli 2019'a dayanıyor ama proje çok daha sonra tamamlandı.
▸Uygulamayı tek kişi mi geliştirdi?
Evet, uygulama tek bir geliştirici tarafından yazıldı. 2019'daki ilk denemede sunucu, veritabanı ve kimlik doğrulama sistemleri için ek birine ihtiyaç duyulmuştu; ancak sonraki süreçte bu engeller aşıldı.
▸Geliştirme süreci ne kadar sürdü?
Yazıda beş aylık bir geliştirme sürecinden söz ediliyor. Bu süreç boyunca kod çoğunlukla geceleri yazıldı ve gerçek kullanıcı sorunları rehberlik etti.
▸Yapay zekâ bu uygulamanın geliştirilmesinde nasıl kullanıldı?
Geliştirme sürecinde yapay zekâ destekli kararlar alındığından bahsediliyor. Ancak yazıda bu kullanımın teknik detayları değil, genel etkisi ön plana çıkarılıyor.
▸Runarchy uygulamasında hangi özellikler var?
Yazıdan anlaşıldığı kadarıyla uygulama koşu takibi yapıyor ve bir Yarış Radarı özelliği içeriyor. Kullanıcıların koşu sıklığını kaydedebildiği bir yapı da mevcut.
▸Yarış Radarı özelliği nedir?
Yarış Radarı, geliştirme süreci içinde ortaya çıkan bir yan özellik olarak anılıyor. Yazıda bu özelliğin beklenmedik bir şekilde geliştiğine dair bir ima var; detayları ayrıca ele alınmış.
▸İlk mobil uygulama denemesi neden tamamlanamadı?
2019'daki ilk denemede yalnızca birkaç ekran hazırlanabildi. Sunucu, veritabanı, giriş ve şifre sıfırlama sistemleri gibi altyapı ihtiyaçları tek başına karşılanamadı ve projeye devam edilemedi.
▸Uygulama yayımlandı mı?
Yazının başlıklarından biri 'Yayımlamaya doğru' olduğundan sürecin yayım aşamasına geldiği anlaşılıyor. Ancak yazı bu noktada sürecin içinden anlatıyor; kesin yayın tarihi belirtilmiyor.


