Files
bogazici-api/backend_ve_admin_dokuman.md
2026-03-27 10:41:54 +03:00

43 KiB
Raw Permalink Blame History

Boğaziçi Denizcilik - Backend (Laravel) & Admin Panel (Next.js) Gereksinim Dökümanı (v2)

Bu döküman, mevcut Next.js (Frontend) projenizin dinamik veri altyapısını bir Laravel API'sine bağlamak ve bu verileri yönetmek için tamamen ayrı bir Next.js Admin Panel geliştirmek üzere hazırlanmıştır.

(v2 Güncellemesi: Gelişmiş Setting altyapısı, Pagination standartları, Modüler Page Builder API'leri, Soft Deletes, Caching, Audit Logs, Rate Limiting ve Çok Dilli (i18n) destek notları eklenmiştir.)

Çok Dilli (i18n) Altyapı Notu: Şimdilik v1 aşamasında tek dil (TR) olarak çıkılacaktır. Ancak v2+ versiyonları için i18n (Çoklu dil) planlanıyorsa, veritabanı tablolarında JSON field veya harici translations tablosu yaklaşımı değerlendirilecektir.

🤖 GitHub Copilot (VS Code) İçin Geliştirme Talimatı (Master Prompt): Laravel Herd ile kendi oluşturduğunuz projeyi VS Code'da açtıktan sonra, Copilot Chat'e (veya Cursor/Cline'a) şu mesajı yazmanız yeterlidir:

"Merhaba Copilot, bu projeyi Laravel 12+ ile geliştireceğiz. Lütfen ana dizindeki backend_ve_admin_dokuman.md dosyasını dikkatlice baştan sona oku ve mimariyi kavra. Ardından şu işlemleri benim onayımı alarak adım adım kodlamaya başla:

  1. Önce "1. Veritabanı Şeması" bölümündeki tüm tablolar için Laravel Migration, Model ve Factory dosyalarını oluştur. Önemli tablolarda SoftDeletes kullan. Bu adımı bitirince onayımı bekle.
  2. Ardından "REST API" ve "Klasör Mimarisi" bölümüne geç. Kesinlikle spagetti controller yazma. Her modül için sırayla; FormRequest, DTO, Action (Service), Repository ve en son Controller ile api.php rotalarını oluştur. Response standartlarına ve Caching kurallarına dikkat et.
  3. Her modülü (Örn: Courses, Categories) tek tek kodla ve her modül bitiminde bana bilgi ver. Asla tüm projeyi tek seferde yazmaya çalışma."

1. Veritabanı Şeması (Laravel Modelleri & Migrations)

(Güvenlik: Kaza eseri veri kayıplarını önlemek için yetki, kurs, kategori ve lead tablolarında SoftDeletes kullanılacaktır.)

1.0. users & roles (Yetkilendirme / Auth)

  • Laravel'in standart users tablosu. Admin panele giriş yapacak personeli temsil eder.
  • Sisteme Spatie Permission paketi kurularak Role ve Yetki altyapısı tanımlanacaktır (Örn: super-admin, editor).
  • SoftDeletes aktif olmalıdır.

1.1. categories (Eğitim Kategorileri)

  • id (PK)
  • slug (string, unique) - Örn: guverte
  • label (string) - Örn: Güverte Eğitimleri
  • desc (text, nullable)
  • image (string, nullable) - Sadece görsel path'i tutar
  • meta_title (string, nullable) - SEO Title
  • meta_description (text, nullable) - SEO Description
  • created_at, updated_at, deleted_at (SoftDeletes)

1.2. courses (Eğitimler/Kurslar)

  • id (PK)
  • category_id (FK -> categories.id)
  • slug (string, unique)
  • title (string)
  • sub (string, nullable) - Örn: STCW II/1
  • desc (text) - Kısa açıklama
  • long_desc (longText) - Detaylııklama
  • duration (string) - Örn: 5 Gün
  • students (integer, default: 0) - Kayıtlı öğrenci sayısı
  • rating (decimal: 2,1, default: 5.0)
  • badge (string, nullable) - Örn: Simülatör
  • image (string, nullable) - Sadece path tutar
  • price (string, nullable)
  • includes (json, nullable) - Fiyata dahil olanlar listesi. Örn: ["Eğitim materyali", "Sertifika ücreti", "İkram"]
  • requirements (json, nullable) - Katılım koşulları/gereksinimler listesi. Örn: ["18 yaşını doldurmuş olmak", "Lise mezunu olmak"]
  • meta_title (string, nullable) - SEO Title
  • meta_description (text, nullable) - SEO Description
  • scope (json, nullable) - Eğitim kapsamı konu başlıkları dizisi. Örn: ["Ana makine sistemleri", "Yağlama ve soğutma sistemleri", "Yakıt sistemleri"]
  • standard (string, nullable) - Uyum standardı. Örn: "STCW / IMO Uyumlu"
  • language (string, nullable, default: "Türkçe") - Eğitim dili
  • location (string, nullable) - Kursun varsayılan lokasyonu. Örn: "Kadıköy, İstanbul"
  • created_at, updated_at, deleted_at (SoftDeletes)

1.3. course_schedules (Takvim / Planlanan Eğitimler)

  • id (PK)
  • course_id (FK -> courses.id)
  • start_date (date) - Örn: 2026-02-24
  • end_date (date) - Örn: 2026-02-28
  • location (string) - Örn: Kadıköy veya Online
  • quota (integer) - Toplam Kontenjan
  • available_seats (integer) - Kalan Koltuk (Otomatik quota - reserved_count mantığıyla çalışmalı veya admin üzerinden manuel update edilmeli. Proje ilerleyişine göre netleşecek).
  • is_urgent (boolean, default: false) - Sınırlı Kontenjan uyarısı
  • created_at, updated_at

1.4. announcements (Duyurular & Haberler)

  • id (PK)
  • slug (string, unique)
  • title (string)
  • category (string, enum) - Tutarsızlığı önlemek için Enum kullanılmalı: announcement | news | event
  • excerpt (text)
  • content (longText)
  • image (string, nullable)
  • is_featured (boolean, default: false)
  • meta_title (string, nullable)
  • meta_description (text, nullable)
  • published_at (timestamp) - Frontend'deki day/month yerine gerçek tarih tutulmalı
  • created_at, updated_at

1.5. hero_slides (Ana Sayfa Slider)

  • id (PK)
  • label (string) - Örn: STCW Sertifikasyonu
  • title (string) - Satır başı için \n destekli
  • description (text)
  • image (string, nullable)
  • order (integer, default: 0)
  • is_active (boolean, default: true)
  • created_at, updated_at

1.6. leads (Ön Kayıtlar / Form Başvuruları)

  • id (PK)
  • name (string)
  • phone (string)
  • target_course (string, nullable) - İlgilenilen eğitim
  • education_level (string, nullable) - Öğrenim durumu
  • subject (string, nullable) - İlgilenilen konu (Danışmanlık formu için Örn: stcw, kaptanlik, belge, diger)
  • message (text, nullable) - Ziyaretçinin ek mesajı (Danışmanlık formu için)
  • status (string, default: 'new') - new, contacted, enrolled, rejected
  • notes (text, nullable) - Admin notları
  • is_read (boolean, default: false) - Admin panelde okunmamışları vurgulamak için
  • source (string) - hero_form | contact_form | consultation_form | whatsapp_widget
  • utm (json, nullable) - utm_source, utm_campaign, vb.
  • consent_kvkk (boolean, default: false)
  • consent_text_version (string, nullable)
  • created_at, updated_at, deleted_at (SoftDeletes)

1.7. menus (Dinamik Menü & Navigasyon Yönetimi)

Tüm site üst (Navbar) ve alt (Footer) bağlantılarının, Mega Menü içeriklerinin admin panelinden yönetilebilmesi için.

  • id (PK)
  • location (string) - Örn: header_main, footer_corporate, footer_education, footer_quicklinks
  • label (string) - Menüde Gözükecek Metin Örn: "Hakkımızda"
  • url (string) - Örn: "/kurumsal/hakkimizda"
  • type (string, default: 'link') - link (Normal Link) | mega_menu_education (Özel Hover Mega Menü) | mega_menu_calendar (Takvim Dropdown)
  • parent_id (integer, nullable) - Alt menüler için (Self Referencing FK)
  • order (integer, default: 0) - Sıralama
  • is_active (boolean, default: true)
  • created_at, updated_at

1.8. comments (Eğitim ve Blog Yorumları / Soru-Cevap)

Kullanıcıların üye olmadan, sadece Ad, Soyad ve Telefon numarası girerek Eğitimlere veya Duyurulara/Bloglara yorum yapabileceği ve adminlerin cevaplayabileceği sistem.

  • id (PK)
  • commentable_id (integer) - Hangi eğitime/duyuruya yapıldı? (Polymorphic Relation)
  • commentable_type (string) - App\\Models\\Course veya App\\Models\\Announcement
  • name_surname (string) - Kullanıcının Adı Soyadı
  • phone (string) - Kullanıcının Telefon Numarası (Soru sorana ulaşmak gerekirse)
  • body (text) - Yorum / Soru metni
  • admin_reply (text, nullable) - Admin'in verdiği cevap (Önyüzde Admin Yanıtı olarak gözükecek)
  • is_approved (boolean, default: false) - Admin onaylamadan sitede gözükmemeli
  • created_at, updated_at, deleted_at (SoftDeletes)

1.9. faqs (Sıkça Sorulan Sorular)

Frontend'deki /sss sayfası ve anasayfadaki FAQ bileşeni için. Adminler soru-cevapları kategorili olarak yönetebilir.

  • id (PK)
  • category (string) - egitimler | kayit | iletisim (Tab bazlı filtreleme için)
  • question (text) - Soru metni
  • answer (text) - Cevap metni
  • order (integer, default: 0) - Kategori içi sıralama
  • is_active (boolean, default: true) - Pasif olanlar önyüzde gösterilmez
  • created_at, updated_at

1.10. guide_cards (Eğitim Rehberi Kartları)

Frontend'deki /egitim-rehberi sayfasındaki kariyer yönlendirme kartları için. Admin panelden yönetilebilir.

  • id (PK)
  • title (string) - Örn: "Yeni Başlayanlar", "Yat Kaptanları"
  • description (text) - Kart içeriği açıklaması
  • icon (string) - Lucide icon adı (Örn: anchor, compass, shield, briefcase)
  • color (string) - Gradient renk sınıfı (Örn: from-blue-500 to-blue-700)
  • link (string) - Yönlendirme URL'i (Örn: /egitimler/stcw)
  • order (integer, default: 0) - Sıralama
  • is_active (boolean, default: true)
  • created_at, updated_at

1.11. settings (Sistem Ayarları)

Admin panelinde otomatik tab/sekme yapısı kurmak ve public/private yalıtımı sağlamak için güçlendirilmiş yapı. Logo, sosyal medya linkleri gibi statik veriler buradan yönetilir.

  • id (PK)
  • group (string) - general | contact | social | seo | forms | footer | guide
  • key (string, unique)
  • value (text/json, nullable)
  • type (string) - text | textarea | image | boolean | json | richtext
  • is_public (boolean, default: true) - Public API'de görünsün mü? (Örn: hero_form_email gizli kalmalıdır).
  • created_at, updated_at

Önerilen Settings Key Listesi (Otomatik Seeder ile Girecekler):

  • Genel: site_name, site_logo, footer_logo, favicon
  • Anasayfa İçerikleri (Sabit Alanlar): home_about_title, home_about_text, home_about_image_1, home_about_image_2, home_stats_students, home_stats_instructors, home_stats_courses (Anasayfadaki "Biz Kimiz", "Kurum Hakkında" veya istatistik alanlarındaki resim/yazıların yönetimi için).
  • İletişim: contact_email, contact_cc_emails, phone_1, phone_2, whatsapp_phone, address, google_maps_embed_url, working_hours
  • Sosyal Medya (Dinamik Logolar / Linkler): instagram_url, facebook_url, tiktok_url, x_url, youtube_url, linkedin_url (Bu alanlar boş bırakılırsa önyüzde iconlar gizlenmelidir).
  • SEO: default_meta_title, default_meta_description, canonical_base, og_default_image, robots_indexing_enabled
  • Formlar / KVKK / Kampanya: lead_notify_email, kvkk_text, privacy_policy_url, newsletter_title, newsletter_desc (E-bülten ve "Sana özel kampanyalar" kutusundaki metinler).
  • Eğitim Rehberi: guide_page_title, guide_page_subtitle, guide_cta_title, guide_cta_text, guide_cta_button_text, guide_cta_button_url (Eğitim Rehberi sayfasındaki başlık, alt metin ve CTA alanlarının yönetimi).
  • Danışmanlık: consultation_page_title, consultation_page_subtitle, consultation_form_title (Danışmanlık sayfasının başlık ve açıklama alanlarının yönetimi).

2. Laravel REST API Uç Noktaları (Endpoints) & Standartları

Cevap (Response) Format Standardı: Frontend tarafının hızlı ilerlemesi için tüm başarılı API listeleme talepleri paginate ve metadata içermeli, Laravel Resource üzerinden standartlaştırılmalıdır.

  • Liste endpoint'leri: { "data": [], "meta": { "total": 0 }, "links": { } }
  • Tekil endpoint'ler: { "data": { } }

Parametrik Arama, Filtreleme, Sıralama:

  • GET /api/v1/courses?category=guverte&search=stcw&sort=title&page=1
  • GET /api/v1/announcements?category=news&featured=1&sort=-published_at&page=1

Public API (Frontend İçin - api/v1/...)

(Performans için aktif olan sık kullanılan Public GET endpoint'leri Laravel Cache / Redis arkasında çalıştırılmalıdır. Veri Admin Panel'den güncellenince Cache Event ile temizlenmelidir.)

  • GET /api/v1/settings -> is_public=true olan ayarları döner.
  • GET /api/v1/hero-slides -> Aktif slider içeriklerini sıralı getirir.
  • GET /api/v1/menus -> Header ve Footer navigasyon ağacını hiyerarşik getirir.
  • GET /api/v1/categories -> Kategorileri listeler.
  • GET /api/v1/courses -> Eğitimleri listeler.
  • GET /api/v1/courses/{slug} -> Tekil eğitim detayı.
  • GET /api/v1/schedules -> Yaklaşan takvim eğitimlerini getirir. (Tarihe göre sıralı)
  • GET /api/v1/announcements -> Duyuruları (featured olanlar dahil) getirir.
  • GET /api/v1/announcements/{slug} -> Tekil duyuru detayı.
  • GET /api/v1/comments/{type}/{id} -> Bir kursun veya blogun onaylanmış (is_approved=true) yorumlarını ve admin cevaplarını getirir.
  • POST /api/v1/comments -> Ziyaretçiden yeni yorum/soru kaydı alır (Spam/Rate Limiting zorunlu).
  • GET /api/v1/faqs -> Aktif SSS verilerini kategorili olarak getirir. ?category=egitimler filtresi desteklenmeli.
  • GET /api/v1/guide-cards -> Eğitim Rehberi kartlarını sıralı getirir.
  • GET /api/v1/pages/{slug} -> Page builder bloklarını sırayla (order_index) getirir. (Sadece /page/ altındaki dinamik sayfalar için)
  • POST /api/v1/leads -> Ön kayıt formu alımı. source alanı ile form kaynağı (hero_form, contact_form, consultation_form) belirlenir. (Spam koruması için IP bazlı Rate Limiting - Throttle uygulanmalıdır. Dakikada maks 2-3 gibi)
  • GET /api/v1/sitemap-data -> Frontend'in dinamik sitemap.xml oluşturması için tüm public slug'ları ve updated_at tarihlerini döner. (Bkz: Bölüm 7.4)

Protected API (Admin Panel İçin - api/admin/...)

Tüm yetkili işlemler burada yalıtılmıştır.

  • POST /api/admin/login -> Bearer token döndürür (Sanctum/Passport).
  • GET /api/admin/me -> Giriş yapan admin detaylarını + Spatie Permission rollerini/izinlerini döner.
  • POST /api/admin/uploads -> Multipart/form-data kabul eder. Standart resim yükleme ucudur. DB'ye URL değil path kaydeder. Response: { "path": "uploads/...", "url": "https://.../uploads/..." }
  • Modüller için tüm standart POST (Oluşturma), PUT/PATCH (Güncelleme), DELETE (Silme) uçları.
  • Menü Yönetimi:
    • CRUD /api/admin/menus -> Menü ekleme ve ağaç dökümü
    • POST /api/admin/menus/reorder -> Sürükle-Bırak sonrası hiyerarşiyi (parent_id ve order) toplu güncelleme
  • SSS (FAQ) Yönetimi:
    • CRUD /api/admin/faqs -> Soru ekleme, düzenleme, silme, listeleme
  • Eğitim Rehberi Kartları:
    • CRUD /api/admin/guide-cards -> Kart ekleme, düzenleme, silme, listeleme
  • Page Builder Admin uçları:
    • CRUD /api/admin/pages
    • CRUD /api/admin/pages/{id}/blocks
    • POST /api/admin/pages/{id}/blocks/reorder -> Sürükle bırak ile sıra (order_index) güncelleme.

3. Laravel Katmanlı Mimari (Repository Pattern) Uygulama Standartları

Backend kodlanırken kesinlikle Spagetti Controller (Controller içine direkt Course::create() yazmak) kullanılmayacaktır. Tüm iş mantığı ve veritabanı sorguları şu katmanlara ayrılmalıdır:

Önerilen Devasa (Enterprise) Klasör Mimarisi (app/):

app/
 ├── Http/
 │    ├── Controllers/
 │    │    └── Api/
 │    │         └── CourseController.php       # HTTP İsteğini alır, DTO'yu oluşturup Action'a yollar. Geriye Response döner.
 │    ├── Requests/
 │    │    └── StoreCourseRequest.php          # Gelen verilerin validasyon zorunluluklarını (required, string) yapar.
 │    └── Resources/
 │         └── CourseResource.php              # {YENİ} Frontend'e gidecek JSON formatını filtreler ve standartlaştırır (Presenter).
 ├── DTOs/
 │    └── CourseData.php                       # Validasyonu geçmiş temiz veriyi, tiplendirilmiş Nesneye (DTO) dönüştürür.
 ├── Actions/ (veya Services/)
 │    └── Course/
 │         └── CreateCourseAction.php          # Tüm "İş Mantığı". İndirim hesapla, Event fırlat, Repository'e yolla.
 ├── Repositories/
 │    ├── Contracts/
 │    │    └── CourseRepositoryInterface.php   # Sınırlar ve Kurallar (Interface)
 │    └── Eloquent/
 │         └── CourseRepository.php            # Veritabanı (DB) sorguları sadece buradadır (Course::create()).
 ├── Models/
 │    └── Course.php                           # Tablo yapısı, İlişkiler (Relations)
 ├── Enums/
 │    └── CourseStatus.php                     # Güvenli Sabitler
 ├── Events/
 │    └── CourseCreatedEvent.php               # Asenkron Olaylar (Decoupling için) -> Cache temizleme vb. burada ateşlenir.
 ├── Listeners/
 │    └── NotifySubscribersListener.php        # Olayı dinleyen arka plan işlemleri
 ├── Policies/
 │    └── CoursePolicy.php                     # Yetki ve Rol kontrolleri (Örn: Yetkisiz kişi kurs silemez)
 ├── Exceptions/
 │    └── CourseFullException.php              # Domain'e özel hata sınıfları (400)

Kusursuz (Ultimate) Veri Akış Yönü: RouteMiddleware (Auth)Policy (Yetki)FormRequest (Validasyon)ControllerDTOActionRepository (Interface)ModelDB (İşlem Başarılıysa)Action => Event Fırlatır / Activity Log Atılır (Controller Çıkışı)API Resource (JSON Formatlama)Next.js FrontEnd

Audit Log / Kullanıcı İşlem Kayıtları Notu: Sisteme yetkili girişler yapılacağı için (Super Admin, Editor vs) veri güncellemelerini, silmeleri (SoftDelete edilen datalar) izlemek amacıyla projeye spatie/laravel-activitylog paketi kurulması, oluşan Transaction'ların tutulması önerilir.


4. Next.js Admin Panel Mimarisi Önerisi

Admin Paneli tamamen ayrı bir Next.js projesi olarak (Örn: admin.bogazicidenizcilik.com veya localhost:3001 portunda) kurulmalıdır.

Mimari Prensip (Katmanlı Mimari - Layered Architecture):

Kodların tek bir klasöre yığılmasını önlemek için Frontend kodları işlevselliğe göre ayrılmalıdır. Örnek src/ mimarisi:

  • src/app/: Sadece sayfalar (Routing) ve sayfa Layout'ları.
  • src/components/: Ortak kullanılan UI elementleri (Button, Input, Table, Ortak ImageUpload Bileşeni).
  • src/features/: Modül bazlı klasörleme (Örn: features/courses/components, features/courses/api, features/courses/types).
  • src/lib/: Axios instance, yardımcı fonksiyonlar.

Önerilen Klasör Dizilimi (src/app/ Route Alanı):

src/app/
 ├── (auth)/
 │    └── login/page.tsx           # Giriş ekranı (Kullanıcı Adı, Şifre -> Laravel Sanctum Token)
 ├── (dashboard)/
 │    ├── layout.tsx               # Sol Sidebar ve Üst Header kapsayıcısı (Role-based menu gösterimi)
 │    ├── page.tsx                 # Dashboard Özeti (İstatistik kartları: Toplam Öğrenci, Yeni Formlar)
...

Tüm Admin Modülleri ve Ekran Detayları

4.1. Kategoriler (/categories)

  • page.tsx: Kategori Tablosu (Resim, Kategori Adı, İşlemler (Düzenle/Sil)).
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • label (Text Input) - Kategori Adı
    • slug (Text Input) - (Girilen isimden otomatik slug yaratılmalı)
    • desc (Textarea) - Kısa Tanıtım
    • image (Upload Component) - POST /api/admin/uploads tetikleyecek tek kullanımlık standart bileşen
    • SEO Alanı: meta_title, meta_description (Text Input)

4.2. Eğitimler (/courses)

  • page.tsx: Eğitimler Tablosu (Kategorisine göre filtrelenebilir, Öğrenci Sayısı vs.).
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • Genel Bilgiler:
      • title, sub, category_id, price, duration, badge
    • İçerik Editörü:
      • desc (Textarea)
      • longDesc (Rich Text Editor - CKEditor/Quill/Notion-stile Editor)
      • image (Upload Component)
    • Dinamik Diziler (Field Arrays / Repeaters):
      • includes (Dynamic Input Array) - "Fiyata Dahil Olanlar" (+)
      • requirements (Dynamic Input Array) - "Kayıt Şartları" (+)
    • SEO Alanı: meta_title, meta_description (Text Input)

4.3. Eğitim Takvimi / Planlama (/schedules)

  • page.tsx: Takvim Tablosu (Kurs Adı, Başlangıç, Bitiş, Kontenjan).
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • course_id, start_date, end_date, location, quota, available_seats
    • is_urgent (Switch / Checkbox) - "Son 3 Gün" uyarı ateşleyicisi

4.4. Duyurular ve Haberler (/announcements)

  • page.tsx: Olayların Tablosu.
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • title, category (Seçim ile), excerpt, content (RTE), image (Upload), meta_title, meta_description
    • published_at (Date/Time Picker) - İleri tarihli yayınlanma opsiyonu
    • is_featured (Switch) - "Ana Sayfada Manşet Yap" onay kutusu

4.5. Ön Kayıt Başvuruları (CRM) (/leads)

  • page.tsx: Form başvuruları listesi. is_read = false olan kayıtlar kalın (bold) veya fosforlu arka planla ayırt edici gösterilmelidir.
  • [id]/page.tsx (Görüntüleme Müşteri Detayı):
    • Gelen veriler: Adı, Telefon, Durumu, İlgilendiği Eğitim, Kaynak (Source), UTMEketleri, KVKK Onay Vrs. (Salt Okunur - Read/Only).
    • Yalnızca Tıklandığında backend'e PATCH isteği atılıp is_read = true yapılır.
    • Admin işlemleri:
      • status (Select) - (Yeni, Arandı, Kayıt Oldu, İptal)
      • notes (Textarea) - Admin/Müşteri Temsilcisi iç notları. Form POST ile güncellenir.

4.6. Menü ve Navigasyon Yönetimi (/menus)

  • page.tsx: Menü lokasyonlarına (header_main, footer_corporate, footer_education, vb.) göre sekmeli (tab) bir liste. Her lokasyon için alt alta ağaç (tree) görünümlü kayıtlar. Sürükle-bırak (Drag & Drop) ile POST /api/admin/menus/reorder tetiklenerek sıralama ve parent/child ilişkisi hızlıca kurulabilmeli.
  • [id]/page.tsx (Ekleme / Düzenleme):
    • location (Select) - Header Ana Menü mü Yoksa Footer mı?
    • label (Text Input) - "Eğitimler"
    • url (Text Input) - "/egitimler"
    • type (Select) - Normal Link mi (link), Eğitim Mega Menüsü mü (mega_menu_education), Takvim mi (mega_menu_calendar)
    • parent_id (Select) - Bir ana menünün altına eklenecekse o ana menü seçilir.
    • is_active (Switch)

4.7. Yorum / Soru-Cevap Yönetimi (/comments)

  • page.tsx: Kullanıcılardan (üye olmadan) Eğitim ve Bloglara gelen tüm soruların/yorumların düştüğü ekran. is_approved = false olanlar (yeni gelenler) belirgin şekilde listelenir.
  • [id]/page.tsx (Yorum Onay ve Yanıtlama):
    • Gelen veriler: Adı Soyadı, Telefon Numarası, Yorum Yapılan İçerik (Kurs Adı vs), Yorum Metni (Read-Only).
    • admin_reply (Textarea) - Yorum/soruyu cevaplamak için adminin dolduracağı alan.
    • is_approved (Switch) - Yorumun sitede herkes tarafından gözüküp gözükmeyeceği.

4.8. SSS / Sıkça Sorulan Sorular Yönetimi (/faqs)

  • page.tsx: FAQ Tablosu (Kategori, Soru, Aktif/Pasif durumu). Kategoriye göre filtrelenebilir.
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • category (Select) - egitimler | kayit | iletisim
    • question (Textarea) - Soru metni
    • answer (Textarea / Rich Text) - Cevap metni
    • order (Number Input) - Kategori içi sıralama
    • is_active (Switch) - Aktif/Pasif

4.9. Eğitim Rehberi Kartları Yönetimi (/guide-cards)

  • page.tsx: Rehber kartlarının listesi (Başlık, Icon, Link, Sıra).
  • [id]/page.tsx (Ekleme / Düzenleme Formu):
    • title (Text Input) - Kart başlığı (Örn: "Yeni Başlayanlar")
    • description (Textarea) - Açıklama metni
    • icon (Select) - Lucide icon seçimi (anchor, compass, shield, briefcase vb.)
    • color (Text Input / Color Picker) - Gradient renk sınıfı
    • link (Text Input) - Yönlendirme URL'i
    • order (Number Input) - Sıralama
    • is_active (Switch)

4.10. Sitenin Genel Ayarları (/settings)

Bu tek bir sayfada çalışır:

  • Sayfa ilk açıldığında GET /api/admin/settings ile tüm satırları çeker.
  • group verisine göre yatay ya da dikey Tabs (Sekmeler) oluşturur (Genel, Anasayfa, İletişim, Sosyal Medya, SEO, Formlar, Eğitim Rehberi, Danışmanlık).
  • Anasayfa Sekmesi: Anasayfadaki "Neden Biz", "Biz Kimiz", info/görsel alanlarındaki başlıklar (home_about_title), metinler (home_about_text) ve resimlerin (home_about_image_1) yönetimi.
  • Sosyal Medya Sekmesi: Tüm hesapların (Instagram, Facebook, Tiktok, LinkedIn vb.) linkleri buraya girilir. Frontend, boş olmayan değerleri render eder.
  • Eğitim Rehberi Sekmesi: Eğitim rehberi sayfasının başlık, alt metin ve CTA (Call to Action) alanlarının yönetimi.
  • Danışmanlık Sekmesi: Danışmanlık sayfasının başlık ve açıklama metinleri.
  • type verisine göre ekranda Text Input, Textarea veya Toggle Switch render eder. Kaydederken array olarak tek bir PATCH isteğinde sunucuya yollar.

5. Mevcut Frontend Projesi (Boğaziçi) Entegrasyon Adımları

Backend ve Admin Panel hazır olduğunda, mevcut statik yapınızda şu işlemler gerçekleştirilecektir:

  1. Çevresel Değişkenler: .env.local içine NEXT_PUBLIC_API_URL=http://api.bogazici.test/api/v1 eklenmeli. Yüklenen resimleri parse edebilmek için NEXT_PUBLIC_ASSET_URL=http://api.bogazici.test konulmalı.
  2. Data Fetching:
    • Statik src/data/*.ts dosyaları silinmeli.
    • Tüm sayfalarda fetch kullanılarak (veya Axios) ISR yapısıyla veriler çekilmeli.
    • Örnek: const res = await fetch(\${process.env.NEXT_PUBLIC_API_URL}/courses`, { next: { revalidate: 3600 } });`
  3. Form Gönderimi: Hero'daki form submit edildiğinde veriler POST /api/v1/leads ucuna JSON olarak yollanmalı.

6. Dinamik Sayfalar İçin Headless Page Builder (/page/ Rotası)

Kapsam Notu: Page Builder sistemi yalnızca /page/ rotası altında oluşturulan dinamik sayfalar için kullanılacaktır. Kurumsal sayfalar (/kurumsal/hakkimizda, /kurumsal/vizyon-misyon, vb.) ve /danismanlik, /egitim-rehberi, /sss gibi özel tasarımlı sayfalar frontend'de statik bileşenler olarak kalacak ve verilerini kendi API endpoint'lerinden veya settings tablosundan çekeceklerdir.

Admin panelden yeni landing page'ler, kampanya sayfaları veya özel içerik sayfaları oluşturmak için Modüler Blok Sistemi kullanılacaktır.

Mevcut Frontend (Boğaziçi Denizcilik) Tarafında Okunması

Örnek src/app/page/[slug]/page.tsx Kullanımı:

export default async function DynamicPage({ params }: { params: { slug: string } }) {
  // 1. Laravel'den sayfanın aktif bloklarını çek
  const page = await fetch(`.../api/v1/pages/${params.slug}`).then(r => r.json());

  return (
    <main>
      {/* 2. Gelen blokları (Lego parçalarını) sırası ve tipine göre render et */}
      {page.blocks.map((block) => {
        switch (block.type) {
          case 'hero':
            return <HeroBlock key={block.id} data={block.content} />;
            
          case 'stats_grid':
            return <StatsBlock key={block.id} data={block.content} />;
            
          case 'text_image':
            return <StoryBlock key={block.id} data={block.content} />;
            
          default:
            return null;
        }
      })}
    </main>
  );
}

Özet Tavsiye: Geliştirme süresi uzasa da, bir kere kurulduğunda kodlamaya bir daha dokunmadan şirketin sayısız ve benzersiz tasarımda yeni sayfalar veya landing page'ler üretmesini sağlar. Endüstri standardı bir çözümdür.


7. SEO & Yapısal Veri (Structured Data) Standartları

Sitenin arama motorlarında üst sıralarda yer alabilmesi için backend API'nin aşağıdaki SEO gereksinimlerini eksiksiz karşılaması gerekmektedir.

7.1. Meta Alanları (Her Modülde Zorunlu)

Aşağıdaki tablolarda meta_title ve meta_description alanları mevcuttur ve zorunlu olarak doldurulmalıdır:

  • categories meta_title, meta_description
  • courses meta_title, meta_description
  • announcements meta_title, meta_description

Kural: Admin panelde bu alanlar boş bırakıldığında, title veya excerpt alanından otomatik üretilmelidir (Frontend veya Backend tarafında fallback mantığı ile).

7.2. OpenGraph Görsel Desteği

Sosyal medyada paylaşıldığında güzel bir önizleme kartı oluşturabilmek için:

  • courses.image ve announcements.image alanları aynı zamanda OG Image olarak kullanılacaktır.
  • Frontend'de generateMetadata fonksiyonunda bu görseller openGraph.images altına eklenmelidir.
  • Görseller minimum 1200x630px boyutunda olmalıdır. Admin panelde resim yüklerken bu uyarı gösterilmelidir.

7.3. JSON-LD Yapısal Veri Şemaları (Schema.org)

Google Rich Snippets, Knowledge Panel ve zengin arama sonuçları için aşağıdaki JSON-LD blokları frontend'de render edilmelidir:

Ana Sayfa (/)

{
  "@context": "https://schema.org",
  "@type": "EducationalOrganization",
  "name": "Boğaziçi Denizcilik",
  "url": "https://www.bogazicidenizcilik.com.tr",
  "logo": "...",
  "description": "...",
  "address": { "@type": "PostalAddress", ... },
  "contactPoint": { "@type": "ContactPoint", ... },
  "sameAs": ["instagram", "facebook", "youtube", ...]
}

(Mevcut frontend'de zaten var — Veriler settings API'den çekilmeli)

Eğitim Detay Sayfası (/egitimler/{kategori}/{slug})

{
  "@context": "https://schema.org",
  "@type": "Course",
  "name": "STCW Temel Güvenlik (BST)",
  "description": "...",
  "provider": {
    "@type": "Organization",
    "name": "Boğaziçi Denizcilik",
    "sameAs": "https://www.bogazicidenizcilik.com.tr"
  },
  "hasCourseInstance": {
    "@type": "CourseInstance",
    "courseMode": "onsite",
    "duration": "P5D",
    "location": { "@type": "Place", "name": "Kadıköy, İstanbul" }
  }
}

Backend Notu: API'den GET /api/v1/courses/{slug} response'unda json_ld alanı opsiyonel olarak döndürülebilir veya frontend tarafında oluşturulabilir.

Duyuru Detay Sayfası (/duyurular/{slug})

{
  "@context": "https://schema.org",
  "@type": "NewsArticle",
  "headline": "...",
  "datePublished": "2026-02-15",
  "author": { "@type": "Organization", "name": "Boğaziçi Denizcilik" },
  "image": "...",
  "publisher": { "@type": "Organization", "name": "Boğaziçi Denizcilik", "logo": "..." }
}

SSS Sayfası (/sss) — FAQPage Schema (Çok Önemli)

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Eğitimleriniz hangi kurumlar tarafından onaylıdır?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Tüm eğitimlerimiz Ulaştırma ve Altyapı Bakanlığı onaylıdır..."
      }
    }
  ]
}

⚠️ Google FAQPage Rich Result: SSS sayfasında bu şema kullanılırsa arama sonuçlarında soru-cevaplar doğrudan gösterilir. Bu GET /api/v1/faqs endpoint'inden dönen verilerle frontend'de dinamik olarak oluşturulmalıdır.

Tüm Sayfalarda — BreadcrumbList Schema

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Anasayfa", "item": "https://..." },
    { "@type": "ListItem", "position": 2, "name": "Eğitimler", "item": "https://.../egitimler" },
    { "@type": "ListItem", "position": 3, "name": "STCW Temel Güvenlik" }
  ]
}

7.4. Dinamik Sitemap (API Destekli)

Mevcut sitemap.ts statik datayla çalışmaktadır. Backend hazır olduğunda:

  • GET /api/v1/sitemap-data → Tüm public slug'ları, updated_at tarihleriyle döndüren özel endpoint. Frontend sitemap.ts bunu kullanarak dinamik sitemap oluşturacak.
  • Sitemap lastModified alanları gerçek updated_at tarihlerinden beslenmelidir (şu an tüm sayfalarda new Date() kullanılıyor).
  • Yeni kurs/duyuru/sayfa eklendiğinde sitemap otomatik olarak güncellenecektir.

Önerilen endpoint response yapısı:

{
  "courses": [{ "slug": "stcw-temel-guvenlik", "kategori": "stcw", "updated_at": "2026-02-15" }],
  "announcements": [{ "slug": "kayitlar-basladi", "updated_at": "2026-02-10" }],
  "pages": [{ "slug": "kampanya-bahar-2026", "updated_at": "2026-02-01" }]
}

7.5. Canonical URL'ler

  • Tüm sayfalarda <link rel="canonical"> bulunmalıdır. Mevcut frontend'de alternates.canonical zaten desteklenmekte.
  • Backend API'den gelen slug'lar ile frontend URL yapısı birebir eşleşmelidir.
  • courses slug'ları: /egitimler/{kategoriSlug}/{courseSlug}
  • announcements slug'ları: /duyurular/{slug}

7.6. Hızlı SEO Kontrol Listesi (Checklist)

Öğe Durum ıklama
<title> tag — Her sayfada benzersiz generateMetadata ile dinamik
<meta description> — Her sayfada benzersiz DB'den meta_description alanı
<link rel="canonical"> alternates.canonical ile
OpenGraph tags (og:title, og:description, og:image) Dinamik sayfalarda var
Twitter Card tags Layout'ta global tanımlı
robots.txt /api/ bloklanmış
XML Sitemap Dinamik hale getirilecek (7.4)
JSON-LD EducationalOrganization Ana sayfada mevcut
JSON-LD Course ⚠️ Detay sayfasına eklenmeli
JSON-LD NewsArticle ⚠️ Duyuru detay sayfasına eklenmeli
JSON-LD FAQPage SSS sayfasına eklenmeli
JSON-LD BreadcrumbList Tüm sayfalara eklenmeli
<html lang="tr"> Layout'ta mevcut
Semantic HTML (h1, h2, article, nav) Tüm sayfalarda uygulanmış
Image alt attributes Görsellerde title kullanılıyor
Lazy loading images İlk 6 eager, geri kalan lazy
generateStaticParams (SSG) Tüm dinamik rotalarda var
ISR / Revalidate ⚠️ API entegrasyonunda revalidate eklenecek

Öncelik Sırası: FAQPage schema → BreadcrumbList schema → Course JSON-LD → NewsArticle JSON-LD → Dinamik Sitemap


8. Backend Uygulama Durumu (Implementation Status)

Bu bölüm, yukarıdaki gereksinimlere göre Laravel backend'de yapılan tüm implementasyonları belgelemektedir.

8.1. Veritabanı & Model Katmanı

Bileşen Sayı Durum Detay
Migration 22 users, cache, jobs, permission_tables, activity_log (×3), personal_access_tokens, soft_deletes_users, categories, courses, course_schedules, announcements, hero_slides, leads, menus, comments, faqs, guide_cards, settings, pages, page_blocks
Model 14 User, Category, Course, CourseSchedule, Announcement, HeroSlide, Lead, Menu, Comment, Faq, GuideCard, Setting, Page, PageBlock
Factory 13 Tüm modeller için (User dahil)
Enum 8 AnnouncementCategory, FaqCategory, LeadSource, LeadStatus, MenuLocation, MenuType, SettingGroup, SettingType
Seeder 5 DatabaseSeeder, RolePermissionSeeder, AdminUserSeeder, SettingSeeder, RoleSeeder (artık kullanılmıyor)

8.2. Katmanlı Mimari (Repository Pattern) Bileşenleri

Dökümanın 3. bölümünde belirtilen mimari tam olarak uygulanmıştır:

Route ➔ Middleware (Auth) ➔ Policy (Yetki) ➔ FormRequest (Validasyon) ➔ Controller ➔ DTO ➔ Action ➔ Repository (Interface) ➔ Model ➔ DB
Katman Sayı Kapsam
Repository Interface 13 BaseRepositoryInterface + 12 modül
Repository Eloquent 13 BaseRepository + 12 modül
DTO (Data Transfer Object) 11 Tüm CRUD modülleri
Action (Service) 34 Create/Update/Delete × 11 modül + UpdateSettingsAction
FormRequest 25 Store/Update × 11 modül + LoginRequest + ReorderMenuRequest + UpdateSettingsRequest
API Resource 13 Tüm modüller + PageBlockResource
Controller 28 13 Public (V1) + 15 Admin
Policy 11 Category, Course, CourseSchedule, Announcement, HeroSlide, Lead, Menu, Comment, Faq, GuideCard, Page

8.3. Yetkilendirme & Permission Sistemi (Spatie Permission v7)

Roller

Rol ıklama
super-admin Tüm 48 permission'a sahip
editor Silme (delete-*) hariç 36 permission'a sahip

Permission Yapısı (12 Modül × 4 Aksiyon = 48 Permission)

Modül view-* create-* update-* delete-*
category
course
schedule
announcement
hero-slide
lead
menu
comment
faq
guide-card
setting
page

Not: editor rolü delete-* permission'larından hariç tutulmuştur. Tüm policy dosyaları hasPermissionTo() ile çalışmaktadır (rol kontrolü değil, permission kontrolü).

8.4. API Rotaları

Toplam 97 rota kayıtlıdır.

Public API — GET /api/v1/...

Endpoint Controller ıklama
GET /api/v1/categories CategoryController@index Kategorileri listeler
GET /api/v1/categories/{slug} CategoryController@show Tekil kategori
GET /api/v1/courses CourseController@index Eğitimleri listeler
GET /api/v1/courses/{slug} CourseController@show Tekil eğitim detayı
GET /api/v1/schedules ScheduleController@index Takvim eğitimleri
GET /api/v1/schedules/upcoming ScheduleController@upcoming Yaklaşan eğitimler
GET /api/v1/schedules/{id} ScheduleController@show Tekil takvim kaydı
GET /api/v1/announcements AnnouncementController@index Duyurular
GET /api/v1/announcements/{slug} AnnouncementController@show Tekil duyuru
GET /api/v1/hero-slides HeroSlideController@index Aktif slider
POST /api/v1/leads LeadController@store Ön kayıt formu (Rate Limit: 3/dk)
GET /api/v1/comments/{type}/{id} CommentController@index Onaylı yorumlar
POST /api/v1/comments CommentController@store Yeni yorum (Rate Limit: 3/dk)
GET /api/v1/menus/{location} MenuController@index Menü ağacı
GET /api/v1/faqs FaqController@index SSS listesi
GET /api/v1/faqs/{category} FaqController@index Kategoriye göre SSS
GET /api/v1/guide-cards GuideCardController@index Rehber kartları
GET /api/v1/settings SettingController@index Public ayarlar (is_public=true)
GET /api/v1/pages/{slug} PageController@show Dinamik sayfa (Page Builder)
GET /api/v1/sitemap-data SitemapController@index Sitemap verileri

Admin API — POST|GET|PUT|DELETE /api/admin/... (Sanctum Auth)

Endpoint Controller ıklama
POST /api/admin/login AuthController@login Giriş → Bearer Token
GET /api/admin/me AuthController@me Giriş yapan admin bilgisi
POST /api/admin/logout AuthController@logout Çıkış
POST /api/admin/uploads UploadController@store Dosya yükleme
CRUD /api/admin/categories AdminCategoryController apiResource
CRUD /api/admin/courses AdminCourseController apiResource
CRUD /api/admin/schedules AdminScheduleController apiResource
CRUD /api/admin/announcements AdminAnnouncementController apiResource
CRUD /api/admin/hero-slides AdminHeroSlideController apiResource
CRUD /api/admin/leads AdminLeadController apiResource (store hariç)
POST /api/admin/menus/reorder AdminMenuController@reorder Menü sıralaması
CRUD /api/admin/menus AdminMenuController apiResource
CRUD /api/admin/comments AdminCommentController apiResource (store hariç)
CRUD /api/admin/faqs AdminFaqController apiResource
CRUD /api/admin/guide-cards AdminGuideCardController apiResource
GET /api/admin/settings AdminSettingController@index Tüm ayarlar
GET /api/admin/settings/group/{group} AdminSettingController@group Grup bazlı
PUT /api/admin/settings AdminSettingController@update Toplu güncelleme
CRUD /api/admin/pages AdminPageController apiResource
POST /api/admin/pages/{page}/blocks/reorder AdminBlockController@reorder Blok sıralaması
CRUD /api/admin/pages/{page}/blocks AdminBlockController Nested apiResource

8.5. Cache & Event Sistemi

Bileşen Dosya ıklama
Event app/Events/ModelChanged.php Tüm CRUD Action'larda dispatch edilir
Listener app/Listeners/ClearModelCache.php ModelChanged event'ini dinler, ilgili cache key'lerini temizler

Cache Uygulanan Repository'ler:

Repository Cache Key TTL ıklama
SettingRepository settings:public 1 saat Public ayarlar
HeroSlideRepository hero_slides:active 1 saat Aktif slider
GuideCardRepository guide_cards:active 1 saat Aktif rehber kartları
MenuRepository menus:{location} 1 saat Lokasyona göre menü
FaqRepository faqs:{category} 1 saat Kategoriye göre SSS

Admin panelden veri güncellendiğinde ModelChanged event'i fırlatılır ve ClearModelCache listener ilgili cache key'lerini otomatik olarak temizler.

8.6. Güvenlik & Middleware

Özellik Durum Detay
Sanctum Token Auth Admin API koruması (auth:sanctum)
Rate Limiting leads: 3/dk, comments: 3/dk (IP bazlı)
Global API Throttle 60 istek/dk (bootstrap/app.php)
Stateful API SPA oturumu için
CORS max_age: 86400
404 Handler API isteklerinde JSON hata dönüşü
SoftDeletes users, categories, courses, leads, comments
Spatie Activity Log spatie/laravel-activitylog kurulu

8.7. Swagger / OpenAPI Dökümantasyonu

  • Paket: darkaonline/l5-swagger v10.1.0
  • Erişim: GET /api/documentation
  • Ana Annotation Dosyası: app/Http/Controllers/SwaggerAnnotations.php
  • Toplam Path: 45+ endpoint, 77+ operasyon
  • Tüm controller'larda @OA\Get, @OA\Post, @OA\Put, @OA\Delete annotation'ları mevcuttur.

8.8. Teknik Altyapı

Paket Versiyon Kullanım
PHP 8.4 Runtime
Laravel Framework v12 Ana framework
Laravel Sanctum v4 Token auth
Spatie Permission v7.2 RBAC (48 permission, 2 rol)
Spatie Activity Log v4.12 Audit log
darkaonline/l5-swagger v10.1 API dökümantasyonu
Pest v4 Test framework
Laravel Pint v1 Kod formatlama
Laravel Herd - Yerel sunucu

8.9. Dosya Özeti

Kategori Sayı
Migration 22
Model 14
Enum 8
Controller 28 (+2 base/swagger)
FormRequest 25
API Resource 13
Repository Interface 13
Repository Eloquent 13
Action 34
DTO 11
Policy 11
Event 1
Listener 1
Seeder 5
Factory 13
Toplam ~214 dosya