Online Kurs Platformu
Video + ödev + quiz + öğrenci paneli.
Online kurs platformu = eğitim girişiminizin omurgası. Teachable/Kajabi ücreti $99-300/ay + ürün başına %5-10. Kendi platformunuz: tam kontrol, sınırsız öğrenci, ek komisyon yok. Modern stack: Next.js + Supabase + Mux (video) + Stripe. 2 haftada MVP, 4-6 haftada production-ready.
Kim İçin Uygun?
- Online eğitmenler (kişisel marka)
- Eğitim girişimleri (kurslar satan)
- Kurum içi L&D (çalışan eğitimi)
- Uzmanlar (avukat, doktor, danışman → online eğitim)
Online Kurs Platformu için olmazsa olmazlar
Kurs katalog (public)
Hero + 6 kurs kartı + 'free trial' veya 'buy'.
Video player (Mux veya Cloudflare)
Adaptive bitrate streaming, hız kontrolü, captions, watermark.
Modül + ders yapısı
Her kurs: 5-15 modül, her modül: 3-10 ders, her ders: video + metin + ödev.
İlerleme takibi
Kullanıcı hangi ders tamamlandı, % bar, sertifika hak ediyor mu.
Quiz / ödev
Çoktan seçmeli quizler, otomatik puanlama. Açık uçlu ödevler, manuel feedback.
Tartışma forumu
Her dersin altında soru-cevap. Eğitmen ve diğer öğrenciler cevaplar.
Sertifika
Tamamlama sonrası PDF sertifika otomatik üretilir, indirilir.
Öğrenci paneli
Devam eden kurslar, tamamlananlar, faturalar.
Önerilen Yığın
9 adımda yayında
İçerik planla (1 gün)
İlk kursun: kaç modül, her modülde kaç ders, ders süresi (~5-10 dk ideal). Excel'e dök.
Video hosting seç
Mux (premium, adaptive streaming, $20+/ay), Cloudflare Stream ($5+/ay), YouTube unlisted (ücretsiz ama brand zayıf). Önemli kurs: Mux.
Schema (Supabase)
Tablolar: courses, modules, lessons, enrollments, lesson_progress, quiz_attempts, certificates. RLS politikaları.
Public sayfalar (1-2 gün)
Anasayfa + kurs detay + ödeme. Marketing site gibi düşün — dönüşüm ön planda.
Öğrenci paneli (3 gün)
Dashboard + kurs içi navigation (sidebar) + video player + ders metni + 'tamamlandı' butonu + sonraki ders.
Quiz + ödev (2 gün)
Çoktan seçmeli quiz UI + otomatik puanlama. Ödev: form + dosya upload + eğitmen incelemesi.
Sertifika + email (1 gün)
Kurs %100 → React PDF ile sertifika üret + Resend ile gönder. PDF: isim + kurs adı + tarih + QR code (doğrulama linki).
Eğitmen paneli (1-2 gün)
Kurs ekle/düzenle, öğrenci listesi, satış metrikleri, ödev incelemesi.
Stripe + deploy (1 gün)
Tek seferlik ödeme veya abonelik. Kupon sistemi. Vercel deploy + custom domain.
Online Kurs Platformu'da Video / Slider Nasıl Yapılır?
Online kurs platformu BÜTÜN MESELESİ video. Doğru video player + slide notları + hız kontrolü + ilerleme kaydı = kullanıcı bitirir. Yanlış video = drop-out %80'i geçer. Burası en önemli bölüm.
Mux player kurulum (en kalitelisi)
Adaptive bitrate streaming. Her bağlantı hızında otomatik kalite. CDN dahil.
npm install @mux/mux-player-react
import MuxPlayer from '@mux/mux-player-react';
<MuxPlayer
playbackId={lesson.muxPlaybackId}
metadata={{
video_id: lesson.id,
video_title: lesson.title,
viewer_user_id: user.id,
}}
streamType="on-demand"
primaryColor="#0EA5E9"
secondaryColor="#000"
onTimeUpdate={(e) => saveProgress(e.target.currentTime)}
onEnded={() => markCompleted(lesson.id)}
/>Cloudflare Stream alternatifi (uygun fiyatlı)
Mux çok pahalıysa Cloudflare. $5/ay başlar, dakika başına $1 storage.
<iframe
src={`https://customer-X.cloudflarestream.com/${videoId}/iframe?poster=${posterUrl}`}
className="w-full aspect-video"
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
allowFullScreen
/>Hız kontrolü (önemli!)
Öğrenciler 1.5×-2× hız sever. Mux player varsayılan destekler. Custom için video.js.
// Mux player'da otomatik var
// Manuel:
<MuxPlayer
playbackId={id}
defaultPlaybackRate={1}
playbackRates={[0.5, 0.75, 1, 1.25, 1.5, 2]}
/>İlerleme kaydı + kaldığı yerden devam
Her 5 sn'de bir Supabase'e progress kaydet. Sonraki açılışta o saniyeden başla.
const [lastTime, setLastTime] = useState(0);
useEffect(() => {
// Sayfa açılışında en son izleme zamanını çek
supabase
.from('lesson_progress')
.select('watched_seconds')
.eq('user_id', user.id)
.eq('lesson_id', lesson.id)
.single()
.then(({ data }) => data?.watched_seconds && setLastTime(data.watched_seconds));
}, [lesson.id]);
const saveProgress = useDebouncedCallback((seconds: number) => {
supabase.from('lesson_progress').upsert({
user_id: user.id,
lesson_id: lesson.id,
watched_seconds: seconds,
last_watched_at: new Date().toISOString(),
});
}, 5000);
<MuxPlayer
playbackId={lesson.muxId}
startTime={lastTime}
onTimeUpdate={(e) => saveProgress(e.target.currentTime)}
/>Slayt + ders notları yan yana
Sol: video, sağ: ders notları/slaytlar (PDF.js veya markdown). Kullanıcı her ikisini eşzamanlı görsün.
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 h-screen">
<div className="lg:col-span-2 bg-black">
<MuxPlayer playbackId={lesson.muxId} className="w-full h-full" />
</div>
<div className="overflow-y-auto p-6 prose dark:prose-invert">
<h2>{lesson.title}</h2>
{/* MDX content */}
<MDXRemote source={lesson.notes} />
{/* PDF slaytları (varsa) */}
{lesson.slidesPdfUrl && (
<a href={lesson.slidesPdfUrl} download className="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded">
<DownloadIcon /> Slaytları indir (PDF)
</a>
)}
</div>
</div>Captions / altyazı (önemli)
İşitme engelliler + sessiz ortam + dil öğrenenler için. Mux/Cloudflare native destekler.
<MuxPlayer
playbackId={lesson.muxId}
// WebVTT dosyası Mux'a yüklenmiş olmalı
/>
// Manuel:
<video controls>
<source src="..." />
<track
kind="subtitles"
src="/captions/lesson-1-tr.vtt"
srcLang="tr"
label="Türkçe"
default
/>
<track
kind="subtitles"
src="/captions/lesson-1-en.vtt"
srcLang="en"
label="English"
/>
</video>Modül listesi sidebar + video carousel
Sol sidebar: modül + ders ağacı. Aktif ders işaretli. Tamamlananlar yeşil tik. Sonraki ders auto-play.
<div className="grid grid-cols-1 lg:grid-cols-4 h-screen">
<aside className="lg:col-span-1 overflow-y-auto border-r bg-gray-50">
{modules.map(m => (
<div key={m.id} className="border-b">
<h3 className="p-4 font-bold">{m.title}</h3>
{m.lessons.map(l => (
<Link
key={l.id}
href={`/courses/${course.slug}/lessons/${l.slug}`}
className={`flex items-center gap-3 p-3 ${l.id === currentLessonId ? 'bg-blue-50 border-l-4 border-blue-600' : 'hover:bg-gray-100'}`}
>
{l.completed ? <CheckCircleIcon className="text-green-500" /> : <CircleIcon />}
<div className="flex-1">
<p className="text-sm font-medium">{l.title}</p>
<p className="text-xs text-gray-500">{l.duration}</p>
</div>
</Link>
))}
</div>
))}
</aside>
<main className="lg:col-span-3 flex flex-col">
<MuxPlayer playbackId={lesson.muxId} className="aspect-video" />
<div className="p-6 overflow-y-auto flex-1">
<MDXRemote source={lesson.notes} />
<div className="mt-8 flex justify-between">
<Link href={prevLesson?.url} className="btn-secondary">← Önceki</Link>
<Link href={nextLesson?.url} className="btn-primary">Sonraki →</Link>
</div>
</div>
</main>
</div>Video tamamlanma + sertifika tetiği
Tüm dersler tamamlandığında otomatik sertifika üret + e-posta at.
// Lesson complete edildiğinde
const allComplete = await checkAllLessonsComplete(courseId, userId);
if (allComplete) {
// Sertifika üret
const certificateUrl = await generateCertificatePDF({
userName: user.name,
courseName: course.title,
completionDate: new Date(),
});
// DB'ye kaydet
await supabase.from('certificates').insert({
user_id: userId,
course_id: courseId,
certificate_url: certificateUrl,
issued_at: new Date(),
});
// E-posta gönder
await sendEmail({
to: user.email,
subject: `🎓 ${course.title} kursunu tamamladın!`,
template: 'certificate-issued',
data: { userName: user.name, courseName: course.title, certificateUrl },
});
}Claude Code'a Yapıştır
Köşeli parantezleri kendi içeriğinizle değiştirin.
Kurs DB schema
Aç ▾Kapat ▴
Supabase için online kurs platformu schema'sı: Tablolar: - courses (id, slug, title, description, hero_image, price, instructor_id, is_published) - modules (id, course_id, order, title, description) - lessons (id, module_id, order, slug, title, description, video_mux_id, duration_seconds, content_mdx, slides_pdf_url) - enrollments (id, user_id, course_id, enrolled_at, expires_at) - lesson_progress (id, user_id, lesson_id, watched_seconds, completed, completed_at) - quizzes (id, lesson_id, title, passing_score) - quiz_questions (id, quiz_id, question, type, options, correct_answer, explanation) - quiz_attempts (id, user_id, quiz_id, answers, score, passed, attempted_at) - assignments (id, lesson_id, title, instructions, max_file_size) - assignment_submissions (id, user_id, assignment_id, file_url, text_answer, instructor_feedback, grade, submitted_at) - certificates (id, user_id, course_id, certificate_url, issued_at) - forum_posts (id, lesson_id, user_id, content, created_at) - forum_replies (id, post_id, user_id, content, created_at) RLS politikaları: - enrollments: kullanıcı kendininkini, eğitmen kendi kursunun tüm enrollment'larını görür - lesson_progress: sadece kendi progress'i - assignments: enrolled kullanıcılar görür - forum: enrolled kullanıcılar okur/yazar İndeksler + migrations.
Video player + progress kaydı
Aç ▾Kapat ▴
Kurs ders sayfası kur: Layout: - Sol sidebar (lg:col-span-1): modül + ders ağacı, ilerleme bar (% tamamlandı) - Sağ ana içerik (lg:col-span-3): - Mux Video Player (responsive, hız kontrolü, captions) - Altında: ders notları (MDX), kaynaklar, slaytlar PDF indir - En altta: tartışma forumu (yorumlar) - Yukarıda: Önceki / Sonraki ders butonları - Tamamlandı butonu (manuel + otomatik %90 izlendiğinde) Functions: - Video time update → her 5sn Supabase'e progress kaydet - Sayfa açılışında en son izleme zamanından devam - Video bittiğinde otomatik 'tamamlandı' + sonraki derse 10sn countdown - Tamamlama yüzdesi sidebar'da gerçek zamanlı güncellensin Mux Player kullanılsın, fallback olarak Cloudflare Stream.
Sertifika üretim sistemi
Aç ▾Kapat ▴
Kurs tamamlama sertifikası sistemi: Trigger: Tüm dersler 'completed' olduğunda (lesson_progress.completed = true tüm dersler için) İşlem: 1. /api/certificates/generate endpoint 2. React PDF ile sertifika üret: - Kurs adı, öğrenci adı, tamamlama tarihi - Eğitmen imzası (görsel) - Şirket logo - QR kod (doğrulama URL'sine) - Sertifika ID (UUID) 3. PDF'i Supabase Storage'a yükle, URL al 4. certificates tablosuna kaydet 5. Resend ile e-posta gönder (template + PDF attached) 6. Öğrenci panelinde 'Sertifikalarım' sayfasında göster Doğrulama: - /verify/[certificate-id] sayfası - QR kod scan edilince doğrulama: kurs adı + öğrenci + tarih + 'Geçerli' badge - Eğer ID yok veya iptal edildiyse 'Geçersiz' React PDF + qrcode kütüphaneleri kullan.
Bu rehberden gerçek bir vaka
Brief
Türkçe Next.js + Supabase eğitmeni. 5 kurs satacak: 'Sıfırdan başla', 'SaaS kur', 'Database', 'Auth', 'Deploy'. Her biri 499 TL, paket 1999 TL.
Sonuç
3 haftada: 5 kurs platformu + Mux video + Stripe (TL native iyzico) + sertifika sistemi + tartışma forumu. İlk 100 öğrenci ön kayıt.
Bunlardan kaçının
Hata
YouTube'a unlisted yükledim, embed ettim
Çözüm
YouTube link kopyalanır, leakelenebilir. Mux veya Cloudflare = signed URL + watermark, korur. Kurs ücretsizse YouTube OK.
Hata
Video çok uzun (60 dk) — drop-out yüksek
Çözüm
Her ders max 10-12 dk. Uzun konuyu birkaç derse böl. İzleme tamamlama %85+ olur.
Hata
Sertifika hiç vermiyor
Çözüm
Insanlar sertifikayı önemser (LinkedIn). Tamamlamayı 2-3× artırır. Otomatik PDF üret — 2 saatlik iş.
Online Kurs Platformu için sık sorular
Teachable yerine kendi platformum mantıklı mı?▾
10+ kurs satıyorsanız ve ayda 100+ öğrenci varsa kesinlikle. Teachable $99/ay + ürün başına komisyon = pahalı. Kendi sistem: ilk 2 hafta yatırım, sonra ekstrası yok.
Mux pahalı mı? Cloudflare daha mı iyi?▾
Mux premium ($20 başlangıç + view başına ücret). Cloudflare $5/ay + dakika başına ucuz. Az izleyici: Cloudflare. Ciddi kurs satıyorsan Mux (player kalitesi + analytics).
Drip content (zaman içinde açılan) nasıl?▾
Her ders'e 'available_at' field ekle. Kayıttan X gün sonra erişilebilir. Süreklilik etkisi, abandonment azaltır. Tek seferde tüm içerik yerine 4 hafta drip.
Diğer site türleri
Landing Page
Tek sayfa, tek amaç — ürün lansmanı veya kampanya.
İncele
Kurumsal Site
Hakkımızda, hizmetler, blog, iletişim — tam kurumsal yapı.
İncele
Portfolyo
Tasarımcı, fotoğrafçı, geliştirici için kişisel showcase.
İncele
Blog / İçerik Sitesi
SEO odaklı, MDX/Markdown destekli içerik platformu.
İncele