Güvenlik ve Optimizasyon
Video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin güvenliği, route ve edge cache stratejileri, dinamik robots.txt ve sitemap üretimi.
Bu sayfa Achidemy’de video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin panelinin güvenliğe alınması, route/edge cache stratejileri ve SEO için dinamik robots.txt ile sitemap üretimini açıklar.
Video Güvenliği — Bunny CDN İmzalı (Signed) URL
Section titled “Video Güvenliği — Bunny CDN İmzalı (Signed) URL”Videolar Bunny.net Stream üzerinden sunulur. Doğrudan indirmeyi ve yetkisiz erişimi engellemek için imzalı (signed) URL kullanılır.
Nasıl Çalışır?
Section titled “Nasıl Çalışır?”- Dosya:
app/lib/video-security.ts - Fonksiyon:
generateSignedVideoUrl(videoId, libraryId, securityKey, expirationSeconds?) - Algoritma: Bunny’nin beklediği formatta token üretilir:
expires = now + expirationSeconds(varsayılan 3600 saniye = 1 saat)tokenData = securityKey + videoId + expires- SHA-256 hash alınır → hex string =
token - URL:
https://iframe.mediadelivery.net/embed/{libraryId}/{videoId}?token={token}&expires={expires}
Bunny CDN, gelen istekteki token ve expires değerini aynı mantıkla doğrular; süre dolmuş veya token yanlışsa içerik verilmez.
Ortam Değişkenleri
Section titled “Ortam Değişkenleri”| Değişken | Açıklama |
|---|---|
BUNNY_LIBRARY_ID | Bunny Stream Library ID |
BUNNY_VIDEO_SECURITY_KEY | Bunny panelinden alınan Pull Zone → Remote Auth / Security Key (imza için kullanılır) |
Kullanıldığı Yerler
Section titled “Kullanıldığı Yerler”- Öğrenme sayfası:
app/routes/learn.$slug.tsx— kayıtlı derslerde sadece erişim hakkı olan kullanıcılarasignedVideoUrlüretilir (preview dersler + enroll edilmiş kullanıcılar). - Kurs detay sayfası:
app/routes/course.$id.tsx— önizleme (preview) dersler içinsignedPreviewUrlüretilir.
BUNNY_VIDEO_SECURITY_KEY tanımlı değilse imzalı URL üretilmez; eski embed URL’i (token olmadan) kullanılır — bu durumda videolar doğrudan paylaşılabilir ve indirilebilir, production’da güvenlik anahtarı kullanılması önerilir.
Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması
Section titled “Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması”Uygulamadaki Mevcut Koruma
Section titled “Uygulamadaki Mevcut Koruma”Admin paneli uygulama seviyesinde şu şekilde korunur:
- Dosya:
app/routes/admin.tsx(layout loader) - Kontrol: Better Auth session alınır;
session?.user?.idyoksa veya veritabanındaki kullanıcırole !== "admin"ise 404’e yönlendirilir. - Tüm admin alt sayfaları bu layout’tan geçer; yani sadece role = admin olan kullanıcılar
/admin/*sayfalarına erişebilir.
Önerilen: Cloudflare Zero Trust (Access)
Section titled “Önerilen: Cloudflare Zero Trust (Access)”Production’da admin panelini ek bir katmanla korumak için Cloudflare Zero Trust (Access) kullanılabilir:
- Cloudflare Dashboard → Zero Trust → Access → Applications ile yeni bir uygulama tanımlanır.
- Protected hostname:
admin.yourdomain.comveyayourdomain.com/admin(path bazlı kural ile). - Policy: Örneğin sadece belirli e-posta alanları, GitHub/Google SSO veya One-time PIN ile giriş zorunlu tutulur.
- Böylece sunucuya istek ulaşmadan önce Cloudflare, kimlik doğrulamayı yapar; yetkisiz kullanıcılar login sayfasına yönlendirilir.
Dökümantasyon: Cloudflare Zero Trust — Application Access ve Protect a self-hosted application resmi dokümanlarından path/host bazlı kurulum yapılabilir.
Özet: Uygulama içi koruma (session + admin role) şu an tek katman; Cloudflare Access ile /admin (veya admin subdomain’i) ikinci katman olarak kilitlenebilir.
SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi
Section titled “SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi”robots.txt (Dinamik)
Section titled “robots.txt (Dinamik)”- Route:
GET /robots.txt(dil prefix’i yok) - Dosya:
app/routes/robots[.]txt.ts - İçerik: Loader içinde
request.urlilehostveprotocolalınır;baseUrldinamik oluşturulur. Aynı kod Cloudflare Workers veya farklı domain’de çalışır.
Kurallar özeti:
- User-agent: * — Genel kurallar: public sayfalar (ana sayfa,
/tr/,/en/,/de/, pricing, teaching, courses, course) Allow; admin, instructor, account, my-courses, cart, payment, login, register, onboarding, learn, verify, api, 404/500 Disallow. - Googlebot / Bingbot / Yandex — Aynı public sayfalar Allow; isteğe bağlı
Crawl-delay(bazı botlar için). - Sitemap: Response’ta
Sitemap: ${baseUrl}/sitemap.xmlve dil bazlısitemap-tr.xml,sitemap-en.xml,sitemap-de.xmlreferansları yer alır.
Not: Dil bazlı sitemap URL’leri (sitemap-tr.xml vb.) robots.txt’te belirtilmiş olabilir; şu an routes.ts içinde yalnızca tek sitemap.xml route’u vardır. Dil bazlı ayrı sitemap’ler istenirse ek route’lar eklenebilir.
Route & Edge Cache — React Router v7 + Cloudflare CDN
Section titled “Route & Edge Cache — React Router v7 + Cloudflare CDN”Ana sayfa ve kurs katalogu gibi yüksek trafikli, ancak verisi saniyede değişmeyen sayfalar için SSR hızında SSG benzeri bir deneyim sağlamak amacıyla HTTP cache header’ları kullanılır.
- Dosyalar:
app/routes/_index.tsx(ana sayfa)app/routes/courses.all.tsx(kategori bazlı kurs listesi)
- Fonksiyon: Her iki dosyada da component dışına
export function headers()tanımlıdır. - Header değeri:
export function headers() { return { "Cache-Control": "public, max-age=60, s-maxage=3600, stale-while-revalidate=86400", };}Açıklama:
max-age=60: Kullanıcının tarayıcısı yanıtı 1 dakika boyunca önbelleğe alır.s-maxage=3600: Cloudflare Edge (CDN) yanıtı 1 saat boyunca önbellekte tutar; bu süre boyunca istekler worker’a uğramadan statik HTML’den cevaplanır.stale-while-revalidate=86400: 1 saatten sonra bile yanıt “stale” olarak kullanıcıya anında gösterilir, arka planda yeni HTML işlenip Edge önbelleği sessizce güncellenir (SWR).
Bu sayede:
- İlk istekte SSR maliyeti ödenir.
- Sonraki binlerce istek, Cloudflare Edge’ten milisaniye içinde döner.
- Veri güncellemeleri arka planda yenilenir; kullanıcılar neredeyse her zaman “sıcak” sayfa görür.
Sitemap XML (Dinamik)
Section titled “Sitemap XML (Dinamik)”- Route:
GET /sitemap.xml - Dosya:
app/routes/sitemap[.]xml.ts - Veri:
getDb(env.DATABASE_URL)ile veritabanına bağlanılır;coursestablosundanstatus = 'published'olan kurslarınslugdeğerleri alınır. - URL’ler:
- Statik sayfalar:
baseUrl/{lang}{page}— diller: tr, en, de, es; sayfalar:"",/courses,/pricing,/teaching,/terms/privacy. Her biri içinchangefreq: weekly,priority: ana sayfa 1.0, diğerleri 0.8. - Kurs sayfaları:
baseUrl/{lang}/course/{slug}— sadece yayında olan kurslar;changefreq: daily,priority: 0.9.
- Statik sayfalar:
- Response:
Content-Type: application/xml,Cache-Control: public, max-age=3600.
Base URL: Sitemap içinde base URL sabit veya env’den okunabilir. Production’da canlı adres https://achidemy.net (BASE_URL / BETTER_AUTH) kullanılmalıdır. Bkz. Ortam Değişkenleri.
Kullanıcı Tarafı Sitemap Sayfası
Section titled “Kullanıcı Tarafı Sitemap Sayfası”- Route:
/:lang/sitemap(ör./tr/sitemap) - Dosya:
app/routes/$lang.sitemap.tsx - İçerik: HTML sitemap sayfası — platform bölümü (ana sayfa, tüm kurslar, fiyatlandırma, eğitmen ol), popüler kurslar (ör. kategori bazlı linkler), yasal (gizlilik, kullanım şartları, çerez politikası) linkleri. Arama motorları için ek bilgi; XML sitemap’in yerine geçmez.
| Konu | Açıklama |
|---|---|
| Video güvenliği | app/lib/video-security.ts — generateSignedVideoUrl ile Bunny CDN imzalı URL (SHA-256 token + expires). learn ve course sayfalarında kullanılır. Env: BUNNY_LIBRARY_ID, BUNNY_VIDEO_SECURITY_KEY. |
| Admin güvenliği | Uygulama: session + user.role === "admin" (admin.tsx loader). Önerilen ek katman: Cloudflare Zero Trust (Access) ile /admin veya admin hostname koruması. |
| Route/Edge cache | app/routes/_index.tsx ve app/routes/courses.all.tsx içinde headers() fonksiyonu ile Cache-Control: public, max-age=60, s-maxage=3600, stale-while-revalidate=86400; ana sayfa ve kurs listeleri Cloudflare Edge üzerinde SWR stratejisiyle cache’lenir. |
| robots.txt | Dinamik, request.url ile baseUrl. Allow/Disallow + Sitemap referansları; dil bazlı sitemap URL’leri isteğe bağlı. |
| sitemap.xml | Dinamik; DB’den yayındaki kurslar + statik sayfalar; diller (tr, en, de, es); XML; cache 1 saat. |
| /:lang/sitemap | HTML sitemap sayfası (kullanıcı ve SEO için). |
İlgili: Ortam Değişkenleri (Bunny ve diğer env), Admin Console (panel yetkilendirmesi), Eğitmen ve Kurs Yönetimi (video yükleme ve Bunny kullanımı), Hesap Güvenliği ve Oturum Yönetimi (hesap paylaşımı engelleme, review bombing koruması).
İlgili Dosyalar
Section titled “İlgili Dosyalar”app/lib/video-security.ts—generateSignedVideoUrl; Bunny CDN imzalı URL.app/routes/robots[.]txt.ts— Dinamik robots.txt.app/routes/sitemap[.]xml.ts— Dinamik sitemap XML.app/routes/$lang.sitemap.tsx— HTML sitemap sayfası.app/routes/admin.tsx— Admin layout; session ve role kontrolü.