Commit Graph

88 Commits

Author SHA1 Message Date
bilalgursen
c60e3ab409 fix(tasarim): şehir haritası kartı arka plan gibi kaplar, kenarlar erir; pikseller azaldı
All checks were successful
Deploy / deploy (push) Successful in 4m34s
- Izgara 72 → 56 sütun, serpinti kaldırıldı (Bilal: "piksel detaylarını azalt").
- Harita `doldur` (slice) ile SehirYuzeyi kartını kaplar, metin üstünde; iki
  katlı mask ile hiçbir kenarda kesik kare kalmaz (Bilal: "canvas net bir
  şekilde kesiliyor"). Telefonda altta, lg'de sağ yarıda belirir.
- Yakınlaşma kutusu kabın oranında kurulur, il `odakHiza` ile kabın istenen
  noktasına gelir (şehir sayfası: lg sağ orta, telefon alt orta; konum kartı orta).
- usePixelHeat meet/slice + ortalama ofsetini hesaba katar.
- Üniversite konum kartı: kartı doldurur, radyal erime.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 15:10:44 +03:00
bilalgursen
eefac56659 feat(tasarim): şehir sayfasına hero dilinde piksel harita; üniversite konum kartı da aynı harita
All checks were successful
Deploy / deploy (push) Successful in 4m39s
- scripts/il-izgara-uret.ts → src/lib/il-izgara-verisi.ts: 81 il ve 7 ülke
  kontürü hero'nun dot-matrix ızgarasına (72×31) rasterize; küçük iller 2×2 garanti.
- SehirPikselHaritasi: iri kareler, altı opaklık, kıyı serpintisi, usePixelHeat
  ısı fırçası; bulunulan il iri turuncu karelerle sırayla belirir (kt-piksel-belir)
  ve nabız atar; KKTC/yurt dışında şehir merkezinde 2×2 iri kare.
- Şehir sayfası başlığı beyaz piksel dokulu yüzeyde (SehirYuzeyi), harita sağda/altta.
- UniversiteKonumHaritasi düz SVG yerine aynı piksel haritayı kullanır.
- DESIGN.md §4.12/§4.17/§10.8 güncellendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 14:56:11 +03:00
bilalgursen
259534fa9c feat(katalog+tasarim): şehir adları her yerde link; piksel yüzeylere beyaz ton
- ilSayfaHref: üniversite sayfası il hapı, /universiteler listesi, bölüm /
  sonuç / listem / tadımlık satırlarındaki il metası şehir sayfasına gider.
- Şehir kümeleri tüm (üniversite, il) çiftlerinden: DB'deki her il değerinin
  sayfası var (ODTÜ Ankara + KKTC); dev'de eski globalThis önbelleğine dayanıklı.
- PikselZemin ton="acik", CtaBandi/CtaSiraForm ton="beyaz": /universiteler
  altı ve /meraklisina kapanışı beyaz, diğer bantlar mavi (dönüşümlü).
- ilUlkeHaritasi: il değerinden ülke haritası + şehir konumu.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 14:56:11 +03:00
bilalgursen
d8a28b7c3a feat(katalog): şehre göre üniversiteler — /universiteler/[il] sayfaları ve şehir çipleri
- Veri: getAllIller/getIlBySlug (üniversite en çok programının olduğu ile
  sayılır; ili boş olan hiçbir şehre girmez; tireli yurt dışı adlar baş harfli).
- /universiteler: "Şehre göre" çip satırı (2+ üniversiteli 28 şehir) +
  "Tüm şehirler" A–Z üç sütunlu liste (#tum-sehirler).
- /universiteler/[il]: 92 statik şehir sayfası — katalog detay düzeni, il ve
  üniversite sayısı hapları, kompakt sıra satırı, devlet/vakıf/KKTC-yurt dışı
  öbekleri, diğer şehir çipleri, CTA bandı; metadata + breadcrumb JSON-LD.
- SehirCipleri: sihirbaz il çipiyle aynı kalıp, aktif şehir mavi dolu.
- Sitemap'e şehir sayfaları eklendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 14:19:09 +03:00
bilalgursen
b11c2c9d45 fix(icerik+metin): 24 Eyl raporunun "bu hafta" işleri — yanlış sayı, vaat cümleleri, üç kural hatası, meslek lisesi ek puanı, sohbette kriz kuralı
All checks were successful
Deploy / deploy (push) Successful in 4m41s
Site metni (rapor 31 §4.3):
- "23.000+ lisans programı" → DB sayımıyla "21.000+ lisans ve önlisans"
  (12.239 + 9.254); sayı tek kaynaktan (veri-kapsami.ts).
- Hero "48 saatlik panikle seçme" → "Tercih listeni gerçek veriyle kur,
  panikle değil"; "Yapay zekâ veriyi tarasın" → resmî veri taransın, YZ
  yalnızca havuzdan seçer; "boşta kalmanın en yaygın sebebi" ve "ihtimalini
  en aza indiririz" iddiaları kaldırıldı; paket sayfasında "insan danışmanın
  işini / aynı işi" dili bırakıldı.

Rehber (rapor 32 §4, 06, 07, 12):
- yerlesemedim: "ekte tabanlar gevşer" hatası düzeltildi (dolu programda
  eşik ilk turun en küçük puanı, Ek Yerleştirme Kılavuzu 1.2); ek listeye
  yerleşince OBP'nin yarıya indiği uyarısı ve kaynaklar eklendi.
- kyk-burs-mu-kredi-mi: "bir öğretim yılı kaybı" maddesi yorumsuz, "KYGM'ye
  sor"; kısmi zamanlı çalışma (2547 md.46), kamu/özel burs ayrımı ve TEV'in
  2026 duyurusu eklendi.
- yatay-gecis-cap-yandal: şemada Ek Madde-1 ve ÇAP kutuları yeşilden sarıya
  (hak ≠ kabul); ÇAP 70 + ilk %20, yandal 65 eşikleri; kontenjan %30/90;
  28 Şubat 2026 "baraj 90" yalnızca açık/uzaktan → örgün; kaynaklar eklendi.
- obp: meslek lisesi ek puanı bölümü (OBP × 0,06, Tablo 6C, lisansta yok,
  yarıya inme, sınavsız geçiş yok). ozel-kosullu: "sınavsız" ifadesi
  M.T.O.K. ve ek puanla düzeltildi.

Danışman sohbeti (rapor 06, 40 §3.2): umutsuzluk / kendine zarar dilinde
tercih konusunu bırakıp yardım almaya yönlendiren güvenlik kuralı; bu dil
artık "tercih dışı" diye reddedilmiyor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 12:50:51 +03:00
bilalgursen
71e6389131 feat(tasarim): funnel CTA'ları arama kartı dilinde, 24'lük piksel liste kreatifi
- PikselCtaYuzeyi: koyu slate-950 yüzey, yazılıp silinen satırlar, tek
  turuncu CTA (arama penceresindeki kartın dili); ana sayfa kapanışı ve
  /sonuc'taki iki panelde köşeye kümelenen PixelField'in yerine
- PikselListe: 24 kare = 24 tercih; kendini kurar (5 hayal · 13 dengeli ·
  6 güvenli), imlece tepki verir, CTA'ya gelince tamamı dolar, dokunmada
  nabız; hareketi azalt'ta durağan; renk hep metinle
- Liste çekmecesi: ilerleme çubuğunun yerinde öğrencinin kendi listesi
  pikselde (her kare o tercihin riski); başlık yan yana dizildi, liste
  alanı 150 → 234 px (375 px ölçümü)
- Funnel metinleri src/lib/funnel-metinleri.ts'e taşındı

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 02:12:45 +03:00
bilalgursen
5df0af0d38 feat(katalog): YÖK İstatistik öğrenci/öğretim üyesi verisi ve Türkiye sıralaması sayfası
- src/lib/yok-istatistik.ts (scripts/yok-istatistik-uret.py ile üretilir):
  üniversite başına örgün öğrenci ve öğretim üyesi, öğrenci/üye oranı ve
  Türkiye medyanı; katalog detayına `istatistik` alanı
- /universite-siralamasi: URAP Türkiye sıralaması sayfası (URAP logosu ve
  zorunlu urapcenter.org atfıyla), sitemap'e eklendi
2026-09-24 00:01:41 +03:00
bilalgursen
e8434dc054 feat(universite): tür, ızgaraya değil H1'in altındaki kimlik çipine döndü
Izgara 5 karta çıkamıyor: lg:grid-cols-[1fr_1fr_1.35fr] + lg:grid-rows-2
şablonunda harita 3. sütunu iki satır kaplıyor, kartlara tam 4 hücre kalıyor.
Tür zaten bir metrik değil kategori; sitenin geri kalanında (program tablosu,
rapor listesi, tadımlık, bölüm listesi) başlığın altında çip olarak yaşıyor,
detay sayfası bunu taşımayan tek yüzeydi.

- Tür çipi H1'in altına girdi; sınıf seti program-tablosu.tsx:329-333'ten
  birebir kopya (yeni varyant yok). Sayfalama sayfalarında da yazar.
- URAP'ı olmayan 31 sayfada ızgaranın 4. hücresi "Tür" yerine "Toplam
  kontenjan" oldu; toplam kontenjanı 0 olan üniversite yok, o hücrede "—"
  çıkmıyor.
- UNITUR_ETIKET bileşenin içinden src/lib/unitur.ts'e çıktı (DILIM_ETIKET'in
  lib/risk.ts'te durması gibi tek kaynak) ve bölüm listesi rozetleri de buna
  bağlandı: "Kktc" → "KKTC", "Vakıf Myo" → "Vakıf MYO".
- Özet cümledeki "…, devlet üniversitesi, …" telafisi kalıyor: tür bir kez
  taranabilir çip, bir kez okunabilir cümle olarak geçiyor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:14:54 +03:00
bilalgursen
493267122f feat(universite): "Tür" kartının yerine URAP Türkiye sırası
/universite/[slug] metrik ızgarasında takas: URAP listesinde olan
üniversitede "Tür" kartının yerini "URAP TÜRKİYE · 18 / 198 ·
2025-2026" alır, olmayan 31 kurumda "Tür" yerinde kalır. Kart sayısı
4'te kalıyor, lg ızgara şablonu değişmiyor, yeni bileşen yok, hiçbir
sayfada "—" ya da delik yok. Payda kartın içinde: "18." tek başına
yanıltır.

Tablonun altına AYRI ikinci kaynak satırı eklendi; VeriKaynagi
kullanılmadı ve kopyalanmadı, çünkü o satır YÖK Atlas'ın yerleştirme
yılına ve son güncelleme tarihine bağlı — URAP'ın dönemi başka.
Satırda metodoloji uyarısı da var: URAP akademik yayın ve araştırma
performansını ölçer, eğitim kalitesini ya da iş bulma oranını ölçmez.
URAP listesinde olmayan üniversitede eksiklik gizlenmiyor, nedeni tek
cümleyle yazılıyor (KKTC/yurt dışı ile MYO/yeni için ayrı cümle).

URAP'ın yayımlama izni "urapcenter.org adresine aktif bağlantı/atıf
vermek" şartına bağlıdır. Kaynak satırındaki bağlantı bu yüzden gerçek
bir <a href>: adres URAP_KAYNAK_URL sabitinden, target="_blank",
rel="noopener", nofollow YOK. Sıranın göründüğü ekran ile atıfın
göründüğü ekran aynı sayfadır; URAP sayısı yalnız ilk sayfada
gösterildiği için kaynak satırı da yalnız ilk sayfada çiziliyor.

Renk yok, rozet yok; URAP risk dili değildir. /universiteler hub'ında
URAP'a göre sıralama/filtre eklenmedi. URAP 24'lük listeye, /sonuc
tablosuna ve LLM prompt'una girmiyor — dokunulan dosya kümesi bunu
zaten dışlıyor.

veri-kalite.ts'e 5 URAP kontrolü (dosyanın en sonunda, tek satırlık
çağrıyla): (1) her URAP slug'ı bir üniversite sayfasına bağlı —
eşleşmeyen sessizce düşmüyor, adıyla listeleniyor; (2) kayıt sayısı =
URAP_TOPLAM; (3) sıralar 1..N tekrarsız ve boşluksuz; (4) puanlar
sıraya göre azalan; (5) kapsama boşluğu — URAP dışında kalan 150+
programlı bir Türkiye üniversitesi varsa UYARI (ad değişikliği
işareti). Beşi de geçiyor, boşluk 31 kurum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 00:21:36 +03:00
bilalgursen
68cb69e458 feat(universite): URAP Türkiye 2025-2026 sıralaması veri sabiti
198 üniversitenin genel sıralaması, /universite/[slug] sayfa slug'ına
anahtarlanmış tek seferlik sabit (uni-koordinatlar.ts deseni). Yeni DB
dosyası, tablo, göç, cron ya da çekme betiği yok: 198 satır × 2 alan
için SQLite'ın hiçbir faydası olmazdı.

Eşleşme 198/198; URAP'ın yazımı bizim DB yazımımızla birebir aynı,
takma ad tablosu gerekmedi. Sıralar 1..198 kesintisiz ve tekrarsız,
puanlar sıraya göre azalan (veri-kalite kontrolleriyle doğrulanıyor).

URAP'ın yayımlama izni "urapcenter.org adresine aktif bağlantı/atıf
vermek" şartına bağlıdır: URAP sayısının göründüğü her yüzeyde, aynı
ekranda, URAP_KAYNAK_URL'ye çıkan gerçek bir <a href> (rel="noopener",
yeni sekme, nofollow YOK) bulunmak zorundadır. Link konulamayan bir
yüzeyde (ör. OG görseli) URAP sayısı hiç gösterilmez. Şart dosyanın
başındaki yorumda da yazılıdır.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 00:21:20 +03:00
bilalgursen
9bd448bd16 fix(kredi): kullanıcı başına üretim kilidi — çifte harcama kapanır
All checks were successful
Deploy / deploy (push) Successful in 10m52s
credit_ledger.ref_id benzersizliği yalnız AYNI denemenin tekrarını koruyordu
(ağda kaybolan cevap → aynı requestId ile retry). requestId istemcide her
mount'ta yeniden üretildiği için "aynı kullanıcı üretimi iki kez başlattı"
durumu hiç yakalanmıyordu: üretim sürerken (20-60 sn) ikinci sekmede açılan
/listem?uret=1 ya da geri→ileri ikinci bir ListeUretici monte edip 3 krediyi
ikinci kez yakıyordu. Karşılığında tek rapor çıkıyordu, çünkü reports.user_id
benzersiz ve ikinci üretim birincinin üstüne yazıyor. Bakiyesi yetmeyen
deneme kullanıcısı ise akışın ortasında "kredi yetersiz" ekranı görüyordu.

- report_locks (user_id birincil anahtar): ikinci INSERT benzersizlik
  ihlaliyle düşer, bu da "üretim sürüyor" demektir. Kilit kredi
  harcamasından ÖNCE alınır, finally'de bırakılır.
- Bayat kilit (süreç OOM'la öldü, deploy) 180 sn sonra devralınabilir;
  devir koşullu UPDATE olduğu için iki eşzamanlı devralmadan yalnız biri
  kazanır. Salım requestId koşullu: geç uyanan eski sahip devralanın
  kilidini silemez.
- Yeni SURUYOR kodu: istemci bunu "hata" sayıp taze requestId ile yeniden
  denerse çifte harcama kapısı yeniden açılırdı. Ekranda "Tekrar dene"
  bilerek yok; kullanıcı listeye yönlendiriliyor, kredi harcanmadı.
- DUPLICATE dalının "İstek tekrarlandı" HATA'sı da SURUYOR'a çevrildi
  (BACKLOG #1'deki ikinci çifte harcama yolu). Revizyon dalı değişmedi.

BACKLOG #1 · güvenlik denetimi G5

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:54:21 +03:00
bilalgursen
84fc88e230 merge(icerik/sezon-celiskisi): [Bilal] content(bant): sezon-dışı bant metni — B alternatifi
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:38:36 +03:00
bilalgursen
4034f03a8b [Bilal] content(bant): sezon-dışı bant metni — B alternatifi
Yalnız `BANT_METNI["takvim-belirsiz"]` değişir. İki seçenek yan yana:

A (dalda duran, ana commit'te):
  "2027 tercihine hazırlık · 2026 yerleştirme verisi yüklü"
  Kısa, bant şeridine tek satırda sığar; ne beklendiğini söylemez.

B (bu commit):
  "2026 yerleştirme verileri yüklendi — 2027 tercih takvimi açıklanınca
   geri sayım burada başlar"
  Sayacın neden boş olduğunu açıklar ve geri döneceğini vaat eder;
  ~95 karakter, 375 px'te saat ikonunun yanında alt satıra taşar.

Cherry-pick edilmezse dal A ile tutarlı çalışır.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:32:23 +03:00
bilalgursen
54fb72d18c refactor(sezon): tercih takvimi tek kaynakta (lib/sezon.ts)
Üst banttaki elle gömülü 2026 başlangıç/bitiş damgaları `src/lib/sezon.ts`
içindeki `SEZON_TAKVIMI`ye taşındı. Aşama hesabı (`sezonAsamasi`) ve geri
sayım hedefi (`sezonHedefi`) artık oradan geliyor; `devam-ediyor` dalının
davranışı birebir aynı. 2027 takvimi ÖSYM tarafından açıklanmadığı için
`null` bırakıldı — tarih uydurulmadı.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:18:24 +03:00
bilalgursen
f60fbd135d feat(olcum): liste_uretim_basladi olayı — üretim denemesinin paydası
Bugüne kadar yalnız başarı (liste_olusturuldu) ölçülüyordu; kaç kişinin
üretimi denediği bilinmiyordu. /listem?uret=1 ile üretim gövdesi mount
olduğunda yeni bileşen `liste_uretim_basladi` atar.

Olay bilerek liste-uretici.tsx'e değil, listem-icerik.tsx'te ona kardeş
mount edilen yeni bir istemci bileşenine kondu (o dosya bu turda başka bir
işin altında). İkisi aynı `uret` dalında render edildiği için koşulları
birebir aynı.

`kaynak` URL'den, yani kullanıcı denetiminden geldiği için allowlist'ten
geçirilir; listede olmayan değer "bilinmiyor" raporlanır. Giriş
round-trip'inde değerin kaybolmaması için geriYol da kaynağı taşır —
`uret=1` her zaman ilk parametre kalır (giris-karti.tsx:31 sözleşmesi).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:18:15 +03:00
bilalgursen
507bf53a95 feat(seo): kapanan 28 bölüm + 2 üniversite sayfası benzer sayfaya kalıcı yönlendirilir
All checks were successful
Deploy / deploy (push) Successful in 6m50s
Arşivlenen slug'lar 200 + 'sayfa yok' dönüyordu (soft 404). Eşlemenin tek kaynağı
src/lib/kapanan-sluglar.ts; alt yollar (/sayfa/N) hedefin köküne gider; zincir ya da
çift kaynak build'i durdurur. Yıllık güncelleme kılavuzuna 5b adımı eklendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 23:34:52 +03:00
bilalgursen
3cf8ec94a0 fix(veri): tadımlık örneği canlı tabanı gösterir; sunucudan gelen liste riskleri yeniden hesaplanır
Yayın sonrası denetim (2026-09-21):
- tadımlık havuzu snapshot'ı 2025 tabanını taşıyordu: örnek satır 'Tıp ~5.118,
  az riskli' derken aynı sayfadaki tablo 4.481 gösteriyordu. Taban ve sıra
  geçmişi artık okuma anında canlı DB'den; güncel kılavuzdan çıkmış program
  örnek gösterilmez (sıradaki kategoriye düşülür)
- sunucuylaBirlestir riskleri her zaman yeniler: sunucu kaydı taze taban +
  başka cihazın bayat riskini taşıyabiliyordu

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 20:06:35 +03:00
bilalgursen
49683fa113 fix(liste): kayıtlı manuel liste tabanları yeni veri yılına tazelenir; yıl metinleri 2021–2026
All checks were successful
Deploy / deploy (push) Successful in 7m24s
Denetim bulgusu (2026-09-21): ManuelTercih.efektifSira ekleme anının
snapshot'ıydı; 2026 verisi yüklenince /listem 2025 tabanıyla renk verirken
/sonuc tablosu 2026 gösteriyordu ve hiçbir yol yenilemiyordu.

- db.ts: efektifSiralarGetir(ids) — güncel COALESCE(sira2026, sira2025).
- liste-actions: listeTabanlariniTazele (oturumsuz, ≤24 id); sunucu kaydı
  (listeSenkronla/listeyiKaydet) tazelenmiş yazılır.
- liste-store: tabanlariGuncelle — efektif sıra + profil varsa risk yenilenir,
  arşivlenmiş program eski değerini korur, değişiklik yoksa yayın yok.
- liste-senkron: girişli/girişsiz herkes için sekme oturumu başına bir kez
  (anahtar SON_YIL taşır).
- meraklisina-icerik: "son beş yılın" → VERI_YIL_SAYISI.
- rehber (4 yazı): katalog sayfalarını anlatan "2021–2025 / son 5 yıl"
  ifadeleri 2021–2026 / son yıllar; yazıların kendi örnek tabloları
  2021–2025 olarak etiketli kaldı.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 18:59:05 +03:00
bilalgursen
2356e8aa38 merge: veri/2026-pc~1 — metinler ve meraklısına şeması ([Bilal] başlık-2027 commit'i hariç) 2026-09-21 17:04:25 +03:00
bilalgursen
1879ffa326 merge: veri/2026-pb — okuyan taraf yılsız Program tipine geçti 2026-09-21 17:04:25 +03:00
bilalgursen
54be4d14db merge: veri/2026 — P-0 yıl sözleşmesi + P-A veri betikleri 2026-09-21 17:04:12 +03:00
bilalgursen
ce40b7c5b3 feat(veri): Program tipi yılsız — db eşleyicisi, lib ve snapshot ilkYil (P-B a)
Program artık siraGecmisi (YILLAR ile hizalı) + efektifSira + siraSon/puanSon/
kontenjanSon/yerlesenSon taşır. db.ts kolonları YILLAR'dan üretip takma adla
seçer, programSatiri eşleyicisi ham satırı Program'a çevirir; SELECT_COLS'un
üç tüketicisi de eşleyiciden geçer. EFEKTIF_SIRA veri-yillari'dan gelir.

- trend: ILK_YIL tek kaynaktan, opsiyonel ilkYil parametresi
- rapor snapshot'ına opsiyonel ilkYil yazılır (eski kayıtlar: okurken ILK_YIL)
- rapor promptu son 4 yılı göndermeye devam eder, anahtarlar dinamik
- tadımlık "son N yıl" filtresi genel: N != VERI_YIL_SAYISI ise servis edilmez
- veri-kapsami VERI_YIL_SAYISI'nı veri-yillari'dan türetir

Bileşenler bir sonraki commit'te yeni tipe geçer (ikisi birlikte derlenir).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 17:00:39 +03:00
bilalgursen
3fa5cab906 feat(veri): katalog/OG/rapor metinleri yılı veri-yillari.ts'ten okur — 2026 yüklemesi P-C
- "2025 yerleştirme" → SON_YIL, "2026 tercihleri" → TERCIH_YILI, başlık yılı → BASLIK_YILI
- yazdırılabilir rapor dipnotu: "2021–2025" → VERI_ARALIGI
- meraklısına 1. bölüm: efektif sıra açıklaması yılsız
- KATALOG_VERI_TARIHI: 2026-09-21 (2026 verisinin çekim tarihi)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:53:42 +03:00
bilalgursen
024a2a49c4 fix(odeme): önce kredi sonra paid damgası; çift pakette iade akışı; UNIQUE tespiti
All checks were successful
Deploy / deploy (push) Successful in 8m50s
- odemeyiSonuclandir krediyi yazıp sonra paid damgalar; araya kesinti girerse
  sipariş pending kalır ve yeniden denenir (eskiden: paid görünür, kredi yok).
  paid + deftersiz eski siparişler ilk ziyarette onarılır
- paket tek seferlik: grantCredits({ paketTekil }) zaten paketliye yazmaz
  (kontrol UPDATE'in WHERE'inde). Sipariş paid damgalanır, senkron log +
  destek@ e-postası, /odeme/sonuc 'Bu ödeme iade edilecek' kartı, /kosullar#iade
- drizzle DrizzleQueryError üst mesajında 'UNIQUE' yok → idempotent no-op yerine
  hata fırlıyordu (grant + iki spend yolu); cause zincirine bakılıyor
- callback geçici DB hatasında 500 yerine sonuç sayfasına yönlendirir
- krediKaydiVarMi (reason, ref_id) indeksini kullanır; haftalık mutabakat sorgusu

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:36:24 +03:00
bilalgursen
38e02e0ed9 feat(veri): yıl kapsamı tek kaynağı (veri-yillari.ts) — 2026 yüklemesi P-0
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:35:24 +03:00
bilalgursen
d7c29ac4a6 merge: entegrasyon/guvenli-etiket — görünen 'Garanti' dilim adı 'Güvenli'
# Conflicts:
#	src/features/sihirbaz/components/cta-sira-form.tsx
2026-09-21 16:13:04 +03:00
bilalgursen
f05f3e0c69 fix: p7/p4 denetim bulguları — derin sayfa sıra yılı ve başlık uzunluğu, giriş sayacı, rybbit host
- derin /bolum ve /universite sayfalarında sıra aralığı hangi yıldan geldiğini
  söyler (2025 / 2024 / 2024–2025); 2024 sırası '2025 verisi' diye sunulmaz
- <title> yuvarlanmış rakamlarla ve şablon eki olmadan ≤~86 karakter
- giriş formunda tek geri sayım interval'i (çift sayaç butonu erken açıyordu)
- RYBBIT_HOST sonundaki '/' atılır

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:12:11 +03:00
bilalgursen
977db40099 merge: origin/gece/p4-eposta (gece vardiyası 2026-09-21) 2026-09-21 16:10:37 +03:00
bilalgursen
5853b7d091 feat(etiket): görünen "Garanti" dilim adı site genelinde "Güvenli"
Yalnız kullanıcıya görünen etiket değişir; iç anahtar, tip, DB değeri, API
parametresi, mermaid classDef ve analitik değeri `garanti` olarak kalır
(veri göçü yok).

- risk.ts: tek kaynak DILIM_ETIKET + dilimdenFarkliRiskEtiketi; rapor
  listesi, yazdır tablosu, /sonuc sekmeleri, seçimlerim paneli ve
  meraklısına şeridi buradan okur
- "Güvenli · Güvenli" / "Güvenli (Güvenli)": satır detayında risk etiketi
  yalnız dilimin varsayılanından farklıysa, yazdır ve seçimlerimde yalnız
  kelime farklıysa yazılır
- LLM prompt'ları: `garanti` teknik anahtar, adaya "güvenli" denir sözlüğü
  (rapor, soru, tadımlık); liste özeti modele görünen dilim adıyla gider
- meraklısına şeması (SEMA düğümü, aria-label), 2. bölüm anlatımı ve
  AGENTS.md şema kuralı görünen adla eşitlendi
- "yerleşme garantisi vermez" türü vaat reddi cümleleri aynen kaldı

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:03:22 +03:00
bilalgursen
9a446df572 merge: origin/gece/p3b-tadimlik-dili~1 (gece vardiyası 2026-09-21)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:27:27 +03:00
bilalgursen
a834f5ff01 merge: origin/gece/p5-kapi-olcum (gece vardiyası 2026-09-21)
All checks were successful
Deploy / deploy (push) Successful in 8m3s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:07:25 +03:00
bilalgursen
dedf3561b3 merge: origin/gece/p2-olcum~1 (gece vardiyası 2026-09-21)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:07:25 +03:00
bilalgursen
79bc7fa8be fix(ai): tadımlık trendi deterministik + gerekçe dil filtresi
cae2aaa yalnız riskNotu'yu deterministik yapmıştı; aynı satırın gerekce ve
trendOzeti alanları DB'deki eski LLM metni olarak servis ediliyordu (lokal
havuzda 89 satır "Son 4 yıl…", 13+ satır "yerleşme olasılığı/ihtimali").
Oradaki "olasılık dili sızamaz" yorumu yanlıştı; düzeltildi.
- yeni src/lib/trend.ts: trendOzetiMetni() saf fonksiyonu — rapor.ts'teki
  trendOzetiUret gövdesi buraya taşındı, rapor ve tadımlık aynı kaynaktan
  okur. Yıl aralığı serideki dolu yıllardan gelir ("2021-2025 arasında…")
- trend cümlesinden tahmin yargısı çıktı: "bölüm zorlaşıyor" → "taban
  sıkılaştı", "yerleşmek görece kolaylaşıyor" → "taban gevşedi". ±%10
  eşiği, ilk–son yıl mantığı, 5/13/6 ve LLM şeması/prompt'u aynı
- tadimlikSec(): DB'deki trendOzeti servis edilmez; program.siraGecmisi'nden
  okuma anında üretilir (alan yoksa "yeterli geçmiş yıl verisi yok")
- tadimlikSec(): gerekce olasılık/ihtimal/şans/garanti/kesin/yüzde/
  "yerleşirsin"/"son 4 yıl" içeriyorsa satır yok sayılır → "genel"
  kategoriye düşer, o da takılırsa null (tadımlık gizlenir). Eşleşme
  Türkçe küçük harfle yapılır (İ/ı)
DB satırları, şema ve script'ler değişmedi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 09:22:40 +03:00
bilalgursen
643e41cc98 fix(analitik): kullaniciTanit script'ten önce sessiz no-op olmasın
Erken olay kuyruğu yalnız olay() içindi; sert yüklemede (OAuth / e-posta
linki dönüşü) RybbitIdentify effect'i de script'ten önce koşuyor, identify
kayboluyor ve kuyruktan boşalan olaylar anonim profile yazılıyordu
(08-kod-denetimi #6).

- Tek "son değer" slotu (bekleyenKimlik): kuyruk değil, yalnız en son
  kimlik anlamlı. Yoklama zamanlayıcısı olay kuyruğuyla ortak
  (zamanlayiciyiBaslat); script 10 sn'de gelmezse slot da atılır.
- kuyruguBosalt kimliği olaylardan ÖNCE uygular.
- kullaniciTemizle slotu siler.

rybbit-identify.tsx'e dokunulmadı.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 09:22:10 +03:00
bilalgursen
67be93c394 feat(analitik): kapi_acildi + kapi_kapatildi olayları
Profil kapısının açılışı ve tamamlanmadan kapanışı doğrudan ölçülmüyordu;
"82 oturum kapıyı gördü" kod davranışından çıkarımdı (09-analitik-tur2).
İki yeni olay (adlar kalıcı sözleşme):

- kapi_acildi {tetik: arti|sonuc|sihirbaz|duzenle|diger}: depoda tek
  açılış noktası (kapiyiAc). Her açıcı kendi tetik'ini yazar:
  programEkleIste → arti, profilDuzenlemeyiAc → duzenle, profilToplamaAc →
  isteğe bağlı 3. parametre, verilmezse hedeften (sonuc/sihirbaz), o da
  yoksa diger. Depoya `tetik` alanı eklendi.
- kapi_kapatildi {adim: giris|sira|sihirbaz, tetik}: yalnız TAMAMLANMADAN
  kapanışta; kapı bileşeninde tek noktadan (vazgec) — X, dışarı tıklama,
  Esc ve "Vazgeç" butonları. Tamamlanan kapı profilTamamlandi ile depodan
  kapanır, bu noktaya uğramaz.

Ham sıra/e-posta olaylara girmez. Davranış değişmez.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 05:25:23 +03:00
bilalgursen
4b87a3e71e fix(analitik): program_eklendi yalnız gerçek eklemede atılsın
Olay, profilsiz ziyaretçide program listeye girmeyip profil kapısı
açıldığında da atılıyordu (kapiAcildi dalı else'e düşüyordu); seri
"ekleme"yi değil "+ tıklaması"nı ölçüyordu (09-analitik-tur2, S6).

- Buton: yalnız sonuc.eklendi iken {kaynak, yol: "dogrudan"}.
- profilTamamlandi: bekleyen program listeye girdiyse (ekle() true)
  {kaynak, yol: "kapi"}.
- OlayAdi yorumuna seri kırılması notu.

Davranış değişmez: profilsiz + hâlâ kapıyı açar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 05:23:40 +03:00
bilalgursen
17046c830f feat(analitik): giris_basarili sunucu olayı
Oturum oluşturulduğunda (databaseHooks.session.create.after) Rybbit'e
sunucudan giris_basarili düşer; yontem = eposta | google | diger
(better-auth uç yolundan türetilir). Huninin "link istendi → giriş yapıldı"
adımı bugüne dek ölçülemiyordu.

- await yok: Rybbit'in 3 sn'lik timeout'u girişi geciktirmez; sunucuOlayi
  hata fırlatmaz. E-posta adresi olaya girmez, yalnızca kullanıcı ID.
- RYBBIT_HOST/SITE_ID/API_KEY yoksa no-op — prod .env.production'da bu
  üçü bugün yok (bkz. ayrı ci.yaml commit'i), eklenene dek olay düşmez.

Giriş akışının davranışını değiştirmez (yalnızca yan etki ekler).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:55:10 +03:00
bilalgursen
2af4a9f781 feat(giris): adres başına 60 sn soğuma
Aynı e-posta adresine 60 sn içinde ikinci giriş linki gönderilmez: istek
yine 200 döner (form "gönderildi" gösterir), mail çıkmaz. Üçüncü kişiye
mail bombardımanını ve Resend kotasının yakılmasını engeller; bugüne dek
tek sınır better-auth'un IP limitiydi (5 istek/60 sn).

- Kaynak süreç içi Map (globalThis.__girisEpostaSon), anahtar
  trim+lowercase adres. verification tablosundan türetilmez: orada
  identifier token'dır ve satır sendMagicLink'ten önce yazılır.
- Pencere kaymaz (düşen istek süreyi uzatmaz); her çağrıda eski kayıtlar
  budanır. Gönderim hata verirse kayıt silinir, kullanıcı hemen yeniden
  deneyebilir.
- Yalnızca NODE_ENV=production: dev paneli "anında giriş" art arda istek
  atıyor. Konsol modunda da işler (lokal docker testi).

Canlı giriş yolunu değiştirir; merge öncesi lokal docker testi şart.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:55:10 +03:00
bilalgursen
cf19903e19 feat(analitik): huni olayları
Huninin kör noktalarına altı olay (adlar kalıcı sözleşme):
- cta_form_goruntulendi: programatik sayfalardaki CTA kartı, yalnız
  profilsiz dalda (görünüm hook'u; sayfa ayrımı Rybbit pathname'inden)
- sira_form_hata {kaynak: hero|cta|kapi|duzenle}: facet isteği hatası;
  geçersiz sayı doğrulaması sayılmaz
- sonuc_goruntulendi {girisli, sira_kovasi}: /sonuc pathname'i maskeli,
  huni adımı bu olayla kurulur; oturum başına girişli/anonim birer kez
- paket_goruntulendi {kaynak: kilit|kredi_bitti|nav|diger}: sayfaya
  dokunmadan yeni paket/layout.tsx + client bileşenle; /paket linklerine
  ?kaynak= eklendi (listem kilit kartları, kredi-yetersiz, nav kredi pill'i)
- liste_uretim_hata {kod: HATA|ISTISNA}: AUTH/KREDI/PAKET dalları atmaz
- giris_hata {yontem: eposta|google, status}

Ham sıra ve e-posta hiçbir olaya girmez; sıra yalnız siraKovasi() ile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:49:09 +03:00
bilalgursen
5992cf3637 fix(eposta): Reply-To + prod'da sessiz fallback yok
- Resend gönderimine replyTo eklendi (EMAIL_REPLY_TO, yoksa
  destek@kolaytercih.com) — mail.kolaytercih.com'un MX'i olmadığı için
  yanıtlar bounce oluyordu.
- epostaKonsolModu(): konsola yazma yalnızca anahtar yokken VE (dev'de ya
  da EPOSTA_KONSOL_FALLBACK=1 ile) geçerli. Production'da anahtar yoksa
  artık "gönderildi" dönmüyor, token'lı link loga yazılmıyor; gönderim
  anında net hata fırlatılıyor (better-auth 500 → formda hata toast'ı).
- Production'da EMAIL_FROM yoksa sessizce onboarding@resend.dev'e düşmek
  yerine hata. Env okumaları çağrı anında — next build etkilenmez.

Canlı giriş yolunu değiştirir; merge öncesi lokal docker testi şart.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:49:08 +03:00
bilalgursen
cae2aaab4d fix(ai): tadımlık risk notu deterministik + prompt dili
Girişsiz /sonuc tadımlığının riskNotu'su LLM üretimiydi ve DB'den olduğu
gibi servis ediliyordu; prompt'u da açıkça "yüksek/orta/düşük ihtimal dili
kullan" diyordu. Rozet ise aynı satırda canlı hesaplanıyor → metinle rozet
çelişebiliyordu.
- tadimlikSec(): riskNotu okuma anında riskNotuMetni(riskHesapla(...) ??
  dilimdenRisk(...)) ile üretilir (rozetle aynı formül). DB satırları ve
  şema değişmez; prod'da havuzu yeniden üretmek gerekmez, /api/tadimlik de
  kapsanır
- tadimlik-uret prompt'u + mock metinleri: ihtimal dili yasaklandı,
  "son 4 yıl" → "son 5 yıl" (çıktı şeması aynı; script koşulmadı)
- danışman sohbeti sistem prompt'u: "ihtimal dili kullan" → olasılık/yüzde/
  ihtimal yasak, risk etiketleri + taban sıralarıyla konuş

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:48:42 +03:00
bilalgursen
16c450827b fix(metin): olasılık dili + 5 yıl
Ürün yerleşme olasılığı üretmiyor; tek yılın tabanına göre risk dilimi
etiketi veriyor (src/lib/risk.ts). Metinler buna eşitlendi:
- "yerleşme olasılığı ve risk analizi" → "yerleşme riski ve trend analizi"
  (ana sayfa fiyat kutusu + /paket özellik listesi)
- riskNotuUret'in dört "ihtimal" cümlesi yeni riskNotuMetni()'ne taşındı;
  cümleler geçmiş taban verisine bağlanıyor, "yerleşirsin/ihtimalle" yok.
  Risk eşikleri, 5/13/6 şeması ve prompt değişmedi (yalnız cümle)
- "son 4 yıl" → VERI_YIL_SAYISI (= 5; DB sira2021–sira2025) — yeni
  src/lib/veri-kapsami.ts tek kaynağından
- arama funnel kartı: "Yerleşme ihtimalini" → "Yerleşme riskini"

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:47:47 +03:00
bilalgursen
aac33e7533 chore(eposta): şablondan harici font + footer iletişim
- <head>'deki Google Fonts preconnect/stylesheet <link>'leri kaldırıldı
  (çoğu istemci yok sayıyor, bazı spam filtrelerinde eksi puan).
- HTML footer'a ve düz metin gövdelerin sonuna kolaytercih.com +
  destek@kolaytercih.com satırı eklendi. Satış dili yok.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:47:30 +03:00
bilalgursen
d9e125c5de feat(rehber): guncelleme alanı → sitemap/JSON-LD/OG/görünür tarih
Frontmatter'a isteğe bağlı `guncelleme` alanı geldi ve uçtan uca akıyor:
sitemap lastmod (yazı + /rehber dizini), Article JSON-LD dateModified,
og:article modified_time ve makale başlığının altındaki görünür tarih
satırı. `tarih`/`guncelleme` YYYY-AA-GG değilse ya da güncelleme yayından
önceyse build kırılır. Tarih metni saat diliminden bağımsız `trTarih` ile
üretilir.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:47:29 +03:00
bilalgursen
fa43392077 fix(analitik): görünüm hook'u callback ref + erken olay kuyruğu
useGorunumOlayi useRef + [ad, anahtarEki] deps'li effect kullanıyordu:
eleman ilk commit'te yoksa (kaydet-banner: mount sonrası açılır, portal
içinde) ya da sökülüp yeni düğümle geri geliyorsa (tadımlık satırı) gözlem
hiç kurulmuyordu → kaydet_banner_goruntulendi / tadimlik_goruntulendi = 0.
Hook artık callback ref döner; gözlem düğüm bağlanınca kurulur, sökülünce
React 19 ref temizliğiyle bırakılır. Çağıranlar yalnız ref={…} verdiği
için kullanım yerleri değişmedi.

olay(): Rybbit script'i afterInteractive; sert yüklemede mount anında
atılan olaylar window.rybbit henüz yokken sessizce düşüyordu. Artık en çok
20 olay, 500 ms aralıkla en çok 20 deneme (10 sn) kuyrukta bekler; script
gelmezse (reklam engelleyici, dev) kuyruk atılır.

olayBirKez(): hook'taki sessionStorage tekilleştirmesinin effect'ten
çağrılabilir hâli (anahtar biçimi aynı: kolaytercih.olay.<ad>[.<ek>]).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:47:24 +03:00
bilalgursen
a9ea0bf49b fix(rehber): frontmatter tırnak + tablo sarmalayıcı
Frontmatter değerinin iki ucundaki tırnak bağımsız siliniyordu; "Alıntı"
diye başlayan açıklamalar baştaki tırnağını kaybediyordu. Artık yalnızca
tamamı aynı tırnakla sarılı değer soyulur. Makale tabloları yatay kayan,
klavyeyle odaklanabilir bir bölgeye sarılır (mobilde sayfa taşması).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 04:46:19 +03:00
bilalgursen
53eb07bb34 feat(seo): GEO paketi — yapılandırılmış metadata, AI bot erişimi, veri tazelik sinyali
- sayfaMetadata(): indekslenebilir sayfalar için tek kaynaklı canonical +
  eksiksiz openGraph üretimi; sayfalar buna geçirildi
- robots.ts: yalnızca /api/ engellenir; noindex'li sayfalar robots engeli
  yerine meta ile yönetilir, AI botları niyeti belgeleyen açık grupla izinli
- next.config: htmlLimitedBots'a AI botları eklendi (JS çalıştırmayan
  botlara metadata head içinde bloklanarak verilir)
- sitemap lastmod + katalogda görünür 'Kaynak/son güncelleme' satırı
  (VeriKaynagi) KATALOG_VERI_TARIHI tek kaynağından
- docs/geo/geo-raporu.md: çalışmanın raporu

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-21 00:51:16 +03:00
bilalgursen
d2651eadb9 fix(odeme): postman-request zincirini standalone trace'ine sok
Some checks failed
Deploy / deploy (push) Has been cancelled
outputFileTracingIncludes yalnızca eşleşen dosyaları kopyalar, trace etmez:
resources/*.js imaja girdi ama IyzipayResource'un require ettiği
postman-request ve bağımlılıkları girmedi — initialize prod'da
"Cannot find module 'postman-request'" ile düşüyordu. IyzipayResource'u
statik import etmek nft trace'inin tüm zinciri doğru pnpm yerleşimiyle
kopyalamasını sağlar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-21 00:42:44 +03:00
bilalgursen
951caa3c93 refactor(odeme): update environment variable usage and documentation
All checks were successful
Deploy / deploy (push) Successful in 8m39s
Replaced `NEXT_PUBLIC_APP_URL` with `APP_URL` in the payment processing logic to ensure proper runtime access. Updated related documentation to clarify the distinction between build-time and runtime environment variables, emphasizing the importance of using `APP_URL` for callback and webhook URLs. Adjusted references in the codebase to reflect this change, enhancing clarity and functionality in the payment flow.
2026-08-11 11:42:47 +03:00
bilalgursen
5ccc9c1ffa chore: update iyzico payment processing and database schema
All checks were successful
Deploy / deploy (push) Successful in 9m3s
Enhanced the iyzico payment processing logic by updating the handling of checkout form content. Modified the order schema to include a new field for storing the checkout form content, ensuring it persists across page refreshes. Updated related functions to reflect these changes, improving the overall payment experience. Additionally, updated the app database to incorporate the latest changes.
2026-08-11 00:51:58 +03:00