Göndermeden önce doldurun
[sunucu adı][etkinlik adı][ne, kimler için, kaçıncı kez, iki cümle][başlangıç ve bitiş, saat dilimi][her gün için saat, oturum başlığı, konuşmacı, salon][kurum adı][e-posta][telefon][konuşmalar kaydedilecek mi, fotoğraf çekilecek mi][alan adı][renk tercihi][etkinlik]
Opus Growth hosting sunucumdaki [sunucu adı] sitesine, [etkinlik adı] için statik ve hızlı bir etkinlik sitesi kur. Etkinlik: [ne, kimler için, kaçıncı kez, iki cümle]. Tarih ve saat: [başlangıç ve bitiş, saat dilimi]. Mekan: [mekan adı, açık adres, ulaşım, otopark, erişilebilirlik olanakları]. Program: [her gün için saat, oturum başlığı, konuşmacı, salon]. Konuşmacılar: [ad, unvan, kurum, konuşma başlığı, biyografi, fotoğraf bağlantısı ve fotoğrafı yayımlama izni]. Biletler: [bilet türleri, fiyatlar, KDV dahil mi, geçerlilik tarihleri, satış platformundaki bağlantı, iade ve devir koşulları]. Düzenleyen: [kurum adı], [e-posta], [telefon]. Kayıt ve fotoğraf politikası: [konuşmalar kaydedilecek mi, fotoğraf çekilecek mi]. Alan adı: [alan adı].
Sayfalar: ana sayfa (tarih ve mekan satırı, geri sayım, kısa tanıtım, ne olacak, konuşmacılardan dört kişi, mekan özeti, SSS), program (/program/: gün sekmeleri ve .ics takvim dosyası), konuşmacılar (/konusmacilar/), bilet (/bilet/: bilet türleri, dahil olanlar, iade, fatura SSS'si), mekan (/mekan/: adres, ulaşım, erişilebilirlik, konaklama), gizlilik (/gizlilik/: fotoğraf ve kayıt tercihi dahil) ve 404.html.
Tarz: konferans afişi. [renk tercihi] verilmediyse sinyal sarısı bir hero bandı, krem zemin, siyah metin ve 2 piksellik siyah kenarlar. Başlıklarda geniş ve kalın bir Fontshare yazı tipi büyük harfle (ör. Panchang 700), gövdede yuvarlak bir sans (ör. Chillax 400 ve 500); ilk ekrandaki üç dosyayı da preload et. Büyük harf dönüşümü için `<html lang="tr">` şart, yoksa "i" harfi "I" olur. Konuşmacı fotoğrafı yoksa ya da yayın izni yoksa fotoğraf yerine baş harf monogramı kullan; başka birinin fotoğrafını koyma.
Etkileşim kuralları (kütüphanesiz, tek `ix.js`, defer, yalnız ana sayfa, program ve konuşmacılar):
1. Geri sayım JS kapalıyken de doğrudur: HTML'de sabit yükseklikli bir kutunun içinde "Başlangıç: <time datetime="2027-05-13T09:00:00+03:00">13 Mayıs 2027 Perşembe, 09.00</time> (Türkiye saati)" metni durur. JS, data-start ve data-end niteliklerindeki saat dilimi ofsetli ISO tarihleri Date.parse ile okur ve aynı kutunun içine gün, saat ve dakika kutularını yazar. Kutu iki durumda da aynı yükseklikte olmalı (CSS min-height ve sabit kutu yüksekliği), yoksa ilk ekranda kayma olur. Saniye gösterme ve sayacı dakikada bir güncelle; sekme gizliyken durdur. Sayı kutuları aria-hidden olsun, ekran okuyucu için yanlarında tek bir görünmez cümle bulunsun ve canlı bölge (aria-live) kullanma, çünkü her dakika okunur. Etkinlik başladıysa "şu an sürüyor", bittiyse "sona erdi" yaz; geçmiş bir tarih için eksi sayı gösterme.
2. Gün sekmeleri: HTML'de her gün kendi başlığıyla ayrı bir section (id="gun-1", "gun-2") ve üstte bu bölümlere giden bağlantılar; JS kapalıyken bütün günler alt alta görünür. Bağlantıları saran kapsayıcı role="group" ve aria-label taşır. JS bunları ARIA sekmelerine çevirir (tablist, tab, tabpanel, aria-selected, tabindex, ok tuşları, Home ve End), sayfa #gun-2 ile açılırsa ikinci günü seçer ve sekme değişince adresi history.replaceState ile günceller ki gün bağlantısı paylaşılabilsin. Her oturum `<time datetime>` taşıyan bir liste satırıdır: saat, başlık, konuşmacının konuşmacılar sayfasındaki çapasına bağlantı, salon; aralar ayrı zeminle.
3. Konuşmacı biyografisi: HTML'de her kartta `<details>` içinde durur, böylece JS kapalıyken ve arama motorları için okunur. JS, summary tıklamasını yakalar, tek bir `<dialog>` oluşturup adı, unvanı, konuşma başlığını ve biyografiyi textContent ile içine kopyalar, showModal ile açar, odağı "Kapat" düğmesine verir; Esc ve arka plana tıklama kapatır, odak geri summary'ye döner. summary'ye aria-haspopup="dialog" ekle. Her kartın id'si konuşmacının kısa adıdır, programdaki bağlantılar oraya gider.
4. Yapışkan bilet çağrısı: masaüstünde başlıktaki "Bilet al" düğmesi, mobilde ekranın altında sabit bir çubuk (tarih, en düşük fiyat ve "Bilet al"). Çubuk alt bilgi şablonunda statik HTML olarak durur ve ilk boyamadan itibaren position: fixed'tir; JS ile sonradan eklenirse kayma yaratır. Mobilde body'ye çubuk yüksekliği kadar alt boşluk ver ki son bağlantılar çubuğun altında kalmasın, `env(safe-area-inset-bottom)` ekle ve bilet sayfasında body'ye verilen bir sınıfla çubuğu gizle.
5. Takvim dosyası: program sayfasından indirilen `/assets/[etkinlik].ics` (VCALENDAR, tek VEVENT, DTSTART ve DTEND UTC olarak, SUMMARY, LOCATION, URL, satır sonları CRLF). Bağlantıya download niteliği ver.
Şema: ana sayfada, program sayfasında ve bilet sayfasında aynı Event (@id /#event): name, description, startDate ve endDate saat dilimi ofsetiyle, eventStatus EventScheduled, eventAttendanceMode OfflineEventAttendanceMode, location içinde Place ve tam PostalAddress, image için 1x1, 4x3 ve 16x9 oranlarında üç görsel, organizer, performer olarak konuşmacılar ve offers dizisi (her bilet türü için name, price, priceCurrency "TRY", availability, validFrom, erken kayıtta validThrough, url olarak satış sayfası). Google'ın etkinlik zengin sonucu location ve startDate ister ve sayfalar arası @id'yi birleştirmez, bu yüzden Event'i her kullandığın sayfada eksiksiz yaz; program sayfasında ayrıca her oturumu subEvent olarak ekle. Etkinlik ertelenir ya da iptal olursa eventStatus'ı EventPostponed ya da EventCancelled yap, sayfayı silme. Mekan sayfasında Place, her iç sayfada BreadcrumbList. Sponsor, katılımcı sayısı ya da "tükendi" bilgisi yalnız gerçekse yazılır.
Kurulum ve bilinen tuzaklar (demo ölçümünde her biri puanı düşürdü, atlama):
1. Sunucuda yayında bir site varsa önce bana söyle, çünkü kurulum index.html ve assets klasörünü ezer. scaffold_site'ı önce confirm=false ile önizle, onayımla confirm=true çağır. Sonra site_design_guide ve site_seo_guide'ı oku. Koda başlamadan tasarım yönünü (tipografi, renk, ızgara, imza öğesi, hareket dili ve YÜKLENMEYECEK kütüphaneler) assets dışında kısa bir ART.md dosyasına yaz ve bana göster.
2. Tailwind'i derle, CDN'den yükleme. site_run_command ile background=true vererek `npm i -D tailwindcss@3` kur ve sonucu site_command_status ile izle. `tailwind.config.js` içindeki content yolları bütün HTML dosyalarını, `_src` şablonlarını ve sınıf yazan JS dosyalarını kapsasın. `_src/tw.css` dosyası `@import "../assets/app.css";` satırı ve üç `@tailwind` satırından oluşsun; `npx tailwindcss -c tailwind.config.js -i _src/tw.css -o assets/site.css --minify` ile tek dosyaya derle. Sayfalardan cdn.tailwindcss.com betiğini ve satır içi tailwind.config'i kaldır, yalnız `/assets/site.css` bağla. Her HTML değişikliğinden sonra yeniden derle.
3. Fontları kendi sunucunda barındır. Seçtiğin Fontshare ailesinin CSS'ini oku, her ağırlığın woff2 dosyasını ayrı ayrı site_fetch ile `assets/fonts/` altına indir ve @font-face kurallarını `font-display: swap` ile `assets/app.css` içine yaz; design-check özgün fontu orada arar. İndirdiğin CSS'teki font-family adını ve ailenin ı, İ, ş, ğ harflerini içerdiğini kontrol et (Tanker'de ı yok). İlk ekranda kullandığın HER ağırlığı `<link rel="preload" as="font" type="font/woff2" crossorigin>` ile önceden yükle ve bu satırları stil dosyası satırından önce yaz; üç dosyayı geçiyorsa ağırlık sayısını azalt. Demoda preload edilmeyen tek bir gövde ağırlığı mobil LCP'yi 2,6 saniyeye itti ve performansı 97'ye düşürdü. Fontshare fontlarının çoğunda ₺ işareti yok, fiyatları "TL" ile yaz.
4. Menüyü ve alt bilgiyi statik HTML yap. chrome.js, motion.js ve site.config.js'i sayfalara yükleme. site.config.js'teki nav listesini okuyup `_src/header.tpl` ve `_src/footer.tpl` şablonlarını her sayfadaki `<!-- nav:start --><!-- nav:end -->` ve `<!-- footer:start --><!-- footer:end -->` işaretlerinin arasına basan küçük bir `chrome-stamp.mjs` yaz; etkin sayfanın bağlantısına aria-current="page" eklesin. Şablonlarda `{{...}}` yerine `[[NAV]]` gibi yer tutucu kullan, uzantıları .html olmasın; yoksa design-check ve seo-check onları yarım sayfa sanar. Mobil menüyü JS'siz `<details>` ile kur. Alt bilgide işletme adı, adres ve telefon düz metin olarak dursun; alt bilgi ve kırıntı bağlantıları en az 44 piksel yüksekliğinde olsun.
5. Görselleri site_fetch ile indirirken dönüştür: aynı görseli resize="480x", "800x" ve "1200x", image_format="webp", quality=60 ile ayrı dosyalara yaz (site_fetch kırpmaz; kırpım gerekiyorsa kaynağı o oranda iste). Her `<img>` için srcset, sizes ve gerçek orana uyan width ve height ver. Sayfanın LCP öğesi olan görsel fetchpriority="high" olsun ve lazy olmasın; diğer bütün görseller loading="lazy" decoding="async" olsun. Mobilde ilk ekranı dolduran bir görsel varsa `<picture>` ile mobile daha küçük bir kırpım ver.
6. Her sayfaya `<link rel="icon" href="/favicon.svg" type="image/svg+xml">` ekle ve logodan site_fetch ile resize="180x180" bir apple-touch-icon üret. Favicon bağlantısı yoksa tarayıcı /favicon.ico ister, konsola 404 düşer ve En İyi Uygulamalar puanı 96'ya iner.
7. HTML doğrulayıcısının kuralları: belge büyük harfli `<!DOCTYPE html>` ile başlasın; tel: bağlantılarının görünen metnindeki her boşluk ` ` olsun ("Ara: 0212..." gibi önekteki boşluk dahil); style="" niteliği kullanma; her düğmeye type yaz; aria-label'ı yalnız landmark, form ya da etkileşimli öğeye koy (ul ya da rolsüz div'e koymak hata verdi); aynı adla etiketlenmiş iki landmark olmasın; satır sonunda boşluk bırakma.
8. Başlık sırası atlamasın: liste sayfasında h1'den sonra kart başlıkları h3 olunca erişilebilirlik 98'e düştü; kartları yeniden kullanırken başlık düzeyini sayfaya göre ver (liste sayfasında h2, bir h2 bölümünün içinde h3).
9. Hareket için niteliğin adı data-reveal olsun (design-check hareketi yalnız bu adla tanır). Gizli başlangıcı JS yalnız sayfa açıldığında ekranın altında kalan bloklara versin, ilk ekrandaki içerik hiç gizlenmesin; transform kullan, opaklıkla soldurma kontrast denetimini düşürür. Niteliği tek başlığa değil başlığı ve açıklamasını saran bloğa koy; demoda yalnız başlığa konunca bekleyen başlık alttaki paragrafın üstüne bindi. prefers-reduced-motion: reduce olduğunda hiçbir şey gizlenmesin ve animasyonlar kapansın.
SEO, AEO ve GEO:
1. Adresleri dizin biçiminde ve sonu eğik çizgili kur. site.config.js'in seo bloğunu doldur ve `node seo-stamp.mjs` çalıştır. Sayfaya özel şemayı ayrı `<script type="application/ld+json">` bloklarına yaz ve @id ile temel grafiğe bağla. BreadcrumbList'i @graph içine gömme, kendi bloğunda dursun; seo-check onu yalnız böyle görür.
2. Title en çok 60 karakter olsun (seo-check 25'in altını ve 65'in üstünü hata sayar), description 130 ile 158 karakter, her sayfada tek h1 ve her sayfanın ana içeriği en az 150 kelime. İletişim, gizlilik ve liste sayfaları bu sınırın altında kalmaya yatkın; sayfaya özgü bilgi ekle, dolgu yazma.
3. Her sayfanın ilk paragrafı sayfanın sorusuna doğrudan cevap versin. Sayfaya özgü SSS'yi `<details>` ile yaz ve FAQPage olarak işaretle. Yayımlayan kurumu ve "Son güncelleme" tarihini `<time>` ile göster.
4. robots.txt'te GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, Claude-SearchBot, PerplexityBot, Perplexity-User, Google-Extended, Applebot-Extended, Bingbot ve CCBot için kararını gerekçesiyle yaz ve sitemap'i göster. sitemap.xml'de gerçek lastmod olsun. llms.txt'te sitenin iki cümlelik doğru özeti ve önemli sayfaların listesi bulunsun.
5. Uydurma yok: bana sormadan yorum, puan, ödül, müşteri sayısı, sertifika, çalışma saati, koordinat ya da fiyat yazma. Bilmediğin alanı şemaya hiç koyma.
Kapılar (sırayla; hepsi geçmeden "bitti" deme):
1. site_run_command ile `node chrome-stamp.mjs`, Tailwind derlemesi, `node seo-stamp.mjs`, `node seo-check.mjs` (0 hata, 0 uyarı), `node design-check.mjs` (0 hata; kalan uyarıyı gerekçesiyle yaz) ve `npx html-validate "**/*.html"` (0 hata).
2. Her sayfayı site_preview ile view="mobile" ve view="desktop" olarak gör. site_preview sayfayı hareket kapalıyken (reduced-motion) çeker; bu görüntüde içerik eksiksiz görünmüyorsa hareketsiz hal bozuk demektir. Tam sayfa görüntüsünde sabit konumlu öğeler (yapışkan çubuk gibi) sayfanın ortasında görünebilir ve aşağıdaki lazy görseller boş çıkabilir; bunları hata sayma ama yolunu kontrol et.
3. Her sayfa için core_web_vitals'ı strategy="mobile" ve strategy="desktop" ile çalıştır. Kabul: mobilde Performance en az 95 (hedef 99 ile 100), Accessibility, Best Practices ve SEO 100; masaüstünde dördü de 100. Tutmayan sayfada resources=true ile hangi dosyanın geciktirdiğini bul, düzelt ve yeniden ölç. Ardından ana sayfada seo_audit'i strategy="mobile" ve runs=2 ile çalıştır. Ağ istekleri listesinde kendi alan adın dışında bir adres kalmamalı.
4. 360, 390, 768 ve 1440 piksel genişlikte yatay kaydırma olmasın, dokunma hedefleri en az 44 piksel olsun, konsolda hata olmasın.
Etkileşim kontrolü: site_preview zamanı, sekmeleri ve dialog'u gösteremez. Bana geri sayımın JavaScript kapalıyken doğru tarihi gösterdiğini ve JS açıkken aynı yükseklikte kutulara döndüğünü, /program/#gun-2 adresinin ikinci günü açtığını ve sekmelerin ok tuşlarıyla değiştiğini, konuşmacı biyografisinin modalda açılıp Esc ile kapandığında odağın geri döndüğünü, telefonda bilet çubuğunun sayfanın son bağlantılarını örtmediğini, takvim dosyasının telefon takvimine doğru saatle eklendiğini ve Google'ın Zengin Sonuç Testi'nde Event'in hatasız göründüğünü nasıl kontrol edeceğimi yaz.
Yayından sonra: site_headers ile `/assets/* Cache-Control: public, max-age=31536000, immutable` kuralını önizle ve onayımla uygula; bundan sonra CSS ya da JS değiştiğinde dosya adını sürümle (site-v2.css gibi). gsc_submit_sitemap ile sitemap.xml'i gönder ve gsc_url_inspect ile ana sayfanın durumuna bak. En sonda bana şunları ver: sayfa sayfa puan tablosu (sayfa, mobil dört puan, masaüstü dört puan, LCP, CLS), kapıların sonucu ve uyguladığın düzeltmelerin listesi.