feat(geo): llms.txt, RSS, IndexNow, Article yazar/görsel, bölüm sayfasına veri özeti, vakıf bursu yazısı
All checks were successful
Deploy / deploy (push) Successful in 6m16s

GEO araştırması (docs/arastirma/2026-09-24-geo-seo) Dalga 1-2 uygulaması:
- /llms.txt ve /feed.xml route'ları (getAllRehberler'den otomatik), head'de RSS linki
- Article JSON-LD: author, image, mainEntityOfPage, publisher logo; görünür 'Yazan' satırı
- robots: ClaudeBot ayrı grupta Crawl-delay 1
- scripts/indexnow.ts (pnpm indexnow) + public anahtar dosyası
- bölüm sayfası açılışı veriden üretilen özgü cümleler (il/program/tür/kontenjan, taban aralığı, yıllık yön)
- ana sayfa fiyat iddiasına kaynak; iki yazıda 23.000 -> 21.000+; beş yazıya 'Kısa cevap' açılışı
- yeni yazı: vakif-universitesi-bursu-kesilir-mi (ÖSYM 2026 kılavuzu + YÖK ücret esasları)
- YAYIN-KUYRUGU: IndexNow adımı ve aylık AI görünürlük rutini

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 17:42:29 +03:00
parent 6094066c5e
commit 24d4bea32c
24 changed files with 1202 additions and 11 deletions

54
src/app/feed.xml/route.ts Normal file
View File

@@ -0,0 +1,54 @@
import { getAllRehberler } from "@/lib/rehber";
import { SITE_NAME, SITE_URL } from "@/lib/seo";
/**
* Rehber yazılarının RSS 2.0 beslemesi. Kök layout metadata'sındaki
* alternates.types bu adresi <link rel="alternate"> olarak <head>'e yazar.
* Cache Components altında istek verisi okunmadığı için prerender edilir.
*/
function xmlKacis(metin: string): string {
return metin
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;");
}
/** "YYYY-MM-DD" → RFC 822 (RSS pubDate). Gün 09:00 Türkiye saati kabul edilir. */
function rfc822(iso: string): string {
return new Date(`${iso}T09:00:00+03:00`).toUTCString();
}
export async function GET() {
const yazilar = getAllRehberler();
const enYeni = yazilar[0]?.guncelleme ?? yazilar[0]?.tarih;
const items = yazilar
.map(
(y) => ` <item>
<title>${xmlKacis(y.baslik)}</title>
<link>${SITE_URL}/rehber/${y.slug}</link>
<guid isPermaLink="true">${SITE_URL}/rehber/${y.slug}</guid>
<description>${xmlKacis(y.aciklama)}</description>
<pubDate>${rfc822(y.tarih)}</pubDate>
</item>`,
)
.join("\n");
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>${SITE_NAME} Tercih Rehberi</title>
<link>${SITE_URL}/rehber</link>
<description>YKS tercih dönemi rehberi: veriye dayalı, öğrenci diliyle yazılar.</description>
<language>tr</language>
<atom:link href="${SITE_URL}/feed.xml" rel="self" type="application/rss+xml" />
${enYeni ? ` <lastBuildDate>${rfc822(enYeni)}</lastBuildDate>\n` : ""}${items}
</channel>
</rss>
`;
return new Response(xml, {
headers: { "Content-Type": "application/rss+xml; charset=utf-8" },
});
}

View File

@@ -52,6 +52,9 @@ export const metadata: Metadata = {
description:
"YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmandan çok daha düşük fiyata, yapay zekâ destekli tercih danışmanlığı.",
applicationName: "KolayTercih",
alternates: {
types: { "application/rss+xml": "/feed.xml" },
},
openGraph: {
type: "website",
locale: "tr_TR",

62
src/app/llms.txt/route.ts Normal file
View File

@@ -0,0 +1,62 @@
import { getAllRehberler } from "@/lib/rehber";
import { KATALOG_VERI_TARIHI, SITE_URL } from "@/lib/seo";
import { SON_YIL, VERI_ARALIGI } from "@/lib/veri-yillari";
import { PROGRAM_SAYISI_METNI } from "@/lib/veri-kapsami";
import { trTarih } from "@/lib/tarih";
/**
* llmstxt.org biçiminde site özeti: H1, tek paragraf özet, H2 altında
* bağlantı listeleri. Yalnızca sitede zaten görünen bilgiyi taşır; içerik
* gövdesi (llms-full.txt) bilinçli olarak üretilmez — etkisi kanıtsız,
* toplu kopyalamayı kolaylaştırır (docs/arastirma/2026-09-24-geo-seo).
*
* Rehber listesi getAllRehberler()'den gelir; sitemap ile aynı kaynak,
* elle bakım yok. Cache Components altında istek verisi okunmadığı için
* build'de prerender edilir.
*/
export async function GET() {
const yazilar = getAllRehberler();
const rehberSatirlari = yazilar
.map(
(y) =>
`- [${y.baslik}](${SITE_URL}/rehber/${y.slug}): ${y.aciklama}`,
)
.join("\n");
const metin = `# KolayTercih
> Türkiye'de YKS (üniversite giriş sınavı) tercih danışmanlığı: YÖK Atlas'ın
> resmî yerleştirme verisine dayanan, yapay zekâ destekli 24 tercihlik dengeli
> liste. Ücretsiz katalog: bölüm, üniversite ve il sayfalarında ${VERI_ARALIGI}
> taban sıralamaları.
Veri kaynağı: YÖK Atlas ${SON_YIL} yerleştirme sonuçları, ${PROGRAM_SAYISI_METNI}
program. Katalog en son ${trTarih(KATALOG_VERI_TARIHI)} tarihinde güncellendi.
KolayTercih, ÖSYM ya da YÖK ile bağlantılı değildir; yerleşme garantisi vermez.
Yapay zekâ önerileri yalnızca kullanıcının sıralamasıyla açılan gerçek programlar
arasından seçilir.
## Ana bölümler
- [Bölümler](${SITE_URL}/bolumler): bölüm bazında taban puanı ve sıralama tabloları
- [Üniversiteler](${SITE_URL}/universiteler): il bazlı üniversite kataloğu
- [Üniversite sıralaması](${SITE_URL}/universite-siralamasi): URAP akademik başarı sıralaması
- [Tercih Rehberi](${SITE_URL}/rehber): tercih süreciyle ilgili ${yazilar.length} rehber yazısı
- [Nasıl çalışır](${SITE_URL}/meraklisina): sihirbaz ve liste mantığının anlatımı
- [Paket](${SITE_URL}/paket): ücretli yapay zekâ tercih listesi hizmeti
## Rehber yazıları
${rehberSatirlari}
## Optional
- [Gizlilik](${SITE_URL}/gizlilik)
- [Kullanım koşulları](${SITE_URL}/kosullar)
- [İletişim](${SITE_URL}/iletisim)
`;
return new Response(metin, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

View File

@@ -93,7 +93,7 @@ const problems = [
icon: Wallet,
title: "Danışman lüks haline geldi",
description:
"İyi bir tercih danışmanı 1.000–3.000 TL istiyor. Ücretsiz robotların çoğu ise yalnızca liste filtreliyor; listeyi kurup gerekçesini yazmıyor.",
"Armut'ta tercih danışmanlığı ilanları ortalama 1.000–3.000 TL (Eylül 2026). Ücretsiz robotların çoğu ise yalnızca liste filtreliyor; listeyi kurup gerekçesini yazmıyor.",
},
];
@@ -185,7 +185,7 @@ const comparison = [
{
feature: "Fiyat",
robot: "Ücretsiz",
danisman: "1.000–3.000 TL",
danisman: "1.000–3.000 TL*",
tercihai: `${PAKET_FIYATI} TL · tek seferlik`,
},
];
@@ -524,6 +524,9 @@ export default function Home() {
</TableBody>
</Table>
</div>
<p className="mt-3 text-xs text-slate-500">
* Danışman fiyat aralığı: Armut ortalama fiyatı, Eylül 2026.
</p>
</Reveal>
</Parallax>
</div>

View File

@@ -25,7 +25,7 @@ const AI_BOTLARI = [
"Amzn-SearchBot",
// Model eğitimi: aramasız yanıtlarda markanın bilinmesi buradan geçer
"GPTBot",
"ClaudeBot",
// ClaudeBot aşağıda kendi grubunda (Crawl-delay için); buraya yazma.
"Google-Extended",
"Applebot-Extended",
"meta-externalagent",
@@ -38,6 +38,9 @@ export default function robots(): MetadataRoute.Robots {
rules: [
{ userAgent: "*", allow: "/", disallow: DISALLOW },
{ userAgent: AI_BOTLARI, allow: "/", disallow: DISALLOW },
// Anthropic Crawl-delay'i resmî olarak destekliyor (support.claude.com);
// eğitim taraması 1011 URL'lik katalogda saniyede 1 istekle yeter.
{ userAgent: "ClaudeBot", allow: "/", disallow: DISALLOW, crawlDelay: 1 },
],
sitemap: `${SITE_URL}/sitemap.xml`,
};