Files
kolaytercih/docs/gece-vardiyasi/2026-09-21/10-marka-seo-tur2.md
bilalgursen 0ab4dbe88c
All checks were successful
Deploy / deploy (push) Successful in 7m18s
Enhance Traefik configuration for www.kolaytercih.com
Added a new router and middleware for handling www to apex domain redirection, ensuring that Let's Encrypt certificates are obtained for both domains. Updated the docker-compose.yml file to include necessary rules and middleware for proper redirection and TLS handling.

Also, updated the CEO agent description to remove redundant details and clarified the QA engineer's responsibilities regarding testing critical flows and error reporting. Adjusted the CTO agent's section for consistency in expert guidance and clarified the designer's tools to include 'Skill' for better design resource management.
2026-09-21 20:37:12 +03:00

34 KiB
Raw Blame History

10 — Marka + SEO, Tur 2 — 2026-09-21 gece vardiyası

Hazırlayan: Marka + SEO ajanı · Girdi: 05-ceo-kararlari.md §7 (soru 4 ve 5), 03-marka-stratejisi.md, 02-seo-geo-konu-plani.md · Yöntem: yalnızca kod okuma (main @ 56925e1), lokal .next build çıktısı (BUILD_ID 21 Eyl 00:42) ve data/*.db dosyalarının salt-okunur (immutable=1) sorgusu. Kod/içerik değiştirilmedi. Satır numaraları main içindir; gece/p3-vaat-dili page.tsx ve rapor.ts satırlarını kaydırır.

Özet (5 madde)

  1. "Garanti" envanteri CEO'nun tahmin ettiği ~10 dosya değil, ~33 dosya: src/ içinde 13 dosyada görünen metin/prompt (≈30 satır), content/rehber/ içinde 19 yazıda dilim anlamında ≈40 geçiş (4 şema düğümü + 3 %% aria + 1 %% altyazi dahil), + AGENTS.md. OG görselleri, e-posta şablonları (src/lib/eposta.ts) ve public/ temiz (0 geçiş; llms.txt yok).
  2. "Etiket değişir, tanımlayıcı kalır" stratejisi uygulanabilir, ama etiket tek sözlükten gelmiyor: aynı etiket 3 ayrı sabitte (rapor-listesi.tsx:38, rapor-yazdir.tsx:10, program-tablosu.tsx:44) + 1 union tipte (tercih-degerlendirme.ts:14 "Daha güvenli") + elle yazılmış JSX/SVG metinlerinde duruyor. sohbet-client.tsx:111 ise zaten "Güvenli dilimden…" diyor (beşinci sözlük). Yeniden adlandırmadan önce tek DILIM_ETIKET kaynağı açılmalı. DB göçü gerekmez (drizzle migration'larında CHECK yok).
  3. İki tuzak: (a) etiket "Güvenli" olunca rapor-listesi.tsx:83 "Güvenli · Güvenli", rapor-yazdir.tsx:13 "Güvenli (Güvenli)" üretir — dilim ve risk etiketi çakışır, küçük bir gösterim kararı gerekir; (b) LLM'e dilim adı ham anahtarla gidiyor (rapor.ts:62,68, listeOzetiCikar → [garanti | Güvenli]), bu yüzden serbest metinde "garanti dilimi" geri sızıyor — lokal DB'de 2 rapordan 1'inin genelDegerlendirme ve uyarilar alanında, 2 sohbet mesajında kelime var. Prompt'a sözlük satırı eklenmeden UI temizliği yarım kalır.
  4. Sayfalama için tek öneri: mevcut "kendine canonical + index" KALSIN; 1. sayfaya canonical VERİLMESİN; başlık/açıklama/H1 içerikle farklılaştırılsın. Kanıt: 363 derin üniversite sayfası (180/229 üniversite) + 304 derin bölüm sayfası (132/635 bölüm) var; program detay sayfası yok; 1. sayfa HTML'i derin sayfadaki programları içermiyor; programların ~%53'ü üniversite tarafında yalnızca derin sayfada listeleniyor. Google'ın sayfalama rehberi de "ilk sayfayı canonical yapma" diyor.
  5. Katalog köprüsünde bugünkü metin marka yasağını deliyor: universite-icerik.tsx:303 "…programlarına yerleşir misin?", cta-sira-form.tsx:143,164,194,204 "nereye yerleşirsin?". Ayrıca /bolum/[slug] sayfasında hiç CTA yok, üniversite sayfasında CTA tablonun ve sayfalamanın altında (ilk ekranda değil). Aşağıda vaat içermeyen 3 varyant var.

A. "Garanti → Güvenli" eksiksiz envanter

Arama: grep -rniI "garant" → src/ scripts/ public/ content/ toplam 193 satır, 56 dosya. Aşağıda sınıflandırılmış hâli. Sütun "Değişir mi?": evet / hayır-iç (iç tanımlayıcı) / hayır-anlam (dilim dışı anlam, marka vaadinin kendisi) / dikkat-DB (kayıtlı değer).

A1. src/ — kullanıcıya görünen dilim etiketi ve anlatım (DEĞİŞİR)

dosya:satır görünen metin tür değişir mi?
src/features/rapor/components/rapor-listesi.tsx:41 garanti: "Garanti" (DILIM_ETIKET; satır detayı başlığı :83 ve tadımlık satırı bunu kullanır) UI etiketi (sözlük 1) evet → "Güvenli" · dikkat: :83 {DILIM_ETIKET[dilim]} · {RISK_ETIKET[risk]} → "Güvenli · Güvenli" olur
src/features/rapor/components/rapor-listesi.tsx:348 "…{n} dengeli · {n} garanti olarak kuruldu." açıklama metni evet
src/features/rapor/components/rapor-yazdir.tsx:13 garanti: "Garanti (Güvenli)" (DILIM_LABEL, PDF/yazdır tablosu :94) UI etiketi (sözlük 2) evet → "Güvenli" (parantez düşer; "Güvenli (Güvenli)" olmasın)
src/features/rapor/components/rapor-yazdir.tsx:53 "…{n} garanti olarak kuruldu." açıklama metni evet
src/features/liste/components/program-tablosu.tsx:68 etiket: "Garanti" (/sonuc dilim sekmesi) UI etiketi (sözlük 3) evet
src/features/pazarlama/components/meraklisina-demo.tsx:149 aria-label: "…Garanti diliminde {n} program var." UI / erişilebilirlik evet
src/features/pazarlama/components/meraklisina-demo.tsx:207 SVG <text> "Garanti" UI etiketi (elle yazılmış) evet
src/features/pazarlama/components/meraklisina-icerik.tsx:71 <span …emerald>Garanti</span> dilimidir açıklama metni evet
src/features/pazarlama/components/meraklisina-icerik.tsx:76 "Garanti diliminin bir sonu yok: …" açıklama metni evet
src/features/pazarlama/components/meraklisina-icerik.tsx:134 "geçen yıl “garanti” görünen bir bölüm bu yıl dolabilir" açıklama (tırnak içinde halk dili) isteğe bağlı — tırnaklı kullanım marka mesajını destekliyor; tutarlılık için "güvenli görünen" önerilir
src/features/pazarlama/components/huni-semasi.tsx:28 L3("sonda garanti — hedef 6, …") şema düğüm metni (SEMA) evet → "sonda güvenli"
src/features/pazarlama/components/huni-semasi.tsx:45 ariaLabel: "…üstte hayal, ortada dengeli, sonda garanti olacak şekilde…" şema aria evet (aynı commit, AGENTS.md)
src/app/page.tsx:114 SSS: "Hayal, dengeli ve garanti dilimlerine dağıtılmış…" — aynı faqs dizisi :197 faqPageJsonLd(faqs) ile FAQPage JSON-LD'ye de gidiyor, tek düzeltme ikisini de günceller açıklama metni + yapılandırılmış veri evet
src/app/page.tsx:132 (ikinci geçiş) "…listeyi hayal/dengeli/garanti dilimleriyle kurarak…" açıklama metni evet
src/features/sihirbaz/components/cta-sira-form.tsx:147 "…hayal, dengeli ve garanti dilimlerindeki programların hazır." açıklama metni evet
src/features/sihirbaz/components/cta-sira-form.tsx:168 "…hayal, dengeli ve garanti dilimlerindeki programları anında listele." açıklama metni evet
src/features/sihirbaz/components/cta-sira-form.tsx:213 "…hayal, dengeli ve garanti dilimlerindeki programları bu sayfadan ayrılmadan gör." açıklama metni evet
src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx:309 "…hayal, dengeli ve garanti dilimlerine dağıtılmış 24 tercihi…" açıklama metni evet
src/features/rapor/components/revizyon-kutusu.tsx:79 placeholder: "…garanti dilimini genişlet…" UI (placeholder) evet
src/lib/ai/rapor.ts:434 yedek genelDegerlendirme: "…hayal, dengeli ve garanti dilimleri sıralamana göre dengelendi." (kullanıcıya gösterilir ve DB'ye yazılır) açıklama metni evet
src/lib/ai/rapor.ts:237,242 dev-mock metni ("hayal/dengeli/garanti dağılımlı", "Garanti dilimindeki son tercihleri…") yalnız dev'de görünür evet (düşük öncelik)

Sözlük birleştirme için "garanti" içermeyen ama aynı commit'e girmesi gereken satırlar (03-G1): src/features/liste/components/secimlerim-paneli.tsx:161 (etiket="Daha güvenli"), src/lib/tercih-degerlendirme.ts:14,72 ("Daha güvenli" union + değer; :60,80,114 cümle içi "daha güvenli" sıfat olarak kalabilir). sohbet-client.tsx:111 zaten "Güvenli dilimden" diyor — dokunulmaz, yeni sözlükle uyumlu.

A2. LLM prompt'ları

dosya:satır metin tür değişir mi?
src/lib/ai/rapor.ts:62 "…üç listeyi doldurmak: hayal (…), dengeli (…), garanti (…)" prompt (JSON alan adı) alan adı kalır (zod şeması :41,51 anahtarı garanti); prompt'a sözlük satırı eklenir
src/lib/ai/rapor.ts:68 "…dengeli ve garanti için de aynısı." prompt kalır (alan adı)
src/lib/ai/rapor.ts:73 ASLA "garanti", "kesin", "yüzde yüz" deme — yalnızca gerekce maddesinin içinde prompt (yasak) genişletilir: yasak genelDegerlendirme ve uyarilar için de geçerli olmalı + "üçüncü dilimi kullanıcıya 'güvenli' diye an"
src/lib/ai/rapor.ts:338,351 yeniden deneme geri bildirimi: "…garanti ${n} olmalı" prompt (LLM'e gider, kullanıcı görmez) hayır-iç
src/lib/ai/rapor.ts:452 listeOzetiCikar: [${t.dilim} | ${RISK_ETIKET}] → sohbet modeline [garanti | Güvenli] prompt verisi evet — ham anahtar yerine etiket sözlüğü kullanılmalı; yoksa sohbet cevaplarında "garanti dilimi" sızar
src/app/api/soru/route.ts:48 "ASLA yerleşme garantisi verme; …" prompt (yasak, vaat anlamı) hayır-anlam · not: devamındaki "yüksek/orta/düşük ihtimal dili kullan" 03-G3 ile çelişiyor (bu envanterin konusu değil, P3 kapsamına not)
scripts/tadimlik-uret.ts:70 ASLA "garanti", "kesin", "yüzde yüz" deme; "yüksek/orta/düşük ihtimal"… prompt (yasak) hayır-anlam · aynı "ihtimal" notu; ayrıca :73 "son 4 yılın" → 5 yıl (P3 notu)
src/lib/ai/client.ts:53 SORUMLULUK_REDDI: "…yerleşme garantisi verilmez." açıklama (vaat reddi) hayır-anlam

A3. Dilim dışı anlamlar — DEĞİŞMEZ (markanın ana cümlesi ya da başka kavram)

dosya:satır metin not
src/app/page.tsx:130 "Yerleşme garantisi veriyor musunuz?" vaat reddi — kalır
src/app/page.tsx:132 (ilk geçiş) "…kimse garanti veremez." kalır
src/app/page.tsx:388 "Yerleşme garantisi vermiyoruz — çünkü kimse veremez." markanın ana cümlesi — kalır
src/app/paket/page.tsx:63 "…yerleşme garantisi verilmez." kalır
src/app/kosullar/page.tsx:43 "…garantisi vermez ve ÖSYM ya da YÖK ile bağlantılı değildir." hukuki metin — kalır
src/app/sonuc/page.tsx:130 "…yerleşme garantisi vermez…" kalır
src/components/site-footer.tsx:133 "…yerleşme garantisi vermez." kalır
src/features/kullanici/components/giris-karti.tsx:85 "KolayTercih yerleşme garantisi vermez." kalır
src/features/rapor/components/rapor-yazdir.tsx:109 "…garantisi vermez." kalır
src/features/sihirbaz/sihirbaz-sabitler.ts:11 "İş garantisi" (sihirbaz öncelik çipi; sihirbaz-adimlar.tsx render eder) ayrı karar: dilimle ilgisiz ama "garanti" kelimesini UI'da tutan tek aksiyon etiketi. Öneri: "İş bulma kolaylığı". dikkat-DB: öncelikler düz metin dizisi olarak saklanıyor (rapor.ts tipi :65 oncelikler?: string[]; kod eşleşmesi metinle yapılıyor, ör. tercih-degerlendirme.ts:58 includes("Kolay yerleşme")). "İş garantisi" metniyle eşleşen kod yok → değiştirmek güvenli; eski kayıtlar eski metni taşır (lokal DB'de 0 kayıt)
"ödeme garantisi / iade garantisi" — kodda yok (0 geçiş). Ödeme tarafında yalnızca "iyzico güvenli ödeme" var (paket-satinal.tsx:114,120, odeme-sayfasi.tsx:36,86, site-footer.tsx:163, listem-govde.tsx:378, page.tsx:542, odeme/page.tsx:10). Yeniden adlandırma sonrası "Güvenli" kelimesi hem dilim hem ödeme bağlamında geçecek; aynı ekranda yan yana gelmiyorlar (dilim: /sonuc, /listem tablo; ödeme: /paket, /odeme) — kabul edilebilir, listem-govde.tsx:378 tek yakın temas noktası

A4. Kod tanımlayıcıları / enum / DB değerleri — AYRI LİSTE (DEĞİŞMEZ)

dosya:satır tanımlayıcı tür
src/types/yokatlas.ts:34,39,54 DilimKey = "hayal" | "dengeli" | "garanti", garanti: Program[] union tipi / alan
src/lib/rapor-havuzu.ts:12,29,30,35,40,47,50,51,74,81,86 Dilim tipi, IDEAL_HEDEF.garanti, sayaçlar tip / sabit
src/lib/risk.ts:25,41 dilim === "garanti" → "guvenli" karşılaştırma (eski raporlar için köprü)
src/lib/db.ts:41,52,69,147,152,156,179 dilimAra(..., "garanti"), yorumlar sorgu parametresi
src/lib/ai/rapor.ts:28,41,51,59,90,94,114,117,204,215,266,363,374,382,412 zod şema anahtarı, DILIMLER, log satırı şema / kod
src/app/api/programlar/route.ts:12, src/app/api/facetler/route.ts:44, src/features/pazarlama/pazarlama-queries.ts:13 ["hayal","dengeli","garanti"] · /api/programlar?dilim=garanti sorgu parametresi API sözleşmesi (kullanıcı görmez)
src/features/liste/components/program-tablosu.tsx:67,84,88,91,127,128, src/features/liste/liste-queries.ts:34,52 key: "garanti", varsayılan sekme durum anahtarı
src/features/pazarlama/components/meraklisina-demo.tsx:204,210, rapor-listesi.tsx:348/rapor-yazdir.tsx:53 içindeki dagilim.garanti alan erişimi kod
src/features/pazarlama/components/huni-semasi.tsx:34,39 + 24 rehber yazısının tamamında classDef garanti … / class X garanti mermaid classDef adı (renk sınıfı; CEO §2 "yalnızca iç anahtar") şema iç anahtarı — render edilmez
scripts/tadimlik-uret.ts:106,115 ["dengeli","garanti"] kod
src/lib/appdb/schema.ts:185 tadimlik_havuzu.dilim enum ["hayal","dengeli","garanti"] dikkat-DB
reports.result JSON (schema.ts:160) tercihler[].dilim: "garanti", kapsam.dagilim.garanti dikkat-DB (kayıtlı JSON)
ilgisiz fiil kullanımı: tercih-profili-kapisi.tsx:205, use-tercih-profili.ts:276, scripts/refresh.ts:125, page.tsx:355 "garanti edilir" (kod yorumu) yorum — kullanıcı görmez

DB kanıtı (lokal data/app.db, salt-okunur): tadimlik_havuzu 514 satır → dilim='garanti' 86, 'dengeli' 428. reports 2 kayıt → 2'sinde "dilim":"garanti" anahtarı; 1'inde LLM'in yazdığı genelDegerlendirme ve uyarilar serbest metninde "garanti" kelimesi. chat_messages içinde 2 mesajda kelime geçiyor. tadimlik_havuzu metin alanlarında 3/514 satırda geçiyor. drizzle/*.sql içinde "garanti" yok → SQLite tarafında CHECK kısıtı yok, enum yalnızca TypeScript düzeyinde. Prod sayıları bilinmiyor (prod'a erişim yasak).

A5. "UI etiketi değişir, tanımlayıcı kalır" — koddan değerlendirme

Uygulanabilir: evet. Ham "garanti" anahtarı kullanıcıya hiçbir yerde doğrudan basılmıyor; her render noktası bir etiket sözlüğünden ya da elle yazılmış metinden geçiyor. risk.ts:41 eski raporları (dilim === "garanti") zaten guvenli riskine çeviriyor; anahtar kaldığı için kayıtlı raporlar, tadımlık havuzu ve API sözleşmesi bozulmaz, migration gerekmez.

Ama etiket dağınık: tek sözlük yok. Aynı bilgi 3 sabitte + 1 union tipte + 2 elle yazılmış JSX/SVG'de + ~10 düzyazı cümlede tekrar ediyor. Önerilen uygulama sırası (tek PR içinde):

  1. src/lib/risk.ts içinde (RISK_ETIKET'in yanında) tek DILIM_ETIKET: Record<Dilim, string> aç; rapor-listesi.tsx:38, rapor-yazdir.tsx:10, program-tablosu.tsx:44-73, meraklisina-demo.tsx:207, listeOzetiCikar (rapor.ts:452) buradan okusun. (rapor-listesi.tsx'teki mevcut export başka yerde import edilmiyor — grep DILIM_ETIKET tek dosya.)
  2. Çakışma kararı (Bilal'in gözü gerekir): dilim etiketi = risk etiketi olunca başlık "Güvenli · Güvenli" olur. Öneri: satır detayında risk etiketi yalnızca dilimin varsayılan riskinden farklıysa gösterilsin (dilimdenRisk(dilim) !== risk); yazdır tablosunda "Hayal (Riskli) / Dengeli (Az riskli) / Güvenli". Eşikler aynı olduğu için (risk.ts:25 yorumu) pratikte tek kelime görünür.
  3. Prompt sözlüğü: sistemMetni'ne "JSON alan adı garanti teknik addır; adaya dönük hiçbir metinde 'garanti' kelimesini kullanma, bu dilimi 'güvenli' diye an" satırı; soru/route.ts kurallarına aynı satır.
  4. Düzyazı cümleler (A1 tablosu).

Kalan sızıntı (kabul edilmesi gereken): eski kayıtlı raporların LLM serbest metni (genelDegerlendirme, uyarilar, gerekce) ve sohbet geçmişi "garanti" kelimesini taşımaya devam eder; veri göçü önerilmez (rapor yeniden üretildiğinde kendiliğinden temizlenir). Tadımlık havuzu için prompt değişikliğinden sonra pnpm tadimlik yeniden koşulmalı (zaten hafızadaki "deploy sonrası prod'da koş" notuyla aynı iş).

A6. content/rehber/*.md — dilim anlamında geçişler (DEĞİŞİR; SEO ile eşgüdüm)

Kural (CEO §2 ile aynı): her yazıda ilk geçişte "güvenli (halk arasında 'garanti tercih')", sonrasında "güvenli". "hayal dengeli garanti" arama kalıbı olduğu için pillar yazıda (tercih-listesi-nasil-yapilir) terim açıklama ve ilk paragrafta anılarak korunur, silinmez.

dosya:satır görünen metin tür
ais-tercih-nasil-yapilir-onaylama.md:54 (2 geçiş), :58 "Listenin sonu gerçekten garanti mi?", "hayal/dengeli/garanti dağılımı", "…dilimleriyle çıkar" metin
bolumun-is-imkanini-nasil-arastirirsin.md:71 "hayal–dengeli–garanti dağılımı" metin
ek-yerlestirme-2026.md:52 "dengeli-garanti ağırlıklı, gerçekçi bir liste" metin
kac-siralama-ile-hangi-bolume-girebilirim.md:10 (ilk geçiş) %% aria: "…hayal, dengeli ve garanti dilimlerini tek bakışta…" şema aria
kac-siralama-ile-hangi-bolume-girebilirim.md:16 düğüm: R("Hayal / dengeli / garanti<br/>dilimleri saniyede çıkar") şema düğümü
kac-siralama-ile-hangi-bolume-girebilirim.md:52 "hayal/dengeli/garanti dilimleriyle ayırıp" metin
merkezi-yerlestirme-nasil-calisir.md:34, :47 "dengeli ve garanti tercihlerinin", "razı olacağın garantileri koy" metin
olu-tercih-nedir.md:42 "hayal/dengeli/garanti dilimleriyle etiketlenir" metin
onlisans-mi-lisans-mi.md:48 "hayal/dengeli/garanti dilimleriyle görürsün" metin
ozel-kosullu-programlar.md:72 "hayal–dengeli–garanti dağılımını temel al" metin
siralama-sartlari-2026.md:17 düğüm: L("Gerçekçi satırları<br/>hayal / dengeli / garanti diz") şema düğümü
taban-puan-mi-siralama-mi.md:48 "hayal/dengeli/garanti dilimleriyle gör" metin
taban-siralamalar-nasil-degisir.md:43, :46, :55 "garanti" davranabilirsin, "garanti bölgesine koyma", "hayal/dengeli/garanti dağılımı" metin
tercih-listesi-nasil-yapilir.md:3 frontmatter aciklama: "…hayal, dengeli ve garanti bölgeleri tek şemada" (meta description + OG) meta — terim anılarak korunur
tercih-listesi-nasil-yapilir.md:7 "hayal / dengeli / garanti mantığıyla" metin — "güvenli (halk arasında 'garanti')"
tercih-listesi-nasil-yapilir.md:16 %% aria: "Son 4-6 satır garanti tercihler…" şema aria
tercih-listesi-nasil-yapilir.md:17 %% altyazi: "…altta garanti (yeşil)…" şema altyazı
tercih-listesi-nasil-yapilir.md:21 düğüm: G("Garanti · son 4-6 satır<br/>…") şema düğümü
tercih-listesi-nasil-yapilir.md:40 (2 geçiş), :52, :54 "3) Garanti tercihleri", "Garanti dilimi …demektir", "…dilimlerini saniyede", "sonu gerçekten garanti mi?" metin / H-benzeri başlık
tercih-robotu-nedir-yok-atlas-nasil-kullanilir.md:14, :62 "hayal / dengeli / garanti mantığıyla", "…dilimlerine ayrılmış aday havuzu" metin
tercih-robotu-nedir-yok-atlas-nasil-kullanilir.md:31 %% aria: "…hayal, dengeli ve garanti dilimlerine ayırır…" şema aria
tercih-robotu-nedir-yok-atlas-nasil-kullanilir.md:35 düğüm: C("Robot dilimler:<br/>hayal / dengeli / garanti") şema düğümü
tercih-sonuclari-ne-zaman-2026.md:63 "hayal/dengeli/garanti dilimleriyle görebilirsin" metin
veliler-icin-tercih-rehberi.md:52 "hayal–dengeli–garanti dağılımı" metin
yatay-gecis-cap-yandal.md:79 "hayal, dengeli ve garanti bloklarını" metin
yerlesemedim-ne-yapmaliyim.md:55 "razı olacağın garantiler koymak" metin
yks-tercih-takvimi-2026.md:49 "altta gerçekten gideceğin garanti" metin

Rehberde DEĞİŞMEYEN (dilim dışı / halk dili eleştirisi): bolum-mu-universite-mi-sehir-mi.md:62 ("yatay geçiş… garanti değildir"), devlet-mi-vakif-mi.md:51 ve veliler-icin-tercih-rehberi.md:58 ("garanti olsun" diye yazılan… — eleştirilen halk kullanımı), kac-siralama…md:10 (ikinci geçiş, "Bant pusuladır, garanti değildir") ve :58, obp-nedir-nasil-hesaplanir.md:34 ("garantim olsun"), siralama-sartlari-2026.md:10,45 ("yerleşmeyi garanti etmez"), taban-siralamalar-nasil-degisir.md:3 ("…ben 85 binim, garanti" demeden önce oku), yatay-gecis-cap-yandal.md:12,13,69, yurt-burs-ve-yillik-maliyet.md:47. Bunlar markanın "garanti yoktur" sesini taşıyor — kalmalı.

Yalnızca classDef garanti içeren (dokunulmayacak) yazılar: hazirlik-sinifi-ve-ogretim-dili, universite-kayit-rehberi-2026 (+ yukarıdaki dilim-dışı listesindekiler: bolum-mu…, devlet-mi…, obp…, yurt-burs…).

Henüz main'de olmayan 3 yazı (gece/rehber-yazilari): üçü de kurala uygun yazılmış ("güvenli … halk arasında 'garanti tercih'"). Tek düzeltme: hedef-siralama-nasil-belirlenir.md:83 "…üründe dilimin adı da böyle geçer" cümlesi yeniden adlandırma sonrası yanlış olur → cümle o PR'da silinmeli.

A7. Temiz çıkan kapsam (0 geçiş — kanıt: aynı grep)

17 adet opengraph-image.tsx (rehber OG'si yazı başlığını basıyor; hiçbir baslik alanında "garanti" yok), src/lib/eposta.ts + eposta-gonder.ts, src/lib/og-sayfa.tsx, public/ (metin dosyası yok; llms.txt yok, robots/sitemap koddan üretiliyor), src/lib/seo.tsx JSON-LD üreticileri.

A8. Boyut, PR planı, AGENTS.md gereği

  • Dosya sayısı: src/ 13 (A1+A2: rapor-listesi, rapor-yazdir, program-tablosu, meraklisina-demo, meraklisina-icerik, huni-semasi, page.tsx, cta-sira-form, sihirbaz-cagri-karti, revizyon-kutusu, ai/rapor.ts, api/soru/route.ts, risk.ts) + sözlük birleştirme 2 (secimlerim-paneli, tercih-degerlendirme) + content/rehber 19 (+1 yeni yazı) + AGENTS.md 1 ≈ 35 dosya, ≈75 satır. İsteğe bağlı iç dokümanlar: docs/urun/gamification.md, vizyon.md, prd-kapi1-ucretsiz-funnel.md, docs/tasarim/ux-duzeltmeler.md.
  • Tek PR'da yapılabilir mi: Evet — tip/şema/DB değişikliği yok, iş mekanik. Öneri: tek PR, iki commit: (1) src/ + AGENTS.md, (2) content/rehber/. Böylece içerik commit'i SEO gözden geçirmesi için ayrı okunur. tsc etkisi yalnızca tercih-degerlendirme.ts union değerinde ("Daha güvenli" → "Güvenli"; kullanan yerler grep riskEtiketi ile kapatılmalı).
  • Sıra/çakışma: page.tsx ve ai/rapor.ts P3 ile, content/rehber/* P1 ve gece/rehber-yazilari ile çakışır → bu PR o dallar merge edildikten sonra açılmalı.
  • AGENTS.md gereği aynı commit'te güncellenecekler: huni-semasi.tsx SEMA düğümü :28 + ariaLabel :45 (figcaption'da kelime yok — değişmez) + meraklisina-icerik.tsx:71,76 (dilim anlatımı; 4. bölüm metninde kelime geçmiyor ama şemayla birlikte okunuyor) + meraklisina-demo.tsx:149,207. Davranış değişmediği için şemanın yapısı aynı kalır; risk renk dili (yeşil + metin etiketi) korunur. AGENTS.md:28'in kendisi "hayal/dengeli/garanti dağılımı" diyor → "hayal/dengeli/güvenli" olarak güncellenmeli, yoksa bir sonraki ajan eski sözlüğü geri getirir.
  • Kabul kriteri önerisi: grep -rniI "garant" src content | grep -v "classDef garanti\|class [A-Za-z0-9_,]* garanti" çıktısında yalnızca A3 (vaat reddi + halk dili) ve A4 (tanımlayıcı) satırları kalır.

A9. Katalog ilk ekranı için 3 köprü cümlesi (vaat yok; "yerleşirsin / garanti / olasılık" yok)

Bağlam (koddan): üniversite sayfasında CTA tablonun ve sayfalamanın altında (universite-icerik.tsx:301-305), bölüm sayfasında hiç yok (bolum-icerik.tsx CtaSiraForm import etmiyor). İlk ekran = H1 + giriş paragrafının hemen altı. CTA biçimi AGENTS.md deseni: metin + sonda <ArrowRight className="size-4" aria-hidden />, başta ikon yok; üstüne rozet gerekirse SectionEyebrow. "Son 5 yıl" ifadesi DB ile tutarlı (sira2021…sira2025).

# Köprü cümlesi CTA metni Hitap ettiği niyet
V1 "Bu tablodaki tabanlar geçen yılın sonucu. Sıralamanı yaz; her programın tabanı senin sıranın önünde mi gerisinde mi, satır satır gör." Sıralamamı tabanlarla karşılaştır → "Bu programa sıralamam yeter mi?" — tabloya bakıp kendi sırasıyla kafadan kıyas yapan, tek bir programı yoklayan aday.
V2 "{Üniversite / Bölüm} içinde sıralamana yakın programlar hangileri? Sıralamanı gir, 2025 tabanına göre sana en yakın olanları öne alalım." Sıralamama yakın programları göster → Keşif — üniversiteyi/bölümü seçmiş ama hangi program/şehir varyantının ulaşılabilir olduğunu bilmeyen aday.
V3 "Tek yılın tabanı yanıltabilir. Sıralamanı gir; bu programların son 5 yıldaki taban seyrini ve senin sıran karşısındaki risk seviyesini saklamadan gösterelim." Risk seviyesini satır satır gör → Temkinli aday ve veli — "geçen yıl tutuyordu" güvenine şüpheyle bakan, markanın dürüstlük vaadine en açık kitle.

Not: mevcut başlıklar ("…programlarına yerleşir misin?", "Sıralamanla nereye yerleşirsin?") 03 Ek A yasak listesine takılıyor; köprü yapılırken cta-sira-form.tsx:143,164,194,204 ve universite-icerik.tsx:303 de aynı işte düzeltilmeli. Hangi varyantın kazandığını okumak için P2'nin cta_form_goruntulendi paydası yayında olmalı (CEO §6 sırası doğru).


B. /universite/*/sayfa/N ve /bolum/*/sayfa/N — tek öneri

B1. Koddan mevcut durum

Soru Bulgu Kanıt
Rota nerede? src/app/universite/[slug]/sayfa/[no]/page.tsx, src/app/bolum/[slug]/sayfa/[no]/page.tsx; ikisi de generateStaticParams ile 2..N üretir, no < 2 ya da tamsayı değilse notFound() dosyaların :13-20; içerik features/katalog/components/{universite,bolum}-icerik.tsx
Sayfa boyu / sıra SAYFA_BOYU = 50. Üniversite: fakülte → efektif sıra ASC. Bölüm: efektif sıra ASC (lisans, sonra önlisans) sayfalama.tsx:6, src/lib/katalog.ts:138,364
Kaç sayfa? 363 derin üniversite sayfası (229 üniversitenin 180'i çok sayfalı; en çok 9 sayfa: Medipol, Nişantaşı) + 304 derin bölüm sayfası (635 bölümün 132'si). Toplam 667 URL lokal .next/server/app/{universite,bolum}/*/sayfa/N.html sayımı
Canonical Kendine: path: /universite/${slug}/sayfa/${sayfa} → alternates.canonical universite-icerik.tsx:61, bolum-icerik.tsx:53, seo.tsx:51; build HTML: <link rel="canonical" href="https://kolaytercih.com/universite/istanbul-medipol-universitesi/sayfa/2"/>
Robots index, follow (layout varsayılanı; sayfa özelinde direktif yok). robots.ts yalnızca /api/ engelliyor src/app/layout.tsx:67; build HTML <meta name="robots" content="index, follow"/>
Title / description "{Ad} Taban Puanları 2026 (Sayfa N)" + "…tablosunun N. sayfası — toplam X programın 2025 yerleştirme verileri." — sayfalar arası tek fark sayfa numarası universite-icerik.tsx:59-60, bolum-icerik.tsx:51-52
H1 / giriş Üniversite: "… — Sayfa N" + satır aralığı cümlesi + 1. sayfaya link (:184-187, 261-274). Bölüm: H1 1. sayfayla birebir aynı ("Psikoloji"); fark yalnızca paragraf sonundaki "— sayfa N" (bolum-icerik.tsx:122-129). Bölümün görünür breadcrumb'ında üst bölüm linki de yok (:116-118; JSON-LD'de var) build HTML'de iki sayfanın <h1>'i: Psikoloji / Psikoloji
Sitemap Girmiyor. Yalnızca /bolum/{slug} ve /universite/{slug} src/app/sitemap.ts:31-44
Keşif yolu Sayfalama gerçek <a href> üretir (rel="prev"/"next" anchor niteliğiyle; <link rel> yok). Pencere: 1 … c-1 c c+1 … son sayfalama.tsx:52-60, 63-79
Program detay sayfası var mı? Yok. src/app altında /program/… rotası yok (21 page.tsx listelendi) find src/app -name page.tsx
Derin sayfadaki programa başka nereden ulaşılır? Her program tam iki listede görünür: üniversitesinin sayfası (k. sayfa) ve bölümünün sayfası (j. sayfa). Üniversite satırı → /bolum/{slug} linki (universite-program-tablosu.tsx:71-77); bölüm satırı → /universite/{slug} linki (bolum-program-listesi.tsx:206-211). Linkler 1. sayfaya gider; programın o listede kaçıncı sayfada olduğu bilinmez —
1. sayfa HTML'i derin programları içeriyor mu? Hayır. bolum/psikoloji.html 51 <tr>; 2. sayfadaki üniversite slug'ları (ör. izmir-bakircay-universitesi) 1. sayfa HTML'inde hiç geçmiyor. (Bölüm listesi istemci bileşenine tüm programları prop olarak alıyor ama prerender HTML'ine gömülmüyor.) build HTML karşılaştırması
Ne kadar içerik derinde? Üniversite tarafında programların ≈ %53'ü (ham ada göre 12.538 / 23.610) yalnızca sayfa/2+'da listeleniyor data/yokatlas.db salt-okunur sorgu (slug birleştirmesi nedeniyle yaklaşık)
Sorgu parametreli varyant? Sayfalama'nın sorgu prop'u hiçbir yerde kullanılmıyor; istemci sıralaması URL değiştirmiyor → filtre/sıralama kaynaklı kopya URL riski yok grep "sorgu=" src → 0

B2. Öneri (tek): kendine canonical + index kalsın; canonical→1. sayfa YAPILMASIN; derin sayfaların başlık/açıklama/H1'i sayfanın gerçek içeriğiyle farklılaştırılsın.

Gerekçe:

  1. Google'ın sayfalama rehberi (Search Central, "Pagination, incremental page loading…": developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading) açıkça: her sayfaya benzersiz URL ver, sayfaları sıralı <a href> ile bağla, "ilk sayfayı dizinin canonical'ı olarak kullanma; her sayfaya kendi canonical'ını ver". Kod bugün bu üçünü de yapıyor. (Not: bu gece yalnızca kod okundu; sayfa açılıp teyit edilmedi — Bilal/SEO ajanı uygulamadan önce linki bir kez açsın. rel=prev/next Google tarafından 2019'dan beri kullanılmıyor; anchor'daki nitelik zararsız.)
  2. Canonical→1. sayfa burada olgusal olarak yanlış sinyal olur: canonical "bu sayfa şunun kopyası" demektir; derin sayfanın 50 satırı 1. sayfada yok (B1). Google ya sinyali yok sayar ya da derin sayfaları dizinden düşürür; ikinci durumda 667 URL'deki programlar (üniversite tarafında programların ~%53'ü) arama için yalnızca diğer eksendeki listeye — o da çoğu zaman yine bir derin sayfaya — kalır. Program detay sayfası olmadığı için telafi edecek başka URL yok.
  3. Asıl zayıflık canonical değil, ayırt edilemezlik: başlık ve açıklama yalnızca sayfa numarasıyla ayrışıyor, bölüm derin sayfasının H1'i 1. sayfayla aynı. Oysa içerik gerçekten farklı ve aranabilir biçimde farklı: bölüm sayfaları taban sırasına göre dizili → N. sayfa belirli bir sıralama aralığını kapsıyor ("Psikoloji — taban sırası 95.000–180.000 arası programlar"); üniversite sayfaları fakülteye göre dizili → N. sayfa belirli fakülteleri kapsıyor ("… — Sağlık Bilimleri Fakültesi, Tıp Fakültesi"). Bu, "X bin sıralama ile psikoloji" türü sorgularla doğrudan örtüşür; veri zaten BolumIcerik/UniversiteIcerik içinde hesaplı (dilim, gruplar).
  4. Risk profili: canonical/robots'a dokunulmadığı için indeks kaybı riski yok — CEO'nun §6'daki erteleme gerekçesi ("derin sayfaları indeksten düşürebilir") bu öneri için geçerli değil; Search Console verisi beklenmeden yapılabilir. GSC dışa aktarımı (§5-c) yalnızca etkiyi ölçmek için gerekir: /sayfa/ URL'lerinde "Kopya, kullanıcı canonical seçmedi" / "Tarandı — dizine eklenmedi" sayısı önce/sonra.

Bilinçli olarak önerilmeyenler: noindex,follow (Google uzun süre noindex kalan sayfanın linklerini de izlemeyi bırakır; derin programların tek keşif yolu kesilir), sitemap'e ekleme (zorunlu değil; öncelik sinyali 1. sayfalarda kalsın — mevcut hâl doğru), SAYFA_BOYU büyütme / "tümünü göster" (ayrı ürün/performans kararı; 428 satırlık tablo).

B3. Değişecek dosyalar (uygulama YOK — yalnızca liste)

Dosya Değişiklik
src/features/katalog/components/bolum-icerik.tsx bolumSayfaMetadata sayfa > 1 dalı (:49-60): başlık ve açıklamaya o sayfanın taban sırası aralığı (dilimdeki ilk/son efektifSira; null'lar için "taban verisi olmayan programlar" yedeği). H1 (:122-124) derin sayfada ayrışsın ("Psikoloji — Sayfa 2" + aralık alt satırı). Görünür breadcrumb (:116-118) üst bölüm linkini de göstersin (üniversite sayfasındaki desenle birebir — AGENTS.md "tek kaynak" ilkesi)
src/features/katalog/components/universite-icerik.tsx uniSayfaMetadata sayfa > 1 dalı (:57-69): açıklamaya (ve uzunluk elverirse başlığa) o sayfadaki fakülte adları (gruplar ile aynı hesap; ilk 2 ad + "ve N birim daha"). Giriş paragrafı (:261-274) fakülte adlarını da saysın. Üniversite adları uzun olduğu için <title> ~60 karakteri aşmasın: farklılaştırıcı öncelikle description + H1 altına
(ortak yardımcı, isteğe bağlı) src/features/katalog/components/sayfalama.tsx ya da yeni küçük yardımcı Dilim hesabı (slice((sayfa-1)*SAYFA_BOYU, …)) metadata ve gövdede iki kez yazılmasın diye tek fonksiyon
Değişmeyecek src/lib/seo.tsx (sayfaMetadata canonical mantığı doğru), src/app/sitemap.ts, src/app/robots.ts, iki sayfa/[no]/page.tsx rota dosyası

Kabul kriteri önerisi: build sonrası universite/<slug>/sayfa/2.html ve sayfa/3.html'in <title> + <meta name="description"> çifti sayfa numarası dışında da farklı; canonical hâlâ kendine; <meta name="robots"> hâlâ index, follow; bölüm derin sayfasında <h1> 1. sayfadan farklı.