Tüm Projeler
PWA & Fullstack Web 2025

foşur.

PWAVanilla JSNode.jsMySQLVercel
0 Uygulama Ekranı
0 API Endpoint
0 Sadakat Kademesi
PWA Telefona Yüklenebilir
Foşur

foşur.

Anadolu Yakası'nda kapıda mobil araç yıkama. Siz bekleyin, biz gelelim.

Site İçi Görüntüler

Proje & Bağlam

Foşur, Anadolu Yakası'nda faaliyet gösterecek mobil araç yıkama hizmeti için sıfırdan tasarlanıp geliştirilen tam yığın bir web uygulaması. Kullanıcı randevu alır, haritada konumunu işaretler; ekip gelir, yıkar, gider.

Tasarım referansı Uber. Çünkü Uber'i herkes biliyor — aynı akış mantığı araç yıkamaya uyarlandı: paket seç, konumu işaretle, ekip gelsin.

"Tek bir HTML dosyası, 15 ekran, tam bir uygulama deneyimi." — Mimari kararın özeti bu.

Neden Tek HTML?

Bu projenin en ilginç teknik kararı buydu. Ama foşur bir PWA — yani telefona kurulabilen, offline çalışabilen bir 'uygulama'. Her sayfa geçişinde yeniden yükleme olmadan ekranlar arasında geçiş yapmak kritik.

Çözüm: tek index.html içinde 15 ekran, CSS ile göster/gizle. Ekranlar arası slide animasyonu — native uygulama hissi. Build adımı yok, 5300 satır temiz HTML/CSS/JS.

15 Ekran, Tek Dosya

s0Hero / Website
s1Paket Seç
s2Araç Bilgisi
s3Konum (Harita)
s4Özet & İletişim
s5Randevu Başarılı
s6Sadakat — Damla
s7Randevu Geçmişi
s8Hesabım
s9Giriş Yap
s10Üye Ol
s11Bildirim Ayarları
s12Yardım & Destek
s13Profil Düzenle
s14Araçlarım

Hizmet Paketleri

Fiyatlar admin panelinden veritabanına güncellenir, siteye otomatik yansır. Araç tipi ek ücreti, isteğe bağlı ekstralar ve ₺50 Stripe kapora.

Hızlı Foşurma
₺199
~20 dakika
Komple Bakım
₺349
~45 dakika
Premium Detay
₺599
~90 dakika

Damla — Sadakat Sistemi

'Pul' demek sıradan gelirdi. 'Damla' — su temalı, akılda kalıcı. Her foşurmada 1 damla. Yeterli biriktir, bir foşurma bedava. Kademe atladıkça gereken damla sayısı düşüyor.

Standart — 8 damla
Gold — 7 damla
Platinum — 6 damla

Referans kodu sistemi de var. Damla verme işlemi admin onayı gerektiriyor — double-award önlemek için appointments tablosunda damla_awarded flag.

Öne Çıkan Özellikler

01

4 Adımlı Randevu Akışı

Paket → Araç → Konum → Özet. Her adım ayrı ekran, slide animasyon geçiş. Progress bar ile ilerleme gösterimi.

02

Leaflet.js Harita Entegrasyonu

Leaflet.js + OpenStreetMap, sıfır maliyet. Geolocation API ile konum, sürüklenebilir pin, reverse geocoding ile adres dönüşümü.

03

Damla Sadakat Sistemi

8 damla ekranı (s6). Dolu yeşil, boş gri. Tier badge, referans kodu. Admin onaylı damla verme — çift verilemez.

04

Admin Paneli (admin.html)

Ayrı admin.html — durum bazlı randevu yönetimi, Damla verme, fiyat güncelleme, bölge yönetimi. is_admin=true ile doğrulama.

Backend & Veritabanı

Vercel serverless Node.js — her endpoint ayrı dosya. 7 iş endpoint + 2 yardımcı (_db.js MySQL pool, _helpers.js). Şifre bcrypt, auth token bazlı.

Bcrypt hash, VAPID push altyapısı (hazır, aktif değil), Stripe kapora endpoint (key girilince devreye girer).

#020e07
#0d0d0d
#282828
#06c167
#048a48
Vanilla JS PWA + Service Worker Node.js Serverless MySQL Vercel Leaflet.js + OSM Stripe (hazır) VAPID Push (hazır) bcrypt JSON-LD Schema Dark / Light Tema Safe Area (iOS)

Teknik Zorluklar

15 Ekran Tek HTML: Performans

⚡ Sorun

15 ekranın tamamı DOM'da aynı anda bulunduğu için sayfa ağırlığı arttı ve initial render yavaşladı. display:none kullanan ekranlar için tarayıcı yine de tüm içeriği parse ediyordu.

✓ Çözüm

Ekranlar display:none yerine visibility:hidden + height:0 + overflow:hidden kombinasyonuyla gizlendi. Bu yöntemde layout hesabı yapılmıyor. Kritik ekranlar (s0-s4) önce yükleniyor, diğerleri lazy-init ediliyor.

iOS Safe Area + Leaflet Harita

⚡ Sorun

iPhone'da alt navigasyon çubuğu Leaflet haritasının zoom kontrollerinin üstüne biniyordu. env(safe-area-inset-bottom) değeri Leaflet'in kendi container'ına uygulanamıyordu.

✓ Çözüm

Leaflet attribution kontrolü CSS ile alt soldan sağa taşındı. Zoom kontrolleri haritanın sağ üstüne alındı. Harita container'ına padding-bottom: calc(env(safe-area-inset-bottom) + 80px) eklendi.

Damla Çift Verilme Race Condition

⚡ Sorun

Admin hızlı çift tıkladığında 'Damla Ver' API'si iki kez tetiklendi ve aynı randevuya çift damla eklendi. Database transaction olmadığında SELECT + UPDATE arasına başka istek giriyordu.

✓ Çözüm

appointments tablosuna damla_awarded boolean sütunu eklendi. API önce damla_awarded=false kontrolü yapıyor, sonra transaction içinde hem damla_awarded=true hem de stamps+1 güncellemesini yapıyor. Çift tıkla ikinci istek engelleniyor.