diff --git a/content/rehber/devlet-mi-vakif-mi.md b/content/rehber/devlet-mi-vakif-mi.md
new file mode 100644
index 0000000..9699fcb
--- /dev/null
+++ b/content/rehber/devlet-mi-vakif-mi.md
@@ -0,0 +1,32 @@
+---
+baslik: Devlet mi Vakıf mı? Burslu ve İndirimli Programlar Nasıl Okunur?
+aciklama: Aynı bölümün beş farklı fiyat etiketi var — %100 burslu, %50 indirimli, ücretli... Vakıf tablosunu doğru okumanın ve devletle kıyaslamanın rehberi.
+tarih: 2026-07-19
+---
+
+Tercih tablolarında aynı bölümün adı beş kez geçebilir: *Psikoloji (Burslu)*, *Psikoloji (%50 İndirimli)*, *Psikoloji (%25 İndirimli)*, *Psikoloji (Ücretli)*, *Psikoloji (İngilizce)*. Bunlar ayrı programlardır: ayrı kontenjan, ayrı taban, ayrı fiyat. Bu yazı tabloyu doğru okumayı ve devlet-vakıf kararını sağlıklı vermeyi anlatıyor.
+
+## Varyantlar ne anlama geliyor?
+
+- **Burslu (%100):** Öğrenim ücreti yok. Vakıfların vitrini olduğu için tabanı çoğu zaman aynı üniversitenin ücretli programından *yüz binlerce sıra* daha iyidir; köklü devletlerle yarışır.
+- **%50 / %25 indirimli:** Ücretin o oranı düşülür. Kalan tutar yıllara ve okula göre ciddi bir bütçedir; 4-6 yıllık toplam maliyeti baştan hesapla.
+- **Ücretli:** Tam ücret. Tabanlar genelde en geniştir.
+- **İngilizce / UOLP:** Öğretim dili veya ortak program bilgisidir; burs bilgisi değildir. Hazırlık yılı ekleyebilir.
+
+Kritik uyarı: **bursun sürme koşullarını** üniversitenin kendi yönetmeliğinden kontrol et. Çoğu vakıfta giriş bursu süresizdir ama bazı okullarda not ortalaması şartı vardır.
+
+## Devlet-vakıf kararında gerçek kriterler
+
+**Bütçe dışında** şunlara bak:
+
+1. **Kadro ve bölümün kurumsallığı.** Bölümün öğretim üyesi sayısı, araştırma çıktısı, akreditasyonu (MÜDEK, PSİKOLOG odaklı akreditasyonlar vb.) devlet-vakıf etiketinden daha belirleyicidir.
+2. **Şehir ve yaşam maliyeti.** Devlet okulu + büyükşehir kirası, bazen vakıf burslusu + yurt kombinasyonundan pahalıya gelir. Toplam maliyeti karşılaştır.
+3. **Tabanın söylediği.** Bir vakıf burslusunun tabanı köklü devletlerle aynıysa, piyasa o programa devlet muadili değer biçiyor demektir. [İşletme](/bolum/isletme) veya [Psikoloji](/bolum/psikoloji) tablolarını aç; Tür kolonunda devlet/vakıf ayrımını, satır altlarında burs varyantlarını yan yana görüp kendi sıralamanla kıyaslayabilirsin.
+
+## Listede nasıl konumlanır?
+
+- Burslu vakıf programları taban olarak "hayal/dengeli" bölgene düşüyorsa devlet alternatifleriyle **aynı blokta, istek sırana göre** diz — ayrı kefeye koyma.
+- İndirimli programlarda aileyle net bütçe konuşmasını *listeyi vermeden önce* yap; yerleştikten sonra "ödeyemeyiz" durumu bir yıl kaybettirir.
+- Ücretli programı yalnızca bütçe gerçekten uygunsa ve o okulu gerçekten istiyorsan yaz — "garanti olsun" diye yazılan ücretli program, kayıt yaptırmayacaksan [ölü tercihten](/rehber/olu-tercih-nedir) beterdir: yerleşirsen ek tercih hakkın da yanar.
+
+Sıralamana hangi devlet ve vakıf programlarının düştüğünü tek ekranda görmek için [tercih robotuna](/tercih-robotu) sıralamanı gir; devlet/vakıf filtresiyle iki evreni ayrı ayrı da tarayabilirsin.
diff --git a/content/rehber/ek-yerlestirme-2026.md b/content/rehber/ek-yerlestirme-2026.md
new file mode 100644
index 0000000..2e8fe0b
--- /dev/null
+++ b/content/rehber/ek-yerlestirme-2026.md
@@ -0,0 +1,40 @@
+---
+baslik: Ek Yerleştirme Nedir? 2026 Ek Tercih Rehberi
+aciklama: İlk yerleştirmede boşta kaldıysan oyun bitmedi — ek yerleştirmenin kuralları, kimlerin başvurabileceği ve ikinci şansı doğru kullanmanın yolu.
+tarih: 2026-07-22
+---
+
+Merkezi yerleştirme sonuçları açıklandığında bir programa yerleşememiş olmak yılın sonu değildir. Üniversiteler kayıt dönemini kapattığında binlerce kontenjan boş kalır ve ÖSYM bu boş kontenjanlar için **ek yerleştirme** (ek tercih) süreci açar.
+
+## Ek yerleştirme ne zaman?
+
+Kayıtlar tamamlandıktan sonra, genellikle **Eylül ayı içinde**. ÖSYM önce boş kontenjanları içeren Ek Yerleştirme Kılavuzu'nu yayımlar, ardından birkaç günlük tercih penceresi açılır. Kesin tarihler her yıl ÖSYM duyurusuyla netleşir — tercih takviminin tamamı için [YKS 2026 tercih takvimi](/rehber/yks-tercih-takvimi-2026) yazısına bak.
+
+## Kimler başvurabilir?
+
+Kurallar nettir ve en kritik olanı şudur:
+
+- **İlk yerleştirmede herhangi bir programa yerleşen aday, kayıt yaptırmasa bile ek yerleştirmeye başvuramaz.** "Yerleştim ama gitmeyeceğim, ek tercihte daha iyisini denerim" diye bir yol yoktur.
+- Ek yerleştirme yalnızca ilk yerleştirmede **hiçbir programa yerleşememiş** adaylara açıktır.
+- İlk dönemde hiç tercih yapmamış adaylar da ek yerleştirmeye katılabilir.
+
+Bu kural, ilk listenin sonuna "kayıt yaptırmayacağım ama boşta da kalmayayım" mantığıyla program yazmanın neden tehlikeli olduğunu gösterir: oraya yerleşirsen ek tercih hakkın yanar. Bu tuzağın detayı [tercih listesi rehberinde](/rehber/tercih-listesi-nasil-yapilir).
+
+## Ek yerleştirmede taban nasıl işler?
+
+Ek yerleştirmede bir programa başvurabilmek için o programın **ilk yerleştirmedeki taban puanına eşit veya daha yüksek** puana sahip olman gerekir (ilk yerleştirmede hiç dolmayan programlarda bu şart esner). Yani ek tercih "tabanlar sıfırlanır, herkes her yere yazılır" demek değildir.
+
+## Boş kontenjanlar nereden çıkar?
+
+- İlk yerleştirmede hiç dolmayan programlar (çoğunlukla vakıf ücretli ve bazı önlisans programları),
+- Yerleşip kayıt yaptırmayan adaylardan boşalan yerler.
+
+Boş kontenjan listesi ağırlıklı olarak vakıf üniversiteleri, ücretli/indirimli varyantlar ve önlisans programlarından oluşur; ama her yıl devlet üniversitelerinden de şaşırtıcı fırsatlar çıkar. Hangi bölümlerde kontenjanların geniş olduğuna dair fikir edinmek için [tüm bölümlerin taban puanları](/bolumler) sayfasındaki kontenjan kolonlarına göz at.
+
+## Ek tercih stratejisi
+
+1. **Kılavuzu bekleme, hazırlığını şimdi yap.** Sıralamana uygun program evrenini [tercih robotuyla](/tercih-robotu) önceden çıkar; kılavuz yayımlanınca sadece kesişimi almak kalır.
+2. **İlk yerleştirme mantığıyla kurma.** Ek yerleştirmede tek liste hakkın var ve pencere kısa; dengeli-garanti ağırlıklı, gerçekçi bir liste kur.
+3. **Kayıt yaptırmayacağın programı yine yazma.** Aynı kural burada da geçerli — ek yerleştirmeden sonra üçüncü bir şans yok.
+
+Ek yerleştirme, ilk turda şanssızlık yaşayanlar için gerçek bir ikinci şanstır; panik turu değil. Veriyle ve soğukkanlı kurulmuş bir ek liste, aceleyle yazılmış ilk listeden daha iyi sonuç verebilir.
diff --git a/content/rehber/kac-siralama-ile-hangi-bolume-girebilirim.md b/content/rehber/kac-siralama-ile-hangi-bolume-girebilirim.md
new file mode 100644
index 0000000..12f73cd
--- /dev/null
+++ b/content/rehber/kac-siralama-ile-hangi-bolume-girebilirim.md
@@ -0,0 +1,41 @@
+---
+baslik: Kaç Sıralama ile Hangi Bölüme Girebilirim? (2025 Verileriyle)
+aciklama: 10 binden 1 milyona — sıralama bandına göre hangi bölümlerin gerçekçi olduğunun veriye dayalı haritası.
+tarih: 2026-07-23
+---
+
+"Sıralamam X, nereyi kazanırım?" tercih döneminin en çok sorulan sorusu. Aşağıdaki bantlar 2025 YKS yerleştirme verilerine (YÖK Atlas) dayanır ve **kabaca bir harita** çizer — kesin sınır değildir; aynı bölümün tabanı üniversiteye, şehre ve burs durumuna göre çok geniş bir aralığa yayılır.
+
+## Sayısal (SAY) için kaba harita
+
+| Sıralama bandı | Gerçekçi seçenekler |
+| --- | --- |
+| İlk 5 bin | Köklü devletlerde [Tıp](/bolum/tip), [Bilgisayar Mühendisliği](/bolum/bilgisayar-muhendisligi), [Elektrik-Elektronik Mühendisliği](/bolum/elektrik-elektronik-muhendisligi) |
+| 5-25 bin | Devlet tıp (yeni fakülteler), [Diş Hekimliği](/bolum/dis-hekimligi), iyi devletlerde mühendislikler |
+| 25-75 bin | [Eczacılık](/bolum/eczacilik), devlet mühendislikleri, [Mimarlık](/bolum/mimarlik) |
+| 75-200 bin | Sağlık bilimleri ([Fizyoterapi ve Rehabilitasyon](/bolum/fizyoterapi-ve-rehabilitasyon), [Hemşirelik](/bolum/hemsirelik)), Anadolu devletlerinde mühendislik |
+| 200-500 bin | Fen bilimleri, ziraat, daha geniş kapatan mühendislikler, vakıf burslu seçenekleri |
+| 500 bin+ | Açıköğretim dışı seçenekler daralır; önlisans (TYT) tarafı güçlü alternatif olur |
+
+## Eşit Ağırlık (EA) için kaba harita
+
+| Sıralama bandı | Gerçekçi seçenekler |
+| --- | --- |
+| İlk 10 bin | Köklü devletlerde [Hukuk](/bolum/hukuk), [Psikoloji](/bolum/psikoloji) |
+| 10-50 bin | Devlet hukuk (geniş kapatanlar), [İşletme](/bolum/isletme) / [İktisat](/bolum/iktisat) (iyi devletler), Psikoloji |
+| 50-150 bin | Anadolu devletlerinde İİBF bölümleri, [Rehberlik ve Psikolojik Danışmanlık](/bolum/rehberlik-ve-psikolojik-danismanlik) |
+| 150-400 bin | Vakıf burslu/indirimli seçenekler, sosyal hizmet, kamu yönetimi |
+
+Sözel ve Dil tarafında bantlar daha da geniştir; öğretmenlikler için ayrıca **başarı sıralaması şartı** devreye girer — detayı [Baraj ve başarı sıralaması şartları](/rehber/siralama-sartlari-2026) yazısında.
+
+## Bu tabloyu nasıl kullanmalısın?
+
+1. **Bandını bul, ama banda güvenme.** Bant sana "hangi bölümlere bakmaya değer" der; hangi üniversitede tutacağını söylemez. Aynı bölüm içinde tabanlar 10 kat oynayabilir.
+2. **Bölüm sayfasının tablosuna in.** Örneğin [Psikoloji taban puanları](/bolum/psikoloji) sayfasında 380'e yakın programın tek tek tabanını görürsün — senin sıralaman listenin neresine düşüyorsa gerçekçi bölgen orasıdır.
+3. **Kendi sıralamanla tara.** [Tercih robotuna](/tercih-robotu) sıralamanı gir; robot 23.000+ programın içinden senin bandına düşenleri hayal/dengeli/garanti dilimleriyle ayırıp önüne koyar. Tablo ezberlemekten hızlıdır.
+
+## Unutma
+
+- Sıralaman **puan türüne özeldir**; SAY sıralaman ile EA sıralaman farklıdır, her listeyi kendi türünün sıralamasıyla kur.
+- Burslu/indirimli/İngilizce varyantların tabanları aynı bölümde bile çok farklıdır.
+- 2026 tabanları bu yılın yerleştirmesiyle netleşir; buradaki veriler pusula, garanti değil.
diff --git a/content/rehber/olu-tercih-nedir.md b/content/rehber/olu-tercih-nedir.md
new file mode 100644
index 0000000..10788cd
--- /dev/null
+++ b/content/rehber/olu-tercih-nedir.md
@@ -0,0 +1,33 @@
+---
+baslik: Ölü Tercih Nedir, Nasıl Anlaşılır? (Ve Nasıl Kaçınılır)
+aciklama: Listende hiç işe yaramayan satırlar olabilir. Ölü tercihin tanımı, en sık yapılan iki biçimi ve listeni bu tuzaktan temizlemenin yolu.
+tarih: 2026-07-24
+---
+
+Ölü tercih, **hiçbir senaryoda seni yerleştirmeyecek satır** demektir. Listende durur, yer kaplar ama hiç işe yaramaz. 24 tercih hakkın varken bunun 5-6'sını ölü satırlara harcamak, tercih dönemi hatalarının en sessizidir — kimse fark etmez, ta ki sonuçlar açıklanana kadar.
+
+## Ölü tercihin iki biçimi
+
+**1) Sıralaması yetmeyecek programı listenin sonuna yazmak.**
+ÖSYM yerleştirme sistemi listeni yukarıdan aşağı okur ve seni *yerleşebildiğin en üst tercihe* koyar. Diyelim sıralaman 200 bin ve 15. sıraya tabanı 40 bin kapatan bir program yazdın. O programa yerleşebilmen için üstteki 14 tercihin de tutmaması VE tabanın 40 binden 200 bine gevşemesi gerekir — pratikte imkânsız. O satır ölüdür. Hayal tercihi meşrudur ama yeri listenin **başıdır**, sonu değil.
+
+**2) Zaten üstte yazdığın programın kopyasını alta yazmak.**
+Aynı programın ikinci yazımı sistemde hiçbir şey değiştirmez. Benzer şekilde, tabanı üstteki tercihten belirgin şekilde daha iyi olan bir programı alta koymak da ölüdür: üstteki tutmadıysa alttaki hiç tutmaz.
+
+## Nasıl anlarsın?
+
+Her satır için şu soruyu sor: **"Bu programa yerleşmem için üstümdeki tercihlerin hepsinin tutmaması VE bu programın tabanının benim sıralamama gelmesi gerçekçi mi?"**
+
+Pratik kontrol yöntemi:
+
+- Satırın taban sıralamasına son 4 yıl üzerinden bak (tek yıl yanıltır).
+- Tabanı, senin sıralamandan iyiyse → o satır ancak listenin *üst bloğunda* (hayal) anlamlıdır.
+- Tabanı üstündeki satırdan da iyiyse → sıra hatası var; satırları taban gevşekliğine göre yeniden diz.
+
+[Tercih robotuna](/tercih-robotu) sıralamanı girdiğinde programlar hayal/dengeli/garanti dilimleriyle etiketlenir; bir programın senin sıralamana göre hangi bölgede olduğunu tek bakışta görürsün. Popüler bölümlerde tabanların ne kadar geniş bir aralığa yayıldığını görmek için [Psikoloji](/bolum/psikoloji) veya [Hukuk](/bolum/hukuk) tablolarına bak — aynı bölümün tabanı üniversiteye göre yüz binlerce sıra oynayabilir; yani bölüm ölü değildir, *yanlış üniversite-satır eşleşmesi* ölüdür.
+
+## Ölü tercihten temizlenmiş liste nasıl görünür?
+
+Yukarıdan aşağı **tabanlar giderek gevşer**. İlk satırlar "tutarsa harika", orta blok "büyük ihtimal buradayım", son satırlar "kesin tutar ve severek giderim" der. Grafiğe döksen düzgün bir merdiven görürsün; ölü tercihli listelerde merdivenin ortasında yukarı fırlayan basamaklar olur.
+
+Son bir uyarı: ölü tercihi temizleyeyim derken listenin başındaki hayal tercihlerini de kesme. Üst sıradaki iddialı tercih ölü değildir — bedava piyango biletidir. Ölü olan, o iddialı tercihi listenin *sonuna* saklamaktır.
diff --git a/content/rehber/onlisans-mi-lisans-mi.md b/content/rehber/onlisans-mi-lisans-mi.md
new file mode 100644
index 0000000..d1b9def
--- /dev/null
+++ b/content/rehber/onlisans-mi-lisans-mi.md
@@ -0,0 +1,32 @@
+---
+baslik: TYT ile Önlisans Tercihi — Önlisans mı, Lisans mı?
+aciklama: 2 yıllıklar "yedek plan" değil, başlı başına bir rota. Önlisansın avantajları, DGS köprüsü ve TYT sıralamasıyla akıllı tercih kurmanın yolu.
+tarih: 2026-07-17
+---
+
+AYT'si istediği gibi gitmeyen ya da hedefi zaten uygulamalı bir meslek olan aday için önlisans (2 yıllık) programlar güçlü bir rotadır. Türkiye'deki yükseköğretim kontenjanının büyük bölümü TYT puan türüyle öğrenci alan önlisans programlarındadır — yani seçenek evreni geniştir.
+
+## Önlisans ne zaman doğru tercih?
+
+- **Hedef meslek uygulamalıysa.** [Bilgisayar Programcılığı](/bolum/bilgisayar-programciligi), [Anestezi](/bolum/anestezi), [İlk ve Acil Yardım](/bolum/ilk-ve-acil-yardim) gibi programlar 2 yılda alana özgü istihdama bağlanır.
+- **Lisansa köprü olarak.** DGS (Dikey Geçiş Sınavı) ile önlisans mezunları ilgili lisans bölümlerine geçebilir. "TYT'm iyi, AYT'm zayıf" profili için 2+ yıl planı — önlisans + DGS — düşük sıralamayla doğrudan zayıf bir lisansa gitmekten daha iyi sonuç verebilir.
+- **Bir yıl daha sınav istemiyorsan.** Tekrar hazırlanmak yerine alanda ilerlemek isteyene zaman kazandırır.
+
+## Lisans lehine düşünmen gereken durumlar
+
+- Hedef meslek lisans diploması şart koşuyorsa (mühendislik, hukuk, tıp, öğretmenlik...).
+- Sıralaman, gitmekten mutlu olacağın bir lisans programına yetiyorsa — sırf "üniversite kazandı" demek için istemediğin lisansa gitmek de, gereksiz yere önlisansa razı olmak da hatadır. Bandını görmek için [kaç sıralama ile hangi bölüme girebilirim](/rehber/kac-siralama-ile-hangi-bolume-girebilirim) rehberine bak.
+
+## TYT tablosunu doğru okumak
+
+Önlisans tercihinde üç ayrıntı belirleyicidir:
+
+1. **Sıralama TYT sıralamasıdır.** SAY/EA sıralamanla önlisans tablosu okuma; sonuç belgende TYT satırı ayrı yazar.
+2. **Aynı programın tabanı okula göre uçurum yapar.** Büyükşehirdeki köklü bir MYO'nun programı ile küçük ilçe MYO'sunun aynı adlı programı arasında yüz binlerce sıra fark olabilir — [Bilgisayar Programcılığı tablosunda](/bolum/bilgisayar-programciligi) bunu net görürsün (395 program!).
+3. **DGS planın varsa bölüm adına dikkat.** DGS'de hangi önlisanstan hangi lisansa geçilebildiği tablolarla sınırlıdır; hedef lisansı önce belirle, ona köprü olan önlisansı sonra seç.
+
+## Tercih listesi taktiği
+
+24 tercih hakkı lisans ve önlisansta **ortaktır** — aynı listeye ikisini de yazabilirsin. Ama farklı puan türlerinin sıralamaları karışacağı için düzeni şöyle kur: önce gitmeye razı olduğun lisans programları (kendi türünün sıralamasıyla), sonra önlisans bloğu (TYT sıralamasıyla). Her iki blokta da [ölü tercih](/rehber/olu-tercih-nedir) kuralları aynen geçerli.
+
+TYT sıralamanı [tercih robotuna](/tercih-robotu) girip türü "TYT" seçersen önlisans evrenini hayal/dengeli/garanti dilimleriyle görürsün; lisans sıralamanla da ayrı bir tarama yapıp iki listeyi yan yana koyman en sağlıklısı.
diff --git a/content/rehber/siralama-sartlari-2026.md b/content/rehber/siralama-sartlari-2026.md
new file mode 100644
index 0000000..93a2417
--- /dev/null
+++ b/content/rehber/siralama-sartlari-2026.md
@@ -0,0 +1,40 @@
+---
+baslik: Baraj ve Başarı Sıralaması Şartları 2026 (Tıp, Hukuk, Mühendislik, Öğretmenlik...)
+aciklama: Bazı bölümleri istemek yetmez — YÖK'ün koyduğu başarı sıralaması şartını geçmek gerekir. Hangi bölümde hangi eşik var, tek tabloda.
+tarih: 2026-07-18
+---
+
+Bazı bölümler için puanın ve sıralaman "yetiyor" görünse bile, YÖK'ün belirlediği **başarı sıralaması şartını** sağlamıyorsan o bölümü tercih bile edemezsin. Bu şart taban sıralamasından farklıdır: taban, yerleşen son kişinin sıralamasıdır ve her yıl piyasada oluşur; **sıralama şartı** ise merkezî bir üst eşiktir — geçemeyen listeye yazamaz.
+
+## 2026'da sıralama şartı olan başlıca bölümler
+
+| Bölüm | Puan türü | Sıralama şartı |
+| --- | --- | --- |
+| [Tıp](/bolum/tip) | SAY | İlk 50 bin |
+| [Hukuk](/bolum/hukuk) | EA | İlk 100 bin |
+| [Diş Hekimliği](/bolum/dis-hekimligi) | SAY | İlk 80 bin |
+| [Eczacılık](/bolum/eczacilik) | SAY | İlk 100 bin |
+| Mühendislik programları (ör. [Bilgisayar Mühendisliği](/bolum/bilgisayar-muhendisligi)) | SAY | İlk 300 bin |
+| [Mimarlık](/bolum/mimarlik) | SAY | İlk 250 bin |
+| Öğretmenlik programları (ör. [İlköğretim Matematik Öğretmenliği](/bolum/ilkogretim-matematik-ogretmenligi)) | İlgili tür | İlk 300 bin |
+
+Şartlar kılavuzla kesinleşir; tercih vermeden önce mutlaka ÖSYM kılavuzunun güncel maddesinden doğrula. (Eşikler son yıllarda sabit seyrediyor ama nihai söz her yıl kılavuzundur.)
+
+## Sıralama şartı ile taban sıralaması karışmasın
+
+İki örnekle netleşir:
+
+- Sıralaman SAY 45 bin olsun. Tıp için şartı (ilk 50 bin) **geçiyorsun** — tercih edebilirsin. Ama köklü devlet tıp fakültelerinin tabanı ilk 5-15 bin bandında kapanır; senin gerçekçi tıp evrenin tabanı 45 bine yakın olan fakültelerdir. Şartı geçmek yerleşmeyi garanti etmez.
+- Sıralaman EA 130 bin olsun. Hukuk şartı ilk 100 bin olduğundan hukuk programlarını **hiç tercih edemezsin** — tabanı 130 binden geniş bir hukuk fakültesi olsa bile. Bu durumda enerjini şartı olmayan komşu bölümlere ([Kamu Yönetimi](/bolum/kamu-yonetimi), [Sosyal Hizmet](/bolum/sosyal-hizmet) vb.) yönlendirmek daha akıllıca.
+
+## Baraj puanları
+
+Sıralama şartından ayrı olarak tercih yapabilmek için puan türünde **baraj puanını** aşmış olman gerekir (TYT ve ilgili yerleştirme puanı barajları). Sonuç belgende puanın hesaplandıysa bu barajı geçmişsin demektir; ayrıca dert etme.
+
+## Ne yapmalı?
+
+1. Hedef bölümünün şartı var mı, kılavuzdan işaretle.
+2. Şartı geçiyorsan gözünü tabana çevir: bölüm sayfasındaki tabloda ([örnek: Tıp](/bolum/tip)) kendi sıralamanın düştüğü bandı bul.
+3. Şartı geçemiyorsan o bölümü listeden çıkar ve alternatif rotayı kur — [tercih robotu](/tercih-robotu) sıralamana uygun programları zaten şartlara göre süzülmüş tablolar üzerinden gösterir.
+
+Sıralama şartı acımasız görünür ama işlevi nettir: hem kontenjan enflasyonunu hem de "nasılsa yazayım" kalabalığını engeller. Senin işin, şartı geçtiğin bölümlerde tabanı doğru okumak.
diff --git a/content/rehber/taban-puan-mi-siralama-mi.md b/content/rehber/taban-puan-mi-siralama-mi.md
new file mode 100644
index 0000000..d8e4c7f
--- /dev/null
+++ b/content/rehber/taban-puan-mi-siralama-mi.md
@@ -0,0 +1,33 @@
+---
+baslik: Taban Puan mı, Başarı Sıralaması mı? Tercihte Hangisine Bakılır?
+aciklama: İki sayı da sonuç belgende yazıyor ama tercih listeni sadece biriyle kurmalısın. Neden sıralamanın kazandığının kısa ve net açıklaması.
+tarih: 2026-07-21
+---
+
+Kısa cevap: **başarı sıralamasına bakılır.** Taban puan, tabelada büyük yazan ama seni yanıltan sayıdır. Nedenini iki dakikada anlatalım.
+
+## Puan neden yanıltır?
+
+YKS puanı, sınavın o yılki zorluğuna ve aday kitlesinin performansına göre şekillenir. Sınav kolay geçtiyse herkesin puanı şişer; zor geçtiyse söner. 450 puan bir yıl ilk 30 bine, ertesi yıl ilk 60 bine denk gelebilir. Yani "geçen yıl bu bölüm 450 ile kapatmış, benim puanım 455, güvendeyim" cümlesi hatalıdır — iki farklı yılın puanları aynı cetvelle ölçülmez.
+
+## Sıralama neden güvenilir?
+
+Başarı sıralaması, seni o yıl sınava giren herkesle kıyaslar: "SAY'da 85.000'incisin" bilgisi yıldan yıla **karşılaştırılabilir** kalır. Bir programın geçen yılki taban *sıralaması* 90 bin ise, bu yıl 85 bininci aday için o program "dengeli" bölgededir — sınav kolay muydu zor muydu fark etmez, çünkü herkes aynı gemide.
+
+ÖSYM sonuç belgende her puan türü için ayrı sıralama yazar. Tercih listeni hangi türden kuruyorsan **o türün sıralamasını** kullan; SAY sıralamanla EA listesi kurmak elma-armut kıyasıdır.
+
+## Peki taban puan ne işe yarar?
+
+- Aynı yıl içinde iki programı kabaca kıyaslamaya,
+- Ek yerleştirmede başvuru eşiği olarak (ek tercihte ilk yerleştirme taban puanı şart koşulur — detay [ek yerleştirme rehberinde](/rehber/ek-yerlestirme-2026)),
+- Bir de haber sitelerine manşet olmaya.
+
+Liste kurarken açtığın her tabloda gözün **sıralama kolonunda** olmalı. Örneğin [Bilgisayar Mühendisliği taban puanları](/bolum/bilgisayar-muhendisligi) sayfasında programlar taban sıralamasına göre dizilir; puan kolonu yalnızca bağlam içindir. Aynısı [Hukuk](/bolum/hukuk) ve tüm diğer bölüm sayfaları için geçerli.
+
+## Uygulamada üç kural
+
+1. **Listeyi sıralamayla kur.** Her satırın son 3-4 yıllık taban sıralaması trendine bak; tek yıl yanıltır ([neden yanılttığını burada gösterdik](/rehber/taban-siralamalar-nasil-degisir)).
+2. **Puan haberlerine kapılma.** "X bölümü 500 puanla öğrenci aldı" manşeti sana hiçbir şey söylemez; o yılın 500 puanı kaçıncı sıraysa bilgi odur.
+3. **Sıralamanı doğru yerden oku.** ÖSYM sonuç belgesindeki, kendi puan türünün "başarı sırası" satırı. OBP eklenmiş/eklenmemiş karışıklığına dikkat — tercihte kullanılan, yerleştirme puanına ait sıralamadır.
+
+Sıralamanı biliyorsan gerisi mekanik: [tercih robotuna](/tercih-robotu) gir, sıralamana uygun programları hayal/dengeli/garanti dilimleriyle gör, listeni veriyle kur.
diff --git a/content/rehber/taban-siralamalar-nasil-degisir.md b/content/rehber/taban-siralamalar-nasil-degisir.md
new file mode 100644
index 0000000..21c1437
--- /dev/null
+++ b/content/rehber/taban-siralamalar-nasil-degisir.md
@@ -0,0 +1,39 @@
+---
+baslik: Taban Sıralamalar Yıldan Yıla Ne Kadar Değişir?
+aciklama: "Geçen yıl 90 bin kapatmış, ben 85 binim, garanti" demeden önce oku — tabanları oynatan beş mekanizma ve trend okumanın doğru yolu.
+tarih: 2026-07-16
+---
+
+Tercih listeni geçen yılın tabanlarıyla kuruyorsun ama yerleşmeni **bu yılın** tabanları belirleyecek. Aradaki fark bazen birkaç bin, bazen yüz binlerce sıra. Bu yazı tabanları neyin oynattığını ve trendi nasıl okuyacağını anlatıyor.
+
+## Tabanı oynatan mekanizmalar
+
+**1) Kontenjan değişimi.** En mekanik etki: bir program kontenjanını 60'tan 90'a çıkarırsa taban gevşer; 90'dan 60'a inerse sıkılaşır. Bölüm sayfalarındaki kontenjan kolonunu yıllar arasında kıyaslamak bu yüzden önemli.
+
+**2) Aday davranışı (sürü etkisi).** "Geçen yıl çok kapattı" diye herkes bir programdan kaçarsa taban gevşer; "gevşedi" diye ertesi yıl herkes geri dönerse tekrar sıkılaşır. Tabanlar bu yüzden testere dişi gibi salınabilir — tek yıla bakan, testere dişinin tepesinden ya da dibinden ölçüm alır.
+
+**3) Yeni açılan programlar.** Bir şehirde yeni fakülte açılınca hem kendi tabanı belirsiz olur hem çevresindeki programların tabanını seyreltir.
+
+**4) Şartlar ve politika değişiklikleri.** Başarı sıralaması şartının gelmesi/eşiğin değişmesi, burs oranlarının değişmesi, öğretim dilinin değişmesi tabanı sıçratır. ([Şartların güncel listesi burada.](/rehber/siralama-sartlari-2026))
+
+**5) Ekonomi ve istihdam algısı.** Mezun istihdamına dair haber akışı bile birkaç yıl içinde bir bölümün talebini görünür şekilde değiştirir — son yıllarda kimi mühendisliklerde ve sağlık programlarında bunun örnekleri yaşandı.
+
+## Trend nasıl okunur?
+
+Tek yılın tabanı **fotoğraf**, dört yılın tabanı **film**dir. Film izle:
+
+- **İstikrarlı taban** (dört yıl üst üste dar bantta): güvenilir referans. Sıralaman tabana yakınsa "dengeli", belirgin gerisindeyse "garanti" davranabilirsin.
+- **Tek yönlü trend** (her yıl sıkılaşıyor): geçen yılın tabanına güvenme; bu yıl daha da sıkılaşacağını varsayıp payla yaklaş. Popüler bölümlerde sık görülür — [Psikoloji](/bolum/psikoloji) ve [Bilgisayar Mühendisliği](/bolum/bilgisayar-muhendisligi) tablolarında 2024-2025 kolonlarını yan yana koyup bak.
+- **Testere dişi** (bir sıkı bir gevşek): sürü etkisi işliyor demektir; ortalamayı referans al, uç yıla değil.
+- **Veri boşluğu** (bazı yıllar "—"): yeni ya da o yıl dolmamış program; belirsizlik yüksek, listende dengeli değil garanti bölgesine koyma, hayal bölgesine koy.
+
+Bölüm sayfalarımızdaki tablolarda 2025 sıralamasının yanında 2024 kolonu ve değişim yönü işareti (▲/▼) tam bu iş için var.
+
+## Listeye nasıl yansıtılır?
+
+1. Her satır için son 4 yılın tabanına bak; tek yıl asla yeterli değil.
+2. Sıkılaşma trendindeki programları bir kademe yukarı say ("dengeli" sandığın aslında "hayal" olabilir).
+3. Gevşeme trendindeki programlara erken sevinme; sürü geri dönebilir.
+4. Belirsizliği [dengeli bir listeyle](/rehber/tercih-listesi-nasil-yapilir) yönet: trend ne yaparsa yapsın, hayal/dengeli/garanti dağılımı düzgün kurulmuş bir liste boşta bırakmaz.
+
+[Tercih robotu](/tercih-robotu) bu analizi senin yerine yapar: sıralamanı girdiğinde programları yalnızca son tabana göre değil, çok yıllı veriyle dilimleyerek gösterir.
diff --git a/content/rehber/tercih-listesi-nasil-yapilir.md b/content/rehber/tercih-listesi-nasil-yapilir.md
new file mode 100644
index 0000000..c157c96
--- /dev/null
+++ b/content/rehber/tercih-listesi-nasil-yapilir.md
@@ -0,0 +1,36 @@
+---
+baslik: YKS Tercih Listesi Nasıl Yapılır? (2026 Rehberi)
+aciklama: 24 tercihlik listeyi dilim dilim kurmanın adım adım yöntemi — hangi tercihi kaçıncı sıraya, neden yazacağını bilerek.
+tarih: 2026-07-25
+---
+
+Tercih listesi kurmanın tek doğru yolu yok; ama boşta bırakan yanlış yolları belli. Bu rehber, ÖSYM'nin tanıdığı 24 tercih hakkını **hayal / dengeli / garanti** mantığıyla nasıl dağıtacağını anlatıyor.
+
+## Önce ölçüyü düzelt: puan değil, sıralama
+
+Tercihin tek sağlam ölçüsü **başarı sıralamandır**. Puanlar her yıl sınavın zorluğuna göre kayar; aynı puan bir yıl 80 bininci, ertesi yıl 120 bininci sıraya denk gelebilir. ÖSYM sonuç belgende her puan türü için ayrı sıralaman yazar — listeyi o satıra göre kur. Bu konunun detayı için [Taban puan mı, başarı sıralaması mı?](/rehber/taban-puan-mi-siralama-mi) yazısına bak.
+
+## Listenin üç bölgesi
+
+**1) Hayal tercihleri (ilk 4-8 sıra).** Taban sıralaması seninkinden *daha iyi* kapatan ama çok istediğin programlar. "Sıralamam yetmez, boşa gider" korkusu yersizdir: bir programı üst sıraya yazmak, alttaki tercihlere yerleşme ihtimalini **azaltmaz**. ÖSYM sistemi yukarıdan aşağı bakar; hayal tutmazsa sıradakine geçer. Tabanlar her yıl oynar — geçen yıl 5 bin kapatmış bir bölüm bu yıl 8 bine gevşeyebilir.
+
+**2) Dengeli tercihler (orta blok, 8-12 sıra).** Taban sıralaması senin sıralamana yakın programlar. Listenin kalbi burasıdır; yerleşme ihtimalinin en yüksek olduğu bölge. Aynı bölümün farklı şehirlerdeki/üniversitelerdeki versiyonlarını sıralama sırasıyla diz.
+
+**3) Garanti tercihleri (son 4-6 sıra).** Taban sıralaması seninkinden belirgin şekilde geniş programlar. Buradaki altın kural: **yerleşsen kayıt yaptırmayacağın hiçbir programı yazma.** Garanti dilimi "razı olacağın en makul seçenek" demektir, "ne olursa olsun bir yere gireyim" demek değil. Kayıt yaptırmayacağın bir yere yerleşirsen hem bir yılın gider hem de ek yerleştirmeye başvuramazsın.
+
+## Sık yapılan hatalar
+
+- **Tek yıla bakmak.** 2025 tabanı tek başına yanıltır; en az son 3-4 yılın trendine bak. Tabanların yıldan yıla nasıl oynadığını [Taban sıralamalar yıldan yıla ne kadar değişir?](/rehber/taban-siralamalar-nasil-degisir) yazısında verilerle gösterdik.
+- **24'ü doldurmak için doldurmak.** Okumayacağın bölümü listeye eklemek hata; 16 gerçekçi tercih, 24 gelişigüzel tercihten iyidir.
+- **"Ölü tercih" yazmak.** Tabanı senin sıralamandan çok daha iyi olan bir programı listenin *sonlarına* yazmak o satırı çöpe atar — üstteki tercihlerinden birine yerleşmişsen oraya sıra zaten gelmez. Detay: [Ölü tercih nedir?](/rehber/olu-tercih-nedir)
+- **Sadece bölüme ya da sadece şehre kilitlenmek.** "Ne olursa olsun [Tıp](/bolum/tip)" diyorsan 24 tercihi de tıp yazabilirsin; ama "mühendislik olsun da hangisi olursa olsun" diyorsan [Bilgisayar Mühendisliği](/bolum/bilgisayar-muhendisligi), [Elektrik-Elektronik Mühendisliği](/bolum/elektrik-elektronik-muhendisligi) gibi yakın bölümleri karışık ve sıralama sırasıyla dizmek daha akıllıca.
+
+## Pratik akış
+
+1. Sıralamanı ve puan türünü not et.
+2. Sıralamana uygun program evrenini çıkar — [tercih robotuna](/tercih-robotu) sıralamanı girerek hayal/dengeli/garanti dilimlerini saniyede görebilirsin.
+3. İstemediklerini ele, kalanları *istek sırana* göre diz (yerleşme ihtimaline göre değil).
+4. Son kontrol: listenin başı hayal mi, ortası dengeli mi, sonu gerçekten garanti mi? Sonunda kayıt yaptırmayacağın program var mı?
+5. ÖSYM AİS'e girerken listeyi bir kez daha kod kod doğrula.
+
+Listeyi kurarken her satırın "neden burada" sorusuna cevabı olmalı. Cevabı yoksa o satır ya yanlış yerde ya da listede fazla.
diff --git a/content/rehber/yks-tercih-takvimi-2026.md b/content/rehber/yks-tercih-takvimi-2026.md
new file mode 100644
index 0000000..b1494b8
--- /dev/null
+++ b/content/rehber/yks-tercih-takvimi-2026.md
@@ -0,0 +1,37 @@
+---
+baslik: YKS 2026 Tercih Takvimi ve Süreç Adımları
+aciklama: Sonuçların açıklanmasından ek yerleştirmeye — 2026 tercih döneminin tüm aşamaları, sıralı ve tek sayfada.
+tarih: 2026-07-20
+---
+
+Tercih dönemi kısa ve her adımı tarihli bir süreçtir. 2026'nın akışı şöyle işliyor (kesin tarihler için tek resmî kaynak ÖSYM duyurularıdır; buradaki çerçeve genel akışı gösterir):
+
+## Sürecin aşamaları
+
+**1) YKS sonuçlarının açıklanması (Temmuz ortası-sonu).**
+ÖSYM sonuç belgende puanların ve her puan türü için **başarı sıralaman** yazar. Tercihte kullanacağın sayı budur — puan değil ([neden olduğunu burada anlattık](/rehber/taban-puan-mi-siralama-mi)).
+
+**2) Tercih kılavuzunun ve kontenjanların yayımlanması.**
+ÖSYM Yükseköğretim Programları ve Kontenjanları Kılavuzu'nu yayımlar; YÖK Atlas verileri güncellenir. Hangi programın kaç kişi alacağı ve geçen yılların tabanları netleşir.
+
+**3) Tercih dönemi (Temmuz sonu — Ağustos başı, ~2 hafta).**
+2026'da tercihler 29 Temmuz - 10 Ağustos arasında alındı. Tercihler ÖSYM AİS (Aday İşlemleri Sistemi) üzerinden girilir; en fazla **24 tercih** hakkın vardır. Liste kurma yöntemi için [tercih listesi rehberine](/rehber/tercih-listesi-nasil-yapilir) bak; sıralamana uygun programları görmek için [tercih robotunu](/tercih-robotu) kullan.
+
+**4) Yerleştirme sonuçlarının açıklanması (Ağustos).**
+Tercih döneminin kapanmasından yaklaşık 2-3 hafta sonra. Sonuçla birlikte her programın o yılki gerçek taban puanı ve sıralaması da netleşir.
+
+**5) Kayıt dönemi (Ağustos sonu — Eylül başı).**
+Yerleştiğin programa e-Devlet üzerinden veya üniversiteye giderek kayıt yaptırırsın. Kayıt süresini kaçırmak hakkın yanması demektir — tarihleri takvimine işaretle.
+
+**6) Ek yerleştirme (Eylül).**
+Boş kalan kontenjanlar için ikinci tur. Kritik kural: ilk yerleştirmede bir programa yerleşen, **kayıt yaptırmasa bile** ek tercihe başvuramaz. Detaylar [ek yerleştirme rehberinde](/rehber/ek-yerlestirme-2026).
+
+## Tercih haftası için pratik plan
+
+- **1. gün:** Sıralamanı doğrula, puan türünü netleştir.
+- **2-3. gün:** Program evrenini çıkar. [Bölüm taban puanları](/bolumler) tablolarında ilgilendiğin bölümlerin son yıllardaki tabanlarını incele; [Psikoloji](/bolum/psikoloji) gibi geniş bölümlerde aralığın ne kadar açıldığını görmek ufuk açar.
+- **4-5. gün:** Taslak listeyi kur: üstte hayal, ortada dengeli, altta gerçekten gideceğin garanti.
+- **6. gün:** Ölü tercih taraması yap ([nasıl yapılır](/rehber/olu-tercih-nedir)), aile onayını al, üniversitelerin özel şartlarını (kılavuz dipnotlarını) oku.
+- **Son gün değil, son günden önce:** AİS'e gir, listeyi kod kod işle, onayla, çıktısını sakla. Sistem son saatlerde yoğunluktan yavaşlar — son güne bırakma.
+
+Tercih dönemi stresli görünür ama takvimi bilen için sadece sıralı bir yapılacaklar listesidir. Adımları sırayla yürü, kararlarını veriyle ver.
diff --git a/data/app.db b/data/app.db
index b775651..7b88dce 100644
Binary files a/data/app.db and b/data/app.db differ
diff --git a/data/yokatlas.db b/data/yokatlas.db
index 9516148..591c0b6 100644
Binary files a/data/yokatlas.db and b/data/yokatlas.db differ
diff --git a/next.config.ts b/next.config.ts
index aacb5a6..4787c8d 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -11,6 +11,8 @@ const nextConfig: NextConfig = {
return [
{ source: "/rapor", destination: "/sonuc", permanent: false },
{ source: "/sohbet", destination: "/listem", permanent: false },
+ // Ayrı robot sayfası kaldırıldı; rehber içi linkler hero formuna düşer.
+ { source: "/tercih-robotu", destination: "/#hero-form", permanent: true },
];
},
};
diff --git a/package.json b/package.json
index 30a33ee..4cfa057 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"remark-gfm": "^4.0.1",
"resend": "^6.18.0",
"shiki": "^4.3.1",
+ "simple-icons": "^16.27.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.6.0",
"turkey-map-react": "^2.0.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4089a0d..c715dc9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -86,6 +86,9 @@ importers:
shiki:
specifier: ^4.3.1
version: 4.3.1
+ simple-icons:
+ specifier: ^16.27.1
+ version: 16.27.1
sonner:
specifier: ^2.0.7
version: 2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -4976,6 +4979,10 @@ packages:
simple-get@4.0.1:
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+ simple-icons@16.27.1:
+ resolution: {integrity: sha512-slZF8iKxkv7Lb9SF3L1AcIl5iYLNvDrKKm8yV69cG66XvxJ12SX+bYTgxRwCY4bXSmklGXoXaKEyVmEypOCeqw==}
+ engines: {node: '>=0.12.18'}
+
sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -10658,6 +10665,8 @@ snapshots:
once: 1.4.0
simple-concat: 1.0.1
+ simple-icons@16.27.1: {}
+
sisteransi@1.0.5: {}
smart-buffer@4.2.0: {}
diff --git a/public/file.svg b/public/file.svg
deleted file mode 100644
index 004145c..0000000
--- a/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/globe.svg b/public/globe.svg
deleted file mode 100644
index 567f17b..0000000
--- a/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index 7705396..0000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/window.svg b/public/window.svg
deleted file mode 100644
index b2b2a44..0000000
--- a/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/scripts/db-index.ts b/scripts/db-index.ts
index ff5252a..0fd6c43 100644
--- a/scripts/db-index.ts
+++ b/scripts/db-index.ts
@@ -17,6 +17,14 @@ db.exec(`
ON programs (tur, onlisans, COALESCE(sira2025, sira2024));
`);
+// Programatik SEO sayfaları (src/lib/katalog.ts) bölüm/üniversite detaylarını
+// ham ada birebir IN (...) eşleşmesiyle çeker; bu iki index olmadan her
+// sayfa tam tablo taraması yapar.
+db.exec(`
+ CREATE INDEX IF NOT EXISTS idx_programs_isim ON programs (isim);
+ CREATE INDEX IF NOT EXISTS idx_programs_universite ON programs (universite);
+`);
+
// Uygulama DB'yi readonly açtığı için checkpoint yapamaz; şişen WAL'i
// (okuma başına ekstra maliyet) burada dosyaya geri yaz ve sıfırla.
db.pragma("wal_checkpoint(TRUNCATE)");
diff --git a/src/app/api/facetler/route.ts b/src/app/api/facetler/route.ts
index ffd2d0a..f353aec 100644
--- a/src/app/api/facetler/route.ts
+++ b/src/app/api/facetler/route.ts
@@ -1,9 +1,17 @@
import { NextResponse, type NextRequest } from "next/server";
-import { PUAN_TURLERI, rankWindowFacets, type PuanTuruKey } from "@/lib/db";
+import {
+ PUAN_TURLERI,
+ dilimAra,
+ rankWindowFacets,
+ type DilimKey,
+ type PuanTuruKey,
+} from "@/lib/db";
+import { KATEGORILER } from "@/lib/kategoriler";
-// Ana sayfadaki sihirbaz modalı için: sıralamaya uygun kategori/il/üniversite
-// tipi facet'leri. /sonuc bu veriyi server component'te doğrudan alır; burada
-// client'tan sıra girildikten sonra çekilir.
+// Sihirbaz modalı için: sıralamaya uygun kategori/il/üniversite tipi
+// facet'leri. Kademeli filtre: `kategori` (tekrarlı) il adımını,
+// `kategori` + `il` (tekrarlı) üniversite tipi adımını süzer — bir önceki
+// adımın seçimi bir sonrakinin seçeneklerini daraltır (bkz. rankWindowFacets).
export function GET(request: NextRequest) {
const { searchParams } = request.nextUrl;
const sira = Number.parseInt(searchParams.get("sira") ?? "", 10);
@@ -18,5 +26,31 @@ export function GET(request: NextRequest) {
);
}
- return NextResponse.json({ facetler: rankWindowFacets(sira, tur) });
+ const kategoriler = [
+ ...new Set(
+ searchParams
+ .getAll("kategori")
+ .filter((k) => (KATEGORILER as readonly string[]).includes(k)),
+ ),
+ ];
+ const iller = [
+ ...new Set(searchParams.getAll("il").filter((i) => i.trim().length > 0)),
+ ].slice(0, 5);
+
+ // ?dilimler=1: /meraklisina'daki canlı dilim şeridi için dilim başına
+ // toplam sayılar da eklenir (limit 0 → yalnızca COUNT çalışır)
+ const dilimToplam =
+ searchParams.get("dilimler") === "1"
+ ? Object.fromEntries(
+ (["hayal", "dengeli", "garanti"] as DilimKey[]).map((d) => [
+ d,
+ dilimAra(sira, tur, d, { limit: 0 }).toplam,
+ ]),
+ )
+ : undefined;
+
+ return NextResponse.json({
+ facetler: rankWindowFacets(sira, tur, { kategoriler, iller }),
+ ...(dilimToplam ? { dilimToplam } : {}),
+ });
}
diff --git a/src/app/api/katalog-ara/route.ts b/src/app/api/katalog-ara/route.ts
new file mode 100644
index 0000000..dd24382
--- /dev/null
+++ b/src/app/api/katalog-ara/route.ts
@@ -0,0 +1,86 @@
+import { NextResponse, type NextRequest } from "next/server";
+import { getAllBolumler, getAllUniversiteler } from "@/lib/katalog";
+import { trBaslikDuzeni } from "@/lib/slug";
+
+const SONUC_SINIRI = 6;
+
+function normalize(metin: string): string {
+ return metin
+ .toLocaleLowerCase("tr-TR")
+ .replace(/ı/g, "i")
+ .replace(/ş/g, "s")
+ .replace(/ğ/g, "g")
+ .replace(/ü/g, "u")
+ .replace(/ö/g, "o")
+ .replace(/ç/g, "c")
+ .replace(/â/g, "a")
+ .replace(/î/g, "i")
+ .replace(/û/g, "u")
+ .normalize("NFKD")
+ .replace(/[̀-ͯ]/g, "");
+}
+
+function eslesmePuani(ad: string, sorgu: string): number {
+ const normalAd = normalize(ad);
+ if (normalAd === sorgu) return 0;
+ if (normalAd.startsWith(sorgu)) return 1;
+ if (normalAd.split(/\s+/).some((kelime) => kelime.startsWith(sorgu))) return 2;
+ return 3;
+}
+
+export function GET(request: NextRequest) {
+ const hamSorgu = request.nextUrl.searchParams.get("q")?.trim() ?? "";
+ const sorgu = normalize(hamSorgu).slice(0, 80);
+
+ if (sorgu.length < 2) {
+ return NextResponse.json({ bolumler: [], universiteler: [] });
+ }
+
+ const bolumler = getAllBolumler()
+ .filter((bolum) => normalize(bolum.ad).includes(sorgu))
+ .sort(
+ (a, b) =>
+ eslesmePuani(a.ad, sorgu) - eslesmePuani(b.ad, sorgu) ||
+ b.programSayisi - a.programSayisi,
+ )
+ .slice(0, SONUC_SINIRI)
+ .map((bolum) => ({
+ href: `/bolum/${bolum.slug}`,
+ ad: bolum.ad,
+ programSayisi: bolum.programSayisi,
+ enIyiSira: bolum.enIyiSira,
+ seviye:
+ bolum.lisans && bolum.onlisans
+ ? "Lisans ve önlisans"
+ : bolum.lisans
+ ? "Lisans"
+ : "Önlisans",
+ }));
+
+ const universiteler = getAllUniversiteler()
+ .filter((universite) => normalize(universite.ad).includes(sorgu))
+ .sort(
+ (a, b) =>
+ eslesmePuani(a.ad, sorgu) - eslesmePuani(b.ad, sorgu) ||
+ b.programSayisi - a.programSayisi,
+ )
+ .slice(0, SONUC_SINIRI)
+ .map((universite) => ({
+ href: `/universite/${universite.slug}`,
+ ad: universite.ad,
+ il: universite.il ? trBaslikDuzeni(universite.il) : null,
+ tur:
+ universite.unitur === "DEVLET"
+ ? "Devlet"
+ : universite.unitur &&
+ ["VAKIF", "VAKIF MYO"].includes(universite.unitur)
+ ? "Vakıf"
+ : universite.unitur
+ ? "KKTC / Yurt dışı"
+ : null,
+ programSayisi: universite.programSayisi,
+ fakulteSayisi: universite.fakulteSayisi,
+ }));
+
+ return NextResponse.json({ bolumler, universiteler });
+}
diff --git a/src/app/api/programlar/route.ts b/src/app/api/programlar/route.ts
new file mode 100644
index 0000000..1d0e348
--- /dev/null
+++ b/src/app/api/programlar/route.ts
@@ -0,0 +1,43 @@
+import { NextResponse, type NextRequest } from "next/server";
+import {
+ PUAN_TURLERI,
+ dilimAra,
+ type DilimKey,
+ type PuanTuruKey,
+} from "@/lib/db";
+
+const SAYFA_BOYU = 20;
+
+const DILIMLER: DilimKey[] = ["hayal", "dengeli", "garanti"];
+
+// Sonuç sayfasındaki ham tablonun "daha fazla göster" sayfalaması: dilim
+// başına SAYFA_BOYU program, yakından uzağa sıralı. İlk sayfa server
+// component'te render edilir (bkz. sonuc/page.tsx); devamı buradan akar.
+export function GET(request: NextRequest) {
+ const { searchParams } = request.nextUrl;
+ const sira = Number.parseInt(searchParams.get("sira") ?? "", 10);
+ const turParam = searchParams.get("tur") ?? "say";
+ const tur: PuanTuruKey =
+ turParam in PUAN_TURLERI ? (turParam as PuanTuruKey) : "say";
+ const dilimParam = searchParams.get("dilim") ?? "";
+ const offset = Number.parseInt(searchParams.get("offset") ?? "0", 10);
+
+ if (!Number.isFinite(sira) || sira < 1 || sira > 4_000_000) {
+ return NextResponse.json(
+ { error: "Geçerli bir sıralama gerekli." },
+ { status: 400 },
+ );
+ }
+ if (!DILIMLER.includes(dilimParam as DilimKey)) {
+ return NextResponse.json({ error: "Geçersiz dilim." }, { status: 400 });
+ }
+ if (!Number.isFinite(offset) || offset < 0 || offset > 100_000) {
+ return NextResponse.json({ error: "Geçersiz offset." }, { status: 400 });
+ }
+
+ const { programlar, toplam } = dilimAra(sira, tur, dilimParam as DilimKey, {
+ limit: SAYFA_BOYU,
+ offset,
+ });
+ return NextResponse.json({ programlar, toplam });
+}
diff --git a/src/app/bolum/[slug]/bolum-icerik.tsx b/src/app/bolum/[slug]/bolum-icerik.tsx
new file mode 100644
index 0000000..9280391
--- /dev/null
+++ b/src/app/bolum/[slug]/bolum-icerik.tsx
@@ -0,0 +1,129 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { ChevronRight } from "lucide-react";
+import { getBolumBySlug, uniSlugFromAd } from "@/lib/katalog";
+import { JsonLd, breadcrumbJsonLd } from "@/lib/seo";
+import { Sayfalama, SAYFA_BOYU } from "@/components/sayfalama";
+import { BolumProgramListesi } from "@/components/bolum-program-listesi";
+
+const sayi = (n: number) => n.toLocaleString("tr-TR");
+
+export function bolumToplamSayfa(programSayisi: number): number {
+ return Math.max(1, Math.ceil(programSayisi / SAYFA_BOYU));
+}
+
+export function bolumSayfaMetadata(slug: string, sayfa: number): Metadata {
+ const bolum = getBolumBySlug(slug);
+ if (!bolum) return {};
+ const { stats } = bolum;
+ if (sayfa > 1) {
+ return {
+ title: `${bolum.ad} Taban Puanları 2026 (Sayfa ${sayfa})`,
+ description: `${bolum.ad} taban puanları ve başarı sıralamaları tablosunun ${sayfa}. sayfası — toplam ${stats.toplam} programın 2025 yerleştirme verileri.`,
+ alternates: { canonical: `/bolum/${slug}/sayfa/${sayfa}` },
+ };
+ }
+ const enIyi =
+ stats.minSira != null
+ ? ` En iyi taban sıralaması ${sayi(stats.minSira)}.`
+ : "";
+ return {
+ title: `${bolum.ad} Taban Puanları ve Başarı Sıralamaları 2026`,
+ description: `${bolum.ad} 2025 yerleştirme verileri: ${stats.toplam} programın taban puanı ve sıralaması, ${stats.devlet} devlet / ${stats.vakif} vakıf.${enIyi} 2026 tercih rehberi.`,
+ alternates: { canonical: `/bolum/${slug}` },
+ };
+}
+
+export function BolumIcerik({ slug, sayfa }: { slug: string; sayfa: number }) {
+ const bolum = getBolumBySlug(slug);
+ if (!bolum) notFound();
+
+ const tumProgramlar = [
+ ...bolum.lisansProgramlari,
+ ...bolum.onlisansProgramlari,
+ ];
+ const toplamSayfa = bolumToplamSayfa(tumProgramlar.length);
+ if (sayfa < 1 || sayfa > toplamSayfa) notFound();
+ const dilim = tumProgramlar.slice(
+ (sayfa - 1) * SAYFA_BOYU,
+ sayfa * SAYFA_BOYU,
+ );
+ const ilkSayfa = sayfa === 1;
+ const buYol = ilkSayfa ? `/bolum/${slug}` : `/bolum/${slug}/sayfa/${sayfa}`;
+
+ return (
+
+
+
+
+
+
+
+ {bolum.ad}
+
+
+ {sayi(tumProgramlar.length)} üniversite programının 2025 taban
+ puanlarını, başarı sıralamalarını ve kontenjanlarını incele
+ {!ilkSayfa ? ` — sayfa ${sayfa}` : ""}.
+
+
+
+
+
+
+ Üniversite programları
+
+
+ {sayi(tumProgramlar.length)} program
+
+
+
+ ({
+ ...program,
+ universiteSlug: uniSlugFromAd(program.universite),
+ }))}
+ bazAd={bolum.ad}
+ />
+
+
+
+
+ );
+}
diff --git a/src/app/bolum/[slug]/page.tsx b/src/app/bolum/[slug]/page.tsx
new file mode 100644
index 0000000..675939e
--- /dev/null
+++ b/src/app/bolum/[slug]/page.tsx
@@ -0,0 +1,28 @@
+import type { Metadata } from "next";
+import { getAllBolumSlugs } from "@/lib/katalog";
+import { BolumIcerik, bolumSayfaMetadata } from "./bolum-icerik";
+
+// Tüm bölümler build sırasında bilinir (veri ancak ingest + deploy ile
+// değişir); bilinmeyen slug getBolumBySlug'dan null dönüp notFound()'a düşer.
+// (dynamicParams cacheComponents ile uyumsuz olduğundan kullanılamıyor.)
+export function generateStaticParams() {
+ return getAllBolumSlugs().map((slug) => ({ slug }));
+}
+
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ slug: string }>;
+}): Promise {
+ const { slug } = await params;
+ return bolumSayfaMetadata(slug, 1);
+}
+
+export default async function BolumPage({
+ params,
+}: {
+ params: Promise<{ slug: string }>;
+}) {
+ const { slug } = await params;
+ return ;
+}
diff --git a/src/app/bolum/[slug]/sayfa/[no]/page.tsx b/src/app/bolum/[slug]/sayfa/[no]/page.tsx
new file mode 100644
index 0000000..d1d6b19
--- /dev/null
+++ b/src/app/bolum/[slug]/sayfa/[no]/page.tsx
@@ -0,0 +1,47 @@
+import type { Metadata } from "next";
+import { notFound } from "next/navigation";
+import { getAllBolumler } from "@/lib/katalog";
+import {
+ BolumIcerik,
+ bolumSayfaMetadata,
+ bolumToplamSayfa,
+} from "../../bolum-icerik";
+
+// Yalnızca 1'den fazla sayfası olan bölümler için 2..N sayfaları üretilir;
+// 1. sayfa taban rota (/bolum/[slug]) olduğundan burada üretilmez.
+export function generateStaticParams() {
+ return getAllBolumler().flatMap((b) => {
+ const toplam = bolumToplamSayfa(b.programSayisi);
+ return Array.from({ length: Math.max(0, toplam - 1) }, (_, i) => ({
+ slug: b.slug,
+ no: String(i + 2),
+ }));
+ });
+}
+
+function sayfaNo(no: string): number | null {
+ const n = Number(no);
+ return Number.isInteger(n) && n >= 2 ? n : null;
+}
+
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ slug: string; no: string }>;
+}): Promise {
+ const { slug, no } = await params;
+ const n = sayfaNo(no);
+ if (n == null) return {};
+ return bolumSayfaMetadata(slug, n);
+}
+
+export default async function BolumSayfaPage({
+ params,
+}: {
+ params: Promise<{ slug: string; no: string }>;
+}) {
+ const { slug, no } = await params;
+ const n = sayfaNo(no);
+ if (n == null) notFound();
+ return ;
+}
diff --git a/src/app/bolumler/page.tsx b/src/app/bolumler/page.tsx
new file mode 100644
index 0000000..813dba7
--- /dev/null
+++ b/src/app/bolumler/page.tsx
@@ -0,0 +1,123 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { getAllBolumler, type BolumOzet } from "@/lib/katalog";
+import { KATEGORILER } from "@/lib/kategoriler";
+import { JsonLd, breadcrumbJsonLd } from "@/lib/seo";
+import { CtaSiraForm } from "@/components/cta-sira-form";
+import { SiteFooter } from "@/components/site-footer";
+import { PagePixelDivider } from "@/components/pixel-decor";
+
+export const metadata: Metadata = {
+ title: "Tüm Bölümlerin Taban Puanları ve Sıralamaları 2026",
+ description:
+ "Üniversite bölümlerinin 2025 yerleştirme taban puanları ve başarı sıralamaları: lisans ve önlisans programları kategori kategori, 2026 tercihleri için.",
+ alternates: { canonical: "/bolumler" },
+};
+
+const sayi = (n: number) => n.toLocaleString("tr-TR");
+
+function BolumLinkleri({ bolumler }: { bolumler: BolumOzet[] }) {
+ return (
+
+ Seçimlerinden geriye kalan{" "}
+
+ {havuz.toLocaleString("tr-TR")} programlık havuz
+ {" "}
+ yapay zekâya gider; o da bu havuzdan tam 24 tercih seçer ve şu iskelete
+ oturtur:
+
+
+ {/* 24 hücrelik liste şeridi — renk + metin birlikte (renk tek başına
+ anlam taşımaz) */}
+
+ · Havuzda olmayan bir bölümü yazamaz — listedeki her satırın kimliği
+ havuzla karşılaştırılır, uymayan liste yeniden ürettirilir.
+
+
+ · Her satıra tek cümlelik gerekçe ve bir risk notu ekler; sıraya neyi
+ neden koyduğu görünür.
+
+
+ · Önceliklerin (iş garantisi, maaş, prestij…) hangi programın öne
+ geçeceğini belirler.
+
+
+ · Havuz 24'ün altına düşerse filtreler adım adım gevşetilir —
+ önce il, sonra alan — ve bu, listende açıkça belirtilir.
+
+
+
+ {dar ? (
+
+ Bu seçimle havuz 24'ün altına düştü. Gerçek sihirbaz bu durumda
+ filtreleri adım adım gevşetir — önce il, sonra alan tercihi esnetilir
+ — ve bunu listende açıkça belirtir; liste her zaman 24'e
+ tamamlanır.
+
+ );
+}
diff --git a/src/app/meraklisina/page.tsx b/src/app/meraklisina/page.tsx
new file mode 100644
index 0000000..27af064
--- /dev/null
+++ b/src/app/meraklisina/page.tsx
@@ -0,0 +1,189 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { ArrowRight } from "lucide-react";
+import { Parallax } from "@/components/parallax";
+import { PagePixelDivider } from "@/components/pixel-decor";
+import { dilimAra, rankWindowFacets, type DilimKey } from "@/lib/db";
+import {
+ DemoKumanda,
+ DilimSeridiCanli,
+ HuniCanli,
+ SiralamaDemo,
+ type DemoVeri,
+} from "./demo";
+
+export const metadata: Metadata = {
+ title: "Meraklısına: KolayTercih nasıl çalışır?",
+ alternates: { canonical: "/meraklisina" },
+ description:
+ "Sıralamanı girdiğinde arka planda ne oluyor? Dilimler, risk renkleri ve sihirbazın adım adım daralan filtreleri — öğrenci diliyle, kendi sıralamanla deneyebileceğin canlı görsellerle.",
+};
+
+/**
+ * Algoritmanın öğrenci diline çevrilmiş anlatımı. Teknik detay (SQL, çarpan
+ * mutfağı) bilerek verilmez; amaç güven: veri gerçek, kurallar şeffaf.
+ * Görseller canlıdır: kullanıcı sıralamasını girer, dilim şeridi ve filtre
+ * hunisi o sıralamanın gerçek sayılarıyla güncellenir (bkz. demo.tsx).
+ * Diyagramlar ürünün risk renk dilini kullanır (yeşil/sarı/kırmızı) ve her
+ * bölge metinle de etiketlenir — renk tek başına anlam taşımaz.
+ */
+
+// Demo ilk açılışta bu sıralamayla dolu gelir; SSR'da gerçek veriyle render
+// edilir ki kullanıcı girmeden de sayfa anlamlı olsun.
+const VARSAYILAN_SIRA = 100_000;
+
+export default function MeraklisinaPage() {
+ const dilimToplam = Object.fromEntries(
+ (["hayal", "dengeli", "garanti"] as DilimKey[]).map((d) => [
+ d,
+ dilimAra(VARSAYILAN_SIRA, "say", d, { limit: 0 }).toplam,
+ ]),
+ ) as Record;
+ const baslangicVeri: DemoVeri = {
+ facetler: rankWindowFacets(VARSAYILAN_SIRA, "say"),
+ dilimToplam,
+ };
+
+ return (
+
+
+
+ Meraklısına
+
+
+ Sıralamanı girince arka planda ne oluyor?
+
+
+ Sihir yok, kara kutu yok: KolayTercih'in önerdiği her satır resmî
+ YÖK Atlas verisinden gelir ve hangi kurala göre önüne geldiği bellidir.
+ Bu sayfa o kuralları öğrenci diliyle anlatır — üstelik görseller
+ canlı: kendi sıralamanı gir, sayılar sana göre değişsin.
+
+
+
+
+
+
+
+
+
+ 1. Her şey taban sıralamasıyla başlar
+
+
+ Bir bölümün taban sıralaması, geçen yıl o bölüme
+ yerleşen son{" "}
+ öğrencinin Türkiye sıralamasıdır. Senin sıralaman bu sayıdan
+ küçükse (yani daha iyiysen), geçen yılın koşullarında o bölüme
+ yerleşebilirdin demektir. Sistemde her programın en güncel taban
+ sıralaması kayıtlıdır; bir bölümün 2025 verisi henüz oluşmamışsa
+ bir önceki yılınki kullanılır.
+
+
+
+
+
+
+
+ 2. Programlar üç dilime ayrılır
+
+
+ Sıralamanı girdiğinde tüm programlar senin konumuna göre üç kümeye
+ ayrılır: tabanı senden daha iyi olanlar{" "}
+ Hayal (şansını
+ denediğin satırlar), tabanı sıralamana{" "}
+ yakın olanlar{" "}
+ Dengeli{" "}
+ (listenin bel kemiği — sıralamanın yaklaşık yüzde kırk fazlasına
+ kadar pay bırakılır), tabanı{" "}
+ belirgin şekilde altında kalan her şey ise{" "}
+ Garanti{" "}
+ dilimidir.
+
+
+
+ Garanti diliminin bir sonu yok: 87. sıradaki bir adayın da 500
+ bininci sıradaki bir adayın da ulaşabildiği bütün{" "}
+ programlar listededir. Liste sana en yakın tabandan başlar; aşağı
+ indikçe ve “Daha fazla göster”e bastıkça senden
+ uzaklaşan seçenekler gelir. Böylece ilk gördüklerin her zaman en
+ isabetli adaylardır ama hiçbir seçenek senden saklanmaz.
+
+
+
+
+
+ 3. Risk renkleri her yerde aynı dili konuşur
+
+
+ Tabloda, haritada ve yapay zekâ listesinde gördüğün nokta ve
+ renkler tek bir kurala bağlıdır:{" "}
+ yeşil{" "}
+ tabanı sıralamanın belirgin altında (güvenli),{" "}
+ sarı{" "}
+ sıralamana yakın (az riskli),{" "}
+ kırmızı{" "}
+ tabanı senden iyi (riskli). Renk hangi sayfada olursa olsun aynı
+ hesaptan çıkar; bir satır sekme değiştirdi diye renk değiştirmez.
+
+
+
+
+
+ 4. Sihirbaz süzer, yapay zekâ kurar
+
+
+ “Listemi oluştur” sihirbazındaki üç adım birbirinden
+ bağımsız değildir. İlk adımda yalnızca{" "}
+ sıralamanla ulaşabildiğin{" "}
+ alanlar listelenir; ikinci adımdaki iller, seçtiğin alanlardaki
+ program sayısına göre yeniden hesaplanır; üçüncü adımdaki
+ devlet/vakıf sayıları da hem alan hem il seçimini hesaba katar.
+ Adımlar bitince elde kalan gerçek programlar bir{" "}
+ aday havuzu{" "}
+ olur ve yapay zekâya öyle gider: ona boş bir sayfa değil, bu havuz
+ verilir. Aşağıda kendin dene — her seçimin havuzu nasıl
+ daralttığını ve havuzun 24'lük listeye nasıl dönüştüğünü huni
+ canlı gösterir.
+
+
+
+
+
+
+ 5. Dürüst olalım: bu bir tahmin aracıdır
+
+
+ Tüm bu hesaplar geçen yılların{" "}
+ yerleştirme sonuçlarına dayanır. Kontenjanlar, tercih davranışları
+ ve puanlar her yıl değişir; geçen yıl “garanti”
+ görünen bir bölüm bu yıl dolabilir. Bu yüzden satırlarda son beş
+ yılın taban seyrini de gösteririz — çizgi yukarı tırmanıyorsa
+ bölüm zorlaşıyor demektir. KolayTercih karar destek{" "}
+ aracıdır; listenin son hâli ve sorumluluğu her zaman sana aittir.
+
+
+
+
+
+ Kuralları öğrendin — şimdi kendi sıralamanla dene.
+
+ "—": o yıl için yerleştirme verisi bulunmuyor (yeni açılan
+ veya o yıl yerleşen çıkmayan program). Kaynak: YÖK Atlas 2025
+ yerleştirme sonuçları.
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/app/universiteler/page.tsx b/src/app/universiteler/page.tsx
new file mode 100644
index 0000000..3e65573
--- /dev/null
+++ b/src/app/universiteler/page.tsx
@@ -0,0 +1,112 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { getAllUniversiteler, type UniOzet } from "@/lib/katalog";
+import { trBaslikDuzeni } from "@/lib/slug";
+import { JsonLd, breadcrumbJsonLd } from "@/lib/seo";
+import { CtaSiraForm } from "@/components/cta-sira-form";
+import { SiteFooter } from "@/components/site-footer";
+import { PagePixelDivider } from "@/components/pixel-decor";
+
+export const metadata: Metadata = {
+ title: "Üniversitelerin Taban Puanları ve Sıralamaları 2026",
+ description:
+ "Devlet ve vakıf üniversitelerinin 2025 yerleştirme taban puanları, başarı sıralamaları ve kontenjanları — üniversite üniversite, 2026 tercihleri için.",
+ alternates: { canonical: "/universiteler" },
+};
+
+const sayi = (n: number) => n.toLocaleString("tr-TR");
+
+function UniLinkleri({ uniler }: { uniler: UniOzet[] }) {
+ return (
+
+ );
+}
diff --git a/src/components/sayfalama.tsx b/src/components/sayfalama.tsx
new file mode 100644
index 0000000..0b82e45
--- /dev/null
+++ b/src/components/sayfalama.tsx
@@ -0,0 +1,98 @@
+import Link from "next/link";
+import { ChevronLeft, ChevronRight } from "lucide-react";
+
+/** Programatik tablo sayfaları için satır dilimi boyutu. */
+export const SAYFA_BOYU = 50;
+
+/**
+ * Statik path tabanlı sayfalama navigasyonu. 1. sayfa taban URL'in
+ * kendisidir (/bolum/x), sonrakiler /bolum/x/sayfa/2 ... — hepsi gerçek
+ * , Google her sayfayı ayrı statik URL olarak tarar.
+ */
+export function Sayfalama({
+ tabanYol,
+ sayfa,
+ toplamSayfa,
+ sorgu,
+}: {
+ tabanYol: string;
+ sayfa: number;
+ toplamSayfa: number;
+ sorgu?: string;
+}) {
+ if (toplamSayfa <= 1) return null;
+ const yol = (n: number) => {
+ const path = n === 1 ? tabanYol : `${tabanYol}/sayfa/${n}`;
+ return sorgu ? `${path}?${sorgu}` : path;
+ };
+
+ // 7'den çok sayfada pencere: 1 … (c-1) c (c+1) … son
+ const numaralar: (number | "...")[] = [];
+ if (toplamSayfa <= 7) {
+ for (let n = 1; n <= toplamSayfa; n++) numaralar.push(n);
+ } else {
+ numaralar.push(1);
+ if (sayfa > 3) numaralar.push("...");
+ for (
+ let n = Math.max(2, sayfa - 1);
+ n <= Math.min(toplamSayfa - 1, sayfa + 1);
+ n++
+ ) {
+ numaralar.push(n);
+ }
+ if (sayfa < toplamSayfa - 2) numaralar.push("...");
+ numaralar.push(toplamSayfa);
+ }
+
+ return (
+
+ );
+}
diff --git a/src/components/sihirbaz-adimlar.tsx b/src/components/sihirbaz-adimlar.tsx
index bcec019..0b370ea 100644
--- a/src/components/sihirbaz-adimlar.tsx
+++ b/src/components/sihirbaz-adimlar.tsx
@@ -3,8 +3,11 @@
// Sihirbazın 3 adımlık seçim gövdesi. Hem ana sayfadaki hero modalında hem de
// /sonuc'taki sihirbaz modalında kullanılır; seçim state'ini kendi tutar,
// tamamlanınca onTamamla(secimler) çağırır.
+//
+// Adımlar kademeli süzülür: 2. adımın illeri seçili kategorilere, 3. adımın
+// üniversite tipi sayıları kategori+il'e göre /api/facetler'den tazelenir.
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { ArrowLeft, ArrowRight, Sparkles, X } from "lucide-react";
import { useReducedMotion } from "motion/react";
import useMeasure from "react-use-measure";
@@ -51,11 +54,15 @@ export function Cip({
const HARITA_ILLERI = new Set(cities.map((c) => normalizeIlAdi(c.name)));
export function SihirbazAdimlar({
+ sira,
+ tur,
facetler,
baslangicSecimler,
sonButonEtiketi,
onTamamla,
}: {
+ sira: number;
+ tur: string;
facetler: SihirbazFacetleri;
baslangicSecimler?: SihirbazSecimleri | null;
sonButonEtiketi: string;
@@ -77,6 +84,45 @@ export function SihirbazAdimlar({
baslangicSecimler?.oncelikler ?? [],
);
+ // Kademeli facet'ler: kategoriler daima ilk yükten gelir; il ve üniversite
+ // tipi sayıları adıma girerken o anki seçimlerle tazelenir. Fetch başarısız
+ // olursa eldeki (daha geniş) liste kalır — sihirbaz asla kilitlenmez.
+ const [canliFacetler, setCanliFacetler] = useState(facetler);
+ const [facetYukleniyor, setFacetYukleniyor] = useState(false);
+ useEffect(() => {
+ if (adim === 0) return;
+ const ctrl = new AbortController();
+ const params = new URLSearchParams({ sira: String(sira), tur });
+ for (const k of kategoriler) params.append("kategori", k);
+ if (adim === 2) for (const i of iller) params.append("il", i);
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- fetch başlangıç işareti
+ setFacetYukleniyor(true);
+ fetch(`/api/facetler?${params}`, { signal: ctrl.signal })
+ .then((res) => (res.ok ? res.json() : null))
+ .then((veri: { facetler: SihirbazFacetleri } | null) => {
+ if (!veri) return;
+ setCanliFacetler((mevcut) => ({
+ ...mevcut,
+ iller: veri.facetler.iller,
+ uniturler: veri.facetler.uniturler,
+ }));
+ // Seçili tip daralan filtrede yoksa (ör. seçilen ilde vakıf kalmadı)
+ // görünmez bir seçim bırakma
+ setUniversiteTipi((tip) =>
+ tip !== "farketmez" &&
+ !veri.facetler.uniturler.some((u) => u.grup === tip)
+ ? "farketmez"
+ : tip,
+ );
+ })
+ .catch(() => {})
+ .finally(() => setFacetYukleniyor(false));
+ return () => ctrl.abort();
+ // Seçimler yalnızca önceki adımlarda değişebildiği için adım geçişinde
+ // okumak yeterli; her çip tıklamasında istek atmayalım.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [adim]);
+
function listeDegistir(
liste: string[],
setListe: (v: string[]) => void,
@@ -198,10 +244,14 @@ export function SihirbazAdimlar({
{/* Çipler birincil seçim yolu (haritadaki küçük iller mobilde
- güvenilir dokunma hedefi değil); tüm iller program sayısına
- göre sıralı listelenir. */}
-
- {[...facetler.iller]
+ güvenilir dokunma hedefi değil); iller seçili kategorilere göre
+ süzülmüş, program sayısına göre sıralı listelenir. */}
+