# 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 `` "Garanti" | UI etiketi (elle yazılmış) | evet | | `src/features/pazarlama/components/meraklisina-icerik.tsx:71` | `Garanti 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` 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
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ı
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
…")` | **ş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:
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 ``, 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: `` | | Robots | `index, follow` (layout varsayılanı; sayfa özelinde direktif yok). `robots.ts` yalnızca `/api/` engelliyor | `src/app/layout.tsx:67`; build HTML `` | | 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 `

`'i: `Psikoloji` / `Psikoloji` | | Sitemap | **Girmiyor.** Yalnızca `/bolum/{slug}` ve `/universite/{slug}` | `src/app/sitemap.ts:31-44` | | Keşif yolu | `Sayfalama` gerçek `` üretir (`rel="prev"/"next"` anchor niteliğiyle; `` 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 ``; 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ı `` 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 `` ~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ı.