Multi-Tenant Tema Sistemi - Kapsamli Referans Dokumani
t-{id} = Tenant temasi. Sadece ozel dosyalar burada.
simple = Fallback (mevcut, zaten var). t-{id}'de yoksa buradan alir.
Ornek: t-3/homepage.blade.php var -> onu kullan, t-3/blog/show.blade.php yok -> simple'dan al
resources/views/themes/{tema}/{view}
Ana tema klasoru - TEK DOSYA PRENSIBI - ONCELIKLI!
Modules/{Modul}/views/themes/{tema}/{view}
Modul ici tema - Fallback (resources'da yoksa)
themes.simple.{view}
Simple tema fallback (aktif tema simple degilse)
{modul}::front.{view}
Son care - Modul front klasoru
Header ve navigasyon icin xl (1280px) breakpoint kullaniyoruz. lg (1024px) kullanmak tablet boyutlarinda sorunlara yol acar!
| Class | Piksel | Kullanim |
|---|---|---|
sm: | 640px | Buyuk telefonlar |
md: | 768px | Tablet dikey |
lg: | 1024px | Tablet yatay / Kucuk laptop |
xl: | 1280px | HEADER BREAKPOINT! |
2xl: | 1536px | Buyuk ekranlar |
{{-- Desktop navigasyon (xl ve uzeri) --}} <nav class="hidden xl:flex items-center gap-8"> ... </nav> {{-- Mobil/Tablet butonlar (xl altinda) --}} <div class="flex items-center gap-2 xl:hidden"> ... </div> {{-- Desktop CTA butonlari (xl ve uzeri) --}} <div class="hidden xl:flex items-center gap-2"> ... </div>
{{-- YANLIS! lg kullanma --}} <nav class="hidden lg:flex"> // 1024px - tablet yatayda bozuk! <div class="lg:hidden"> // Cift ikon sorunu! {{-- DOGRU! xl kullan --}} <nav class="hidden xl:flex"> // 1280px - temiz gecis <div class="xl:hidden"> // Tek ikon
Mobilde 2 kolon (grid-cols-2) varsayilan! Tek kolon (grid-cols-1) kullanma - cok bos gorunur.
| Bolum | Class |
|---|---|
| Hizmetler | grid-cols-2 lg:grid-cols-3 |
| Neden Biz? | grid-cols-2 lg:grid-cols-3 |
| Cozum Surecleri | grid-cols-2 lg:grid-cols-4 |
| Galeri | grid-cols-2 md:grid-cols-3 lg:grid-cols-4 |
| Blog Listesi | grid-cols-1 md:grid-cols-2 lg:grid-cols-3 |
{{-- YANLIS! Mobilde cok bos --}} <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"> {{-- DOGRU! Mobilde 2 kolon --}} <div class="grid grid-cols-2 lg:grid-cols-3">
{{-- Hizmetler bolumu --}} <div class="grid grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6"> @foreach($services as $service) <div class="bg-white dark:bg-slate-800 rounded-xl p-4"> ... </div> @endforeach </div> // Mobil (0-1023px): 2 kolon // Desktop (1024px+): 3 kolon
Tum paragraflar leading-relaxed (1.625) kullanmali. Farki satir yukseklikleri okumasi zor metinler olusturur!
| Class | Deger | Kullanim |
|---|---|---|
leading-tight | 1.25 | Basliklar |
leading-snug | 1.375 | Alt basliklar |
leading-relaxed | 1.625 | PARAGRAFLAR - STANDART! |
leading-loose | 2 | Cok seyrek |
{{-- Icerik alanlari icin --}} <div class="prose prose-lg max-w-none dark:prose-invert prose-p:leading-relaxed prose-li:leading-relaxed prose-headings:font-heading prose-a:text-primary-600"> @parsewidgets($body ?? '') </div> {{-- Normal paragraflar icin --}} <p class="text-gray-600 dark:text-gray-300 leading-relaxed"> Aciklama metni... </p>
{{-- YANLIS! prose-base ve prose-lg karisik --}} <div class="prose prose-base"> // Sayfa 1 <div class="prose prose-lg"> // Sayfa 2 - FARKLI! {{-- DOGRU! Tutarli prose-lg --}} <div class="prose prose-lg prose-p:leading-relaxed">
Top Bar
Telefon numaralari, WhatsApp, calisma saatleri. Mobil/tablet icin sadelesilmis.
Main Header (sticky)
Logo, navigasyon, dark mode toggle, CTA butonlari
Mobile Menu (xl:hidden)
x-show ile acilir/kapanir. Navigasyon + arama butonlari
@auth
@if(auth()->user()->hasRole('root'))
<div class="flex items-center gap-1 ml-2">
{{-- Cache Sifirla --}}
<button @click="fetch('/admin/cache/clear'...)">
<i class="fat fa-sync-alt"></i>
</button>
{{-- AI Reset --}}
<button @click="localStorage.removeItem('tenant'+tenantId+'_ai_session')">
<i class="fat fa-robot"></i>
</button>
</div>
@endif
@endauth
@php
$siteName = setting('site_title') ?: setting('site_company_name');
$siteSlogan = setting('site_slogan');
$sitePhone = setting('contact_phone_1'); // Ana telefon
$siteMobile = setting('contact_phone_2') ?: setting('contact_whatsapp_1');
$siteWhatsapp = setting('contact_whatsapp_1')
? preg_replace('/[^0-9]/', '', setting('contact_whatsapp_1')) : null;
$whatsappUrl = whatsapp_link(); // Global helper!
// Logo Service
$logoService = app(\App\Services\LogoService::class);
$logos = $logoService->getLogos();
$hasLogo = $logos['has_light'] || $logos['has_dark'];
@endphp
social_whatsapp YANLIS! Dogru key: contact_whatsapp_1
| Key | Aciklama | Ornek |
|---|---|---|
contact_phone_1 | Ana telefon (sabit) | 0212 XXX XX XX |
contact_phone_2 | Mobil telefon | 0533 XXX XX XX |
contact_whatsapp_1 | WhatsApp numarasi | 0533 XXX XX XX |
contact_email_1 | E-posta | info@site.com |
contact_address_1 | Adres | Istanbul, Turkiye |
| Key | Aciklama |
|---|---|
site_title | Site basligi |
site_company_name | Sirket adi |
site_slogan | Slogan |
site_description | Site aciklamasi |
// Global helper fonksiyonu - helpers.php function whatsapp_link($message = null) { $number = setting('contact_whatsapp_1'); if (!$number) return null; $clean = preg_replace('/[^0-9]/', '', $number); $url = 'https://wa.me/' . $clean; if ($message) { $url .= '?text=' . urlencode($message); } return $url; } // Kullanim: $whatsappUrl = whatsapp_link(); // https://wa.me/905331234567 $whatsappUrl = whatsapp_link('Merhaba, bilgi almak istiyorum'); // Blade'de: @if($whatsappUrl = whatsapp_link()) <a href="{{ $whatsappUrl }}" target="_blank">WhatsApp</a> @endif
// YANLIS! setting('social_whatsapp') // Boyle key YOK! setting('site_phone') // Boyle key YOK! setting('whatsapp') // Boyle key YOK! // DOGRU! setting('contact_whatsapp_1') setting('contact_phone_1') setting('contact_phone_2')
@php
$logoService = app(\App\Services\LogoService::class);
$logos = $logoService->getLogos();
// Donen deger:
[
'has_light' => true, // Light logo var mi?
'has_dark' => true, // Dark logo var mi?
'light_logo_url' => '...', // Light logo URL
'dark_logo_url' => '...', // Dark logo URL
]
$hasLogo = $logos['has_light'] || $logos['has_dark'];
@endphp
@if($hasLogo)
@if($logos['has_light'] && $logos['has_dark'])
{{-- Her iki logo da var --}}
<img src="{{ $logos['light_logo_url'] }}" class="dark:hidden h-10">
<img src="{{ $logos['dark_logo_url'] }}" class="hidden dark:block h-10">
@elseif($logos['has_light'])
{{-- Sadece light logo --}}
<img src="{{ $logos['light_logo_url'] }}" class="h-10">
@elseif($logos['has_dark'])
{{-- Sadece dark logo --}}
<img src="{{ $logos['dark_logo_url'] }}" class="h-10">
@endif
@else
{{-- Fallback: Icon + Site ismi --}}
<div class="w-10 h-10 bg-primary-500 rounded-xl flex items-center justify-center">
<i class="fat fa-blinds text-white"></i>
</div>
<span>{{ $siteName }}</span>
@endif
Page modulu OZGUR olmali! Template sadece wrapper. Her sayfanin kendine ozel tasarimi pages tablosundaki css ve js kolonlarinda saklanir.
| Kolon | Tip | Aciklama |
|---|---|---|
title | JSON | Cok dilli baslik |
body | JSON (longText) | Cok dilli icerik (widget destekli) |
css | TEXT | Sayfa ozel CSS |
js | TEXT | Sayfa ozel JavaScript |
{{-- SUBHEADER (Breadcrumb + Title) --}} <section class="bg-gray-50 dark:bg-gray-800 border-b"> <div class="container"> <nav>{{ breadcrumb }}</nav> <h1>{{ $title }}</h1> </div> </section> {{-- CONTENT - Sadece container --}} <section class="bg-white dark:bg-gray-900 py-10"> <div class="container"> <div class="page-content prose prose-lg max-w-none prose-p:leading-relaxed"> @parsewidgets($body ?? '') </div> </div> </section> {{-- CSS/JS veritabanindan --}} @if(isset($item->css))<style>{!! $item->css !!}</style>@endif @if(isset($item->js))<script>{!! $item->js !!}</script>@endif
resources/views/themes/{tema}/ klasorunde SADECE layout kullanan dosyalar olmali. Standalone HTML dosyasi (DOCTYPE ile baslayan) YASAK!
// resources/views/themes/t-3/homepage.blade.php @extends('themes.t-3.layouts.app') <-- LAYOUT VAR! @section('content') {{-- Sayfa icerigi --}} @endsection
// YANLIS - Standalone <!DOCTYPE html> <html> <head>...</head> <-- LAYOUT YOK! YASAK!
resources/views/themes/{tema}/ = Sadece homepage, ozel sayfalar@extends('themes.{tema}.layouts.app') ile baslamaliprose-a:no-underline kullan
TUM sayfalar @include kullanmali
resources/themes/ icinde DOCTYPE YASAK
Page modulu FREE olmali
grid-cols-1 degil, grid-cols-2 kullan
Her yerde leading-relaxed kullan