# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
# Tarayıcı açma
**Varsayılan: açma.** UI değişikliklerini tarayıcıda/preview'da doğrulamaya çalışma; kullanıcı kendisi kontrol ediyor. Dev sunucusu veya browser paneli açma — sadece kod değişikliğini yap ve ne değiştiğini raporla. Bu kural `yazilimci`, `qa-muhendisi` dışındaki roller ve genel kod işleri için geçerlidir.
**İstisna: `tasarimci` ve UX işi.** Tasarımcı, gerekli gördüğünde önizlemeyi/dev sunucusunu **açabilir**. Bazı tasarım sorunları koddan teşhis edilemez — taşma, üst üste binme, kırılma noktaları, gerçek metin uzunluğuyla oluşan yerleşim, karanlık mod, odak halkası, dokunma hedefi. Bunlarda "koddan çıkarım" yetmez; bakmak gerekir.
Açtığında geçerli olanlar:
- **Gerekçesini yaz:** neyi koddan göremediğin için açtın.
- **Ne gördüğünü yaz**, hangi genişlikte (375 / 768 / 1024 / 1280 px) ne olduğunu tek tek. Ekran görüntüsü alabilirsin.
- İşin bitince **sunucuyu kapat** (`preview_stop`). Disk ve bellek dar olabilir; açık bırakma.
- Tarayıcıda hesap açma, şifre/kart/kimlik girme, ödeme, mesaj gönderme, yayın/post, CAPTCHA çözme, dosya indirme **yine yasak** (PROTOKOL md.5). Çerez bandı çıkarsa reddet. Kullanıcının açık oturumlarına girme.
- Canlı siteye (`kolaytercih.com`) bakmak serbesttir ve çoğu zaman dev sunucusu açmaktan ucuzdur — önce onu dene.
# Sürümleme (7 Eki 2026'dan itibaren geçerli)
Site semantik sürüm taşır; tek kaynak `package.json` `version` alanıdır, header'daki
rozet (`src/components/surum-rozeti.tsx`, `src/lib/surum.ts`) bunu build'den okur.
Canlıdaki (`main`) sistem **1.0.0 Beta**'dır; `v2` dalı **2.0.0** geliştirmesidir.
Kurallar:
- **Major (X.0.0):** sihirbaz/liste/ödeme akışında kullanıcının gördüğü davranış değişir,
eski liste ya da raporlar yeni sistemle uyumsuz hâle gelir, ya da veri şeması kırılır.
Yalnızca Bilal açar; `vN` adlı dalda biriktirilir, `main`'e merge edilince `package.json`
`N.0.0` olur.
- **Minor (x.Y.0):** yeni özellik, yeni ekran, yeni rehber altyapısı — geriye uyumlu.
Özelliği `main`'e alan commit `package.json`'daki sürümü de artırır (aynı commit).
- **Patch (x.y.Z):** hata düzeltmesi, metin/stil düzeltmesi, içerik. Düzeltme commit'i
artırır; yalnız rehber yazısı ekleyen commit'ler sürüm artırmaz.
- "Beta" etiketi rozette sabittir; kalkması Bilal'in kararıdır (rozet metni tek yerde,
`surum-rozeti.tsx`).
- Sürüm artıran commit mesajı `chore(surum): 1.1.0` ya da özelliğin mesajına `(→ 1.1.0)`
ekiyle yazılır; `main`'e giden her push'tan sonra canlıdaki rozetin beklenen sayıyı
gösterdiği kontrol edilir.
# Push öncesi build zorunlu
Push emri geldiğinde önce lokalde `pnpm build` başarıyla geçmeli; geçmeden asla push etme. Kritik detay: çalışma ağacı kirliyken build, commit'lenmemiş dosyaları da gördüğü için CI'da kırılacak bir commit'i yakalayamayabilir. Bu yüzden build'i **push edilecek commit'in kendisi** üzerinde doğrula (ör. geçici `git worktree add
HEAD` + `node_modules` symlink'i ile). Ayrıca kısmi commit atarken değişikliğin bağımlılık kapanışını kontrol et — bir dosyanın kullandığı prop/export başka bir commit'lenmemiş dosyadan geliyorsa onları da aynı commit'e dahil et.
# Görsel dilin tek kaynağı: docs/tasarim/DESIGN.md
UI'a dokunan her iş (yeni ekran, bileşen, kart, modal, buton, form; mevcut arayüz değişikliği) önce `docs/tasarim/DESIGN.md` okunarak yapılır; renk, yazı tipi, köşe, gölge, boşluk ve tek kaynak bileşenlerin sınıf dizileri oradan **birebir** alınır, "yaklaşık aynısı" yazılmaz. Aşağıdaki rozet/çarpı/CTA kuralları o belgenin özetidir. Genel tasarım katalogları (`ui-ux-pro-max` gibi "50 stil, 97 palet" kütüphaneleri) bu projede kullanılmaz; yön zaten belli. İş bitmeden `pnpm tasarim:denetim` sıfır hata vermeli (`pnpm lint` bunu da koşar); betik `scripts/tasarim-denetim.ts`, kural eklerken DESIGN.md'deki bölüm numarasına atıf yap.
# Karanlık mod: token'la çalışır, `dark:` yazılmaz
Sitede açık / koyu / sistem teması var (DESIGN.md §2.3). Karanlık mod `src/app/globals.css` içindeki `.dark` bloğunda palet token'ları çevrilerek çalışır (slate ölçeği ters döner, renkli açık zeminler koyu tona iner); bileşenlere `dark:` sınıfı yazılmaz. Yeni UI yazarken: yüzey zemini `bg-card`'dır (`bg-white` koyu temada da beyaz kalır — yalnız logo karosu gibi gerçekten beyaz kalması gereken yerde); koyu hap (`bg-slate-900`) yazısını `text-slate-50` ile alır; SVG/satır içi stilde sabit renk yerine `var(--card)`, `var(--color-slate-200)` gibi değişken kullanılır; koyu vurgu yüzeyi (`bg-slate-950`) `kt-koyu-yuzey` sınıfını taşır. `pnpm tasarim:denetim` bunları `yuzey-beyaz`, `koyu-hap-beyaz-yazi` ve `dark-sinif` kurallarıyla yakalar.
# Badge/eyebrow rozetleri: tek kaynak SectionEyebrow
Site genelindeki tüm badge/rozet/eyebrow elemanları ana sayfadaki section başlıklarının üstünde duran rozetle birebir aynı olmalı. Kanonik bileşen `src/components/pixel-decor.tsx` içindeki `SectionEyebrow`dur (piksel imzalı `PixelMark` ikonu + `inline-flex items-center gap-2 rounded-full border border-slate-200 bg-card px-3.5 py-1.5 text-xs font-semibold text-primary`; metin büyük-küçük harfli yazılır — uppercase yok). Yeni bir badge/eyebrow gerektiğinde `SectionEyebrow` kullan (`className` prop'u kenar boşluğu için var); `@/components/ui/badge`'deki `Badge` ile ya da elle yazılmış pill span'lerle yeni badge tasarlama. İnteraktif chip/buton pill'leri (filtre çipleri, nav butonları) bu kuralın dışındadır. Header'daki "Beta" sürüm rozeti (`src/components/surum-rozeti.tsx`) de dışındadır: o Arc UI Badge biçiminde, akademik gösterge morunda (`bg-indigo-500`) tek bir yerde durur; başka yere kopyalanmaz.
# UI tutarlılığı: ortak elemanlar tek kaynaktan
Modallar arası ortak elemanlar (kapatma çarpısı, başlık düzeni vb.) görsel olarak birebir aynı olmalı. Kapatma çarpısının kanonik stili `src/components/ui/dialog.tsx` içindeki `DialogContent` varsayılan butonudur (yuvarlak, `size-9`, `border border-slate-200`, `size-4` X ikonu, hover'da `bg-slate-100`, `active:scale-[0.96]`). Yeni bir modal eklerken bu varsayılanı kullan; özel yerleşim gerekiyorsa (ör. katalog-arama'da input satırının içindeki buton) `showCloseButton={false}` ver ama **aynı class setini** kopyala — farklı boyut/renk/varyantta yeni bir çarpı tasarlama. Aynı prensip diğer tekrarlanan UI parçaları için de geçerli: bir eleman iki yerde görünüyorsa stilini tek kaynaktan al veya birebir eşleştir.
# CTA butonlarında ikon: yıldız yok, sağ ok metnin sonunda
Funnel CTA butonlarında ("Listemi oluştur", "Tercihlerimi belirle", giriş/ödeme CTA'ları vb.) `Sparkles` (yıldız) ikonu kullanılmaz. Kanonik desen: buton metni önce gelir, sonunda `` durur. Yeni bir CTA butonu eklerken bu deseni uygula; metnin başına ikon koyma. Dekoratif `Sparkles` kullanımları (boş durum başlık ikonları, bilgi satırları) bu kuralın dışındadır — kural yalnızca aksiyon butonları/CTA linkleri içindir.
# Meraklısına'daki mermaid şeması mimariyle senkron kalmalı
`/meraklisina` sayfasındaki sihirbaz akış şeması (`src/features/pazarlama/components/huni-semasi.tsx` içindeki `SEMA` sabiti) ürünün gerçek davranışının belgesidir, dekor değildir. Sihirbaz/listeleme mimarisinde davranış değiştiren her değişiklikte bu şema da aynı PR/commit içinde güncellenmeli: sihirbaz adımlarının sayısı-sırası-içeriği (alan → il → devlet/vakıf), aday havuzu kuralları, 24'lük liste iskeleti (hayal/dengeli/güvenli dağılımı — üçüncü dilimin kullanıcıya görünen adı "Güvenli"dir; iç anahtar, tip, DB değeri, mermaid `classDef` ve analitik değeri `garanti` olarak kalır, görünen etiketin tek kaynağı `src/lib/risk.ts` içindeki `DILIM_ETIKET`), havuz 24'ün altına düşünce filtre gevşetme sırası ve yapay zekânın havuz-dışına-çıkamama kuralı. Şemayı güncellerken çevresindeki unsurları da eşitle: bölümdeki anlatım metni (`src/features/pazarlama/components/meraklisina-icerik.tsx`, 4. bölüm), kabın `aria-label`'ı ve figcaption. Şema öğrenci diliyle kalmalı (SQL/prompt/teknik detay yok) ve ürünün risk renk dilini korumalı — kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz.
# Yayın sonrası arama motoru bildirimi (zorunlu)
Yeni ya da güncellenmiş bir rehber yazısı **canlıya çıktıktan sonra** şu iki adım yapılır, atlanmaz:
1. **Search Console'da URL denetimi.** Her yeni yazının tam adresi (`https://kolaytercih.com/rehber/`) Search Console'un URL denetleme kutusuna girilir; "URL Google'da yok" diyorsa **"Dizine eklenmeyi iste"** tıklanır. Google mülk başına günde sınırlı sayıda (~10-13) istek kabul eder — kota dolduğunda ısrar edilmez, kalanlar ertesi güne bırakılır ve nereye kalındığı not edilir.
2. **`sitemap.xml` yeniden gönderilir.** Search Console → Site Haritaları → `https://kolaytercih.com/sitemap.xml` tekrar gönderilir; "Başarılı" durumu ve keşfedilen URL sayısı not edilir. Aynı sitemap Bing Webmaster Tools'a da gönderilir.
**Sıra kuralı — ihlal edilmez:** URL denetimi yalnızca **canlıda 200 dönen** adres için yapılır. Commit'lenmemiş, push edilmemiş ya da deploy olmamış bir yazının adresi Search Console'a verilmez — 404 gönderilmiş olur ve günlük kota boşa yanar. Yazı yazıldığında sıra şudur: yaz → Bilal commit'ler ve yayınlar → canlıda 200 doğrulanır (`curl -s -o /dev/null -w "%{http_code}"`) → **sitemap'te görünür doğrulanır (aşağı)** → ancak o zaman Search Console.
**Sitemap ön kontrolü — bildirimden önce, her adres için tek komut.** 22 Eylül 2026'da `kyk-burs-mu-kredi-mi` bildirildiğinde Search Console "Yönlendiren site haritası algılanmadı" dedi. Bu yüzden bildirimden önce adresin **bizim sitemap'imizde gerçekten olduğu** doğrulanır:
```sh
curl -s https://kolaytercih.com/sitemap.xml | grep -c "/rehber/<"
```
Desendeki kapanış `<` şart: onsuz bir slug, kendisiyle başlayan daha uzun bir slug'ı da sayar ve sayım yanlış 1 döner. Sonuç **1 değilse o adres bildirilmez** — sorun deploy tarafındadır (yazı dosyası canlı derlemeye girmemiş; `src/app/sitemap.ts` slug listesini `content/rehber`'den üretir), önce o çözülür. 0 iken yapılan bildirim kotadan bir istek yakar. Toplu yayında hepsi tek seferde sayılır:
```sh
for s in …; do printf "%s -> " "$s"; curl -s https://kolaytercih.com/sitemap.xml | grep -c "/rehber/$s<"; done
```
**Sırayı bozma:** sitemap **önce** yeniden gönderilir, URL denetimleri **sonra** yapılır. Sayım 1 çıktığı hâlde Search Console yine "yönlendiren site haritası algılanmadı" diyorsa bu bizim değil Google'ın okuma gecikmesidir — **istek tekrarlanmaz, kota yakılmaz**; bir hafta sonra bakılır.
**Kota sayacı — her bildirim gününde tutulur.** Günlük kota mülk başına ~10-13 istek. `docs/ekip/YAYIN-KUYRUGU.md` içindeki **"Kota kullanımı"** tablosuna o günün satırı yazılır (`22 Eyl: 6/13` biçiminde) ve her istekten sonra güncellenir; **13'e varınca o gün durulur**, kalan adresler ertesi güne yazılır. Başarısız/boşa giden istek de sayaca yazılır — kotadan düşen odur, sonuç değil.
**Mülk ve hesap — işe başlamadan önce.** Mülk **`sc-domain:kolaytercih.com`** ve Bilal'in **ikinci** Google hesabında (Search Console adresinde `/u/1/`); birinci hesap (`bilalgursen777@gmail.com`) mülkü görmüyor, "Maalesef bu mülke erişiminiz yok" diyor. Bu yüzden: (a) işe başlarken doğru hesapta olunduğu **görülür** — adres çubuğunda `/u/1/` ve üstte mülk adı; (b) Search Console'un arama kutusu **dar pencerede kendini kapatıyor**: pencere genişletilir → büyüteç düğmesine basılır → kutunun açıldığı **görülür** → ancak o zaman yazılır. Açılmamış kutuya yazmak ve kutuya doğrudan değer basmak (`form_input`) yasak; 22 Eylül'de kaybedilen 2 istek böyle gitti (biri tekrar istek, biri iki adresin birbirine yapışmasıyla oluşan bozuk adres). Kalıcı çözüm Bilal'de: birinci hesabı mülke **tam yetkili kullanıcı** olarak eklemek — hesap değiştirme penceresiyle uğraşmak bitince bu hata sınıfı da biter.
**Yetki:** Bu adımlar Bilal'in Google oturumunu kullanır. Ajan bu işi ancak Bilal açıkça söylediğinde ve kendi tarayıcısı üzerinden yapar; hesap açma, şifre girme, başka Google hizmetine geçme yasaktır. "Tarayıcı açma" kuralı (UI'ı önizlemede doğrulama yasağı) bu işi kapsamaz — o kural dev sunucusu ve arayüz doğrulaması içindir.
**Kuyruk:** Henüz yayımlanmamış ama yazılmış yazıların adresleri `docs/ekip/YAYIN-KUYRUGU.md` dosyasında tutulur; yayın sonrası bu listeden tek tek düşülür.
# Yıkıcı git komutları yasak (22 Eyl 2026 gece vardiyasında öğrenildi)
Ajanlar şu komutları **hiçbir koşulda** çalıştırmaz: `git reset --hard`, `git checkout -- `, `git restore `, `git clean`, `git stash`.
Sebebi: bu komutların hepsi **çalışma ağacındaki commit'lenmemiş değişiklikleri** siler ve bu değişiklikler çoğu zaman ajanın kendisine ait değildir — Bilal'in ya da paralel çalışan başka bir oturumun işidir. 22 Eylül gecesi bir kod ajanı kendi dalında commit'ini düzeltmek için `reset` koştu ve üç dosyada başkasının işini yok etti: `docs/ekip/KARARLAR.md` (iki karar kaydı), `docs/ekip/BACKLOG.md`, `content/rehber/veliler-icin-tercih-rehberi.md`. Commit'lenmemiş içerik git nesne veritabanına hiç girmediği için `git fsck` ile kurtarılamaz; o gece kurtarma yalnızca metin başka bir ajanın raporunda saklandığı için mümkün oldu.
Yerine ne yapılır:
- Son commit'i düzeltmek: `git commit --amend` (reset gerekmez).
- Bir commit'i geri almak: `git revert ` (yeni commit üretir, çalışma ağacına dokunmaz).
- Kendi yazdığın bir dosyayı geri almak: dosyayı elle düzenle, `checkout --` kullanma.
Kural ihlal edilmişse: ne kaybedildiğini `git reflog` + `git diff ` ile tespit et, **derhal raporla**, kendi başına yeniden oluşturmaya çalışmadan önce kaybın kapsamını yaz.