Mobile App Development Prompt

Muzibu Mobile App

Bu doküman Mac'teki Claude'a verilecek başlangıç prompt'udur. Tüm API'ler, auth sistemi, stream yapısı, iş mantığı ve teknik detaylar dahildir.

API'ler Hazır Sanctum Auth HLS + AES-128

0. Claude CoWork Protocol

İki Claude birlikte çalışacak:
ATLAS = Sunucu Claude (Backend API, DB, Stream) — mztest.muzibu.com
NOVA = Mac Claude (React Native, Expo, Mobil UI) — Yerel Mac

Roller & Sorumluluklar

KonuATLASNOVA
API endpoint değişiklikleriOluşturur / düzeltirİhtiyaç bildirir
Auth & TokenBackend mantığıToken storage & refresh
HLS StreamURL generation, key serveHLS.js player, decode
VeritabanıMigration, modelDokunmaz
React Native kodDokunmazTüm UI & navigation
TestAPI test (curl)Device test (Expo Go)

İletişim Formatı

NOVA → ATLAS mesajı: 📡 ATLAS'a sor: [Soru/İstek] Detay: [Teknik detay] Beklenen: [Ne bekleniyor] ATLAS → NOVA mesajı: 🖥️ NOVA'ya bilgi: [Cevap] Endpoint: [Method + URL] Response: [JSON örneği] Dikkat: [Varsa uyarı]

Altın Kurallar

  • Netlik: Belirsizlik varsa sor, tahmin etme
  • Detay: Response formatlarını tam kullan, field atlama
  • Adım adım: Her faz bitmeden sonrakine geçme
  • Test: Her endpoint'i kodladıktan sonra test et

1. Teknoloji Stack

KatmanTeknolojiVersiyon/Not
FrameworkReact Native + ExpoSDK 52+, Managed workflow
RoutingExpo RouterFile-based routing (app/ dizini)
DilTypeScriptStrict mode
StateZustandLightweight, persist middleware
Data Fetching@tanstack/react-queryCache, refetch, mutation
StylingNativeWind (Tailwind)v4+
Auth Tokenexpo-secure-storeKeychain / Keystore
Audio Playerexpo-av veya react-native-track-playerBackground playback desteği
HLSNative HLS desteğiiOS native, Android ExoPlayer
HTTPaxiosInterceptor ile token injection
Storage@react-native-async-storageOffline cache
Icons@expo/vector-iconsFontAwesome 6
Animationsreact-native-reanimatedGesture handler ile

Setup Komutları

npx create-expo-app@latest muzibu-app --template tabs cd muzibu-app # Core npx expo install expo-router expo-linking expo-constants expo-status-bar # State & Data npm install zustand @tanstack/react-query axios # UI npm install nativewind tailwindcss react-native-reanimated react-native-gesture-handler # Auth & Storage npx expo install expo-secure-store @react-native-async-storage/async-storage # Audio Player npx expo install expo-av # VEYA (background playback için): npm install react-native-track-player # Extras npx expo install expo-image expo-haptics expo-linear-gradient

2. Proje Yapısı

muzibu-app/ ├── app/ # Expo Router (file-based routing) │ ├── _layout.tsx # Root layout (providers, auth check) │ ├── index.tsx # Splash / redirect │ ├── (auth)/ # Auth ekranları (login, register, forgot) │ │ ├── _layout.tsx │ │ ├── login.tsx │ │ ├── register.tsx │ │ └── forgot-password.tsx │ └── (tabs)/ # Ana tab navigation │ ├── _layout.tsx # Tab bar layout │ ├── index.tsx # Ana Sayfa (Home) │ ├── search.tsx # Arama / Keşfet │ ├── library.tsx # Kitaplık │ └── profile/ # Profil (nested) │ ├── index.tsx # Profil ana ekranı │ ├── stats.tsx # İstatistikler │ ├── history.tsx # Dinleme geçmişi │ ├── subscription.tsx # Abonelik │ ├── devices.tsx # Cihazlarım │ └── settings.tsx # Ayarlar │ ├── components/ │ ├── player/ │ │ ├── MiniPlayer.tsx # Alt bar mini player │ │ ├── FullPlayer.tsx # Tam ekran player │ │ ├── ProgressBar.tsx # İlerleme çubuğu │ │ ├── QueueSheet.tsx # Sıradakiler bottom sheet │ │ └── PlayerControls.tsx # Play/pause/skip butonları │ ├── cards/ │ │ ├── SongCard.tsx # Şarkı kartı (yatay/dikey) │ │ ├── PlaylistCard.tsx # Playlist kartı │ │ ├── AlbumCard.tsx # Albüm kartı │ │ └── ArtistCard.tsx # Sanatçı kartı │ ├── lists/ │ │ ├── SongListItem.tsx # Şarkı liste satırı │ │ └── PlaylistListItem.tsx # Playlist liste satırı │ └── ui/ │ ├── LoadingSpinner.tsx │ ├── ErrorView.tsx │ ├── EmptyState.tsx │ └── PremiumBadge.tsx │ ├── hooks/ │ ├── useAuth.ts # Auth state & methods │ ├── usePlayer.ts # Player controls & state │ ├── useFavorites.ts # Favori toggle/check │ ├── useSearch.ts # Arama logic │ └── useApi.ts # React Query hooks │ ├── services/ │ ├── api.ts # Axios instance (base URL, interceptors) │ ├── auth.ts # Login, register, logout, token management │ ├── songs.ts # Song API calls │ ├── playlists.ts # Playlist API calls │ ├── albums.ts # Album API calls │ ├── artists.ts # Artist API calls │ ├── favorites.ts # Favorite API calls │ ├── search.ts # Search API calls │ ├── stream.ts # Stream URL decode + HLS setup │ ├── profile.ts # Profile & subscription API │ ├── stats.ts # Listening history & statistics │ └── tracking.ts # Play tracking (start/hit/end) │ ├── store/ │ ├── authStore.ts # User, token, isPremium │ ├── playerStore.ts # Current song, queue, playback state │ └── appStore.ts # Theme, settings, cache │ ├── types/ │ ├── api.ts # API response types │ ├── models.ts # Song, Album, Artist, Playlist, User │ └── player.ts # Player state types │ ├── constants/ │ ├── api.ts # Base URL, endpoints │ ├── colors.ts # Tema renkleri │ └── config.ts # App config │ └── utils/ ├── formatDuration.ts # Süre formatlama ├── streamDecoder.ts # XOR stream URL decode └── colorHash.ts # HSL gradient parser

3. Authentication Sistemi

Auth Yöntemi: Laravel Sanctum Bearer Token
Token Storage: expo-secure-store (Keychain/Keystore)
Her request'te: Authorization: Bearer {token} header'ı

Auth Endpoints

MethodEndpointAuthAçıklama
POST/api/auth/login-Giriş yap
POST/api/auth/register-Kayıt ol
POST/api/auth/check-email-Email müsait mi?
POST/api/auth/logoutsanctumÇıkış
GET/api/auth/me-Auth durumu
POST/api/auth/forgot-password-Şifre sıfırlama linki
POST/api/auth/reset-password-Şifre sıfırla

Login Flow

// REQUEST POST /api/auth/login Content-Type: application/json { "email": "user@example.com", "password": "password123", "remember": true } // RESPONSE 200 { "success": true, "message": "Giriş başarılı", "user": { "id": 42, "name": "Ahmet Yılmaz", "email": "user@example.com", "is_premium": true }, "csrf_token": "abc123..." } // RESPONSE 422 { "message": "Validation error", "errors": { "email": ["E-posta veya şifre hatalı."] } }
⚠️ ÖNEMLİ — Token Akışı:
Mevcut login endpoint session-based çalışıyor ve csrf_token dönüyor.
Mobil uygulama için V1 Token API kullanılmalı:

V1 Token-Based Auth (Mobil için Önerilen)

MethodEndpointAuthAçıklama
POST/api/v1/auth/login-Login + Bearer token al
POST/api/v1/auth/register-Register + Bearer token al
POST/api/v1/auth/logoutsanctumLogout + token iptal
GET/api/v1/auth/mesanctumKullanıcı bilgisi

Token Yönetimi

MethodEndpointAçıklama
GET/api/v1/tokensToken listesi
POST/api/v1/tokens/refreshToken yenile → yeni token döner
DELETE/api/v1/tokens/{id}Tek token iptal
DELETE/api/v1/tokensTüm tokenları iptal (mevcut hariç)
GET/api/v1/tokens/validateToken geçerli mi?
GET/api/v1/tokens/currentMevcut token bilgisi

Axios Interceptor Örneği

// services/api.ts import axios from 'axios'; import * as SecureStore from 'expo-secure-store'; const API_BASE = 'https://mztest.muzibu.com'; const api = axios.create({ baseURL: API_BASE, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }); // Request interceptor — her isteğe token ekle api.interceptors.request.use(async (config) => { const token = await SecureStore.getItemAsync('auth_token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }); // Response interceptor — 401'de login'e yönlendir api.interceptors.response.use( (res) => res, async (error) => { if (error.response?.status === 401) { await SecureStore.deleteItemAsync('auth_token'); // router.replace('/login'); } return Promise.reject(error); } ); export default api;

Premium Kontrolü

// TEK KAYNAK: users.subscription_expires_at // Gelecekte ise → Premium (true) // NULL veya geçmişte ise → Ücretsiz (false) // Trial ayrımı YOK — trial da premium sayılır // Backend 5 dakika Redis cache kullanır // Auth check response'unda: { "authenticated": true, "user": { "id": 42, "name": "Ahmet", "email": "ahmet@mail.com", "is_premium": true, // ← Bunu kullan "trial_ends_at": null, "device_limit": 999 } } // Abonelik detayı (ayrı endpoint): GET /api/v1/subscription { "is_premium": true, "subscription_expires_at": "2026-12-31T23:59:59", "active": { "subscription_id": 15, "status": "active", "plan_name": "Premium Yıllık", "cycle_label": "Yıllık", "price": 299.99, "currency": "TRY", "current_period_start": "2026-01-01T00:00:00Z", "current_period_end": "2026-12-31T23:59:59Z", "days_remaining": 310, "auto_renew": true, "has_trial": false, "trial_ends_at": null, "started_at": "2025-06-15T00:00:00Z" }, "pending_chain": [] }

4. Müzik API Endpoint'leri

Base URL: https://mztest.muzibu.com
Prefix: Müzik API'leri /api/muzibu/, Genel API'ler /api/v1/
Auth header: Authorization: Bearer {token}

Şarkılar (Songs)

MethodEndpointAuthAçıklama
GET/api/muzibu/songs/recentsanctumSon dinlenenler (kişiye özel, 2dk cache)
GET/api/muzibu/songs/popular-Popüler şarkılar (30dk cache)
GET/api/muzibu/songs/last-played-Son dinlenen (preload)
GET/api/muzibu/songs/{id}-Şarkı detayı
GET/api/muzibu/songs/{id}/playlistssanctumHangi playlistlerde

Şarkı Response Formatı

{ "song_id": 42, "song_title": {"tr": "Yalnızlık Senfonisi", "en": "Symphony of Solitude"}, "song_slug": {"tr": "yalnizlik-senfonisi"}, "duration": 222, // saniye "hls_path": "muzibu/hls/42", "lyrics": {"tr": "Gözlerimde..."}, "album_id": 10, "album_title": {"tr": "Gülümse"}, "album_slug": {"tr": "gulumse"}, "album_cover": "https://mztest.muzibu.com/storage/...", "artist_id": 5, "artist_title": "Sezen Aksu", // string, JSON değil "artist_slug": {"tr": "sezen-aksu"}, "cover_url": "https://..." // popular/show'da var } // ÖNEMLİ: title alanları çoğu zaman JSON (translatable) // Gösterimde: song_title.tr veya song_title[locale] kullan

Albümler (Albums)

MethodEndpointAuthAçıklama
GET/api/muzibu/albums-Tüm albümler (paginated)
GET/api/muzibu/albums/new-releases-Yeni çıkışlar
GET/api/muzibu/albums/{id}-Albüm detayı + şarkıları

Sanatçılar (Artists)

MethodEndpointAuthAçıklama
GET/api/muzibu/artists-Tüm sanatçılar
GET/api/muzibu/artists/{id}-Sanatçı detayı
GET/api/muzibu/artists/{id}/albums-Sanatçının albümleri
GET/api/muzibu/artists/{id}/songs-Sanatçının şarkıları

Türler / Sektörler / Radyolar

MethodEndpointAçıklama
GET/api/muzibu/genresTüm türler
GET/api/muzibu/genres/{id}/songsTür şarkıları
GET/api/muzibu/sectorsTüm sektörler
GET/api/muzibu/sectors/{id}/playlistsSektör playlistleri
GET/api/muzibu/sectors/{id}/songsSektör şarkıları
GET/api/muzibu/radiosTüm radyolar
GET/api/muzibu/radios/{id}/songsRadyo şarkıları

Arama (Search)

GET /api/muzibu/search?q=sezen&type=all // type: all | songs | albums | playlists | artists | genres | sectors | radios // Minimum 2 karakter gerekli. Meilisearch powered. // RESPONSE: { "songs": [{ "song_id": 1, "title": "Gözleri Aşka Gülen", "cover_url": "...", "album": {"title": "..."}, "artist": {"title": "Sezen Aksu"} }], "albums": [{ "album_id": 5, "title": "Gülümse", "cover_url": "...", "artist": {...} }], "playlists": [{ "playlist_id": 12, "title": "Sezen Aksu Hitleri", "cover_url": "..." }], "artists": [{ "artist_id": 3, "title": "Sezen Aksu", "cover_url": "..." }], "genres": [], "sectors": [], "radios": [] }

5. Playlist API

MethodEndpointAuthAçıklama
GET/api/muzibu/playlists-Tüm playlistler (paginated)
GET/api/muzibu/playlists/featured-Öne çıkan playlistler
GET/api/muzibu/playlists/{id}-Playlist detayı + şarkılar
GET/api/muzibu/playlists/my-playlistssanctumKullanıcının playlistleri
POST/api/muzibu/playlists/quick-createsanctumHızlı playlist oluştur
POST/api/muzibu/playlists/{id}/add-songsanctumŞarkı ekle
POST/api/muzibu/playlists/{id}/add-albumsanctumAlbüm ekle
DELETE/api/muzibu/playlists/{id}/remove-song/{songId}sanctumŞarkı çıkar
PUT/api/muzibu/playlists/{id}/reordersanctumSıralama güncelle
PUT/api/muzibu/playlists/{id}sanctumPlaylist düzenle
DELETE/api/muzibu/playlists/{id}sanctumPlaylist sil
POST/api/muzibu/playlists/clonesanctumPlaylist kopyala

Playlist Show Response

GET /api/muzibu/playlists/12 { "playlist": { "id": 12, "playlist_id": 12, "title": {"tr": "Sabah Enerjisi"}, "slug": {"tr": "sabah-enerjisi"}, "description": {"tr": "Güne enerji dolu başla!"}, "cover_url": "https://...", "is_system": true, // Sistem playlist'i düzenlenemez "is_public": true, "songs": [ { "song_id": 42, "song_title": {"tr": "Yalnızlık Senfonisi"}, "duration": 222, "album_cover": "https://...", "artist_title": "Sezen Aksu", "position": 1 } ], "song_count": 45 } }

Quick Create

POST /api/muzibu/playlists/quick-create { "title": "Favori Karışım", "description": "Beğendiklerimden seçmeler", "song_ids": [42, 55, 67, 89], "is_public": false } // 201 Created { "success": true, "data": { "playlist_id": 156, ... } }

6. Stream Sistemi (Kritik!)

⚠️ EN KRİTİK BÖLÜM! Stream URL'leri şifrelenmiş gelir. Doğru decode gerekir.
Mobil uygulama hem HLS hem MP3 stream'i desteklemeli.

Stream URL Al

GET /api/muzibu/songs/{id}/stream Authorization: Bearer {token} // RESPONSE (Premium kullanıcı): { "status": "ready", "_": "base64_encrypted_data", // XOR-encrypted JSON "__": "base64_key", // Decryption key "___": 1708790400, // Unix timestamp "hls_converting": false, "song": { "id": 42, "title": "Yalnızlık Senfonisi", "duration": "3:42", "bitrate": "320 kbps", "cover_url": "https://...", "color_hash": "15,80,65,200,70,55,340,65,70" }, "is_premium": true, "subscription_ends_at": "2026-12-31" } // RESPONSE (Guest → 401): { "status": "unauthorized", "redirect": "/login" } // RESPONSE (Free → 402): { "status": "subscription_required", "redirect": "/subscription/plans" }

Stream URL Decode (XOR)

// utils/streamDecoder.ts export function decodeStreamUrl(encrypted: string, key: string): StreamData { // 1. Base64 decode both const encBytes = atob(encrypted); const keyBytes = atob(key); // 2. XOR decrypt let decrypted = ''; for (let i = 0; i < encBytes.length; i++) { decrypted += String.fromCharCode( encBytes.charCodeAt(i) ^ keyBytes.charCodeAt(i % keyBytes.length) ); } // 3. Parse JSON return JSON.parse(decrypted); // → { stream_url: "https://...", fallback_url: "https://...", stream_type: "hls"|"mp3" } } interface StreamData { stream_url: string; // Ana URL (HLS master.m3u8 veya MP3) fallback_url: string; // Yedek (genelde MP3) stream_type: 'hls' | 'mp3'; }

HLS Yapısı

// HLS 4 seviyeli adaptif bitrate: master.m3u8 → 4 variant seçer: ├── ultralow/playlist.m3u8 (32kbps, mono) ├── low/playlist.m3u8 (64kbps, mono) ├── mid/playlist.m3u8 (128kbps, stereo) └── playlist.m3u8 (orijinal kalite, ~320kbps) // Tüm segment'ler AES-128 encrypted // Key URL: /hls-key/muzibu/songs/{id}?token=...&expires=...&sig=... // iOS: AVPlayer native HLS desteği var — doğrudan URL ver yeter // Android: ExoPlayer HLS desteği var — doğrudan URL ver yeter // Key request'leri player otomatik yapar

MP3 CDN URL Yapısı

// CDN-friendly URL (Cloudflare cache'lenebilir): /audio/songs/{id}/{expires}/{signature}?q=original|mp3_128|mp3_64 // expires: 30dk bloka yuvarlanır → aynı blokta herkes aynı URL alır // Fallback zinciri: mp3_128 yoksa → mp3_64 → orijinal

Mobil Player Flow

1. Kullanıcı şarkıya tıklar 2. GET /api/muzibu/songs/{id}/stream → encrypted response 3. decodeStreamUrl(_.__, ___) → { stream_url, stream_type } 4. stream_type === 'hls' → expo-av veya react-native-track-player'a HLS URL ver → Player otomatik ABR (adaptif bitrate) yapar → Key request'leri otomatik yapılır 5. stream_type === 'mp3' → Doğrudan MP3 URL'i player'a ver 6. POST /api/muzibu/songs/{id}/track-start → play_id al 7. 30s sonra → POST /api/muzibu/songs/{id}/track-hit 8. Şarkı bitince → POST /api/muzibu/songs/{id}/track-end

7. Favoriler & Dinleme Takibi

Favori API

MethodEndpointAuthAçıklama
POST/api/favorites/togglesanctumFavori ekle/çıkar (toggle)
GET/api/favorites/listsanctumFavori listesi (id array)
GET/api/favorites/checksanctumTek item favori mi?
GET/api/favorites/my-favoritessanctumDetaylı favori listesi (paginated)
// Toggle POST /api/favorites/toggle { "model_class": "Modules\\Muzibu\\App\\Models\\Song", "model_id": 42 } → { "success": true, "data": { "action": "added", "is_favorited": true, "favorites_count": 156 } } // List (hızlı kontrol için — tüm favorileri çek, local'de tut) GET /api/favorites/list → { "success": true, "data": ["song-42", "song-55", "album-10", "playlist-12"] } // Format: "{type}-{id}" // Model class mapping: Song → "Modules\\Muzibu\\App\\Models\\Song" Album → "Modules\\Muzibu\\App\\Models\\Album" Artist → "Modules\\Muzibu\\App\\Models\\Artist" Playlist → "Modules\\Muzibu\\App\\Models\\Playlist"

Dinleme Takibi (3 Aşamalı)

// Aşama 1: Şarkı başlayınca POST /api/muzibu/songs/{id}/track-start { "source_type": "playlist", "source_id": 12 } → { "success": true, "play_id": 9876 } // Aşama 2: 30 saniye sonra (play count artırılır) POST /api/muzibu/songs/{id}/track-hit { "play_id": 9876 } → { "success": true, "play_count": 1248 } // Aşama 3: Şarkı bitince veya geçilince POST /api/muzibu/songs/{id}/track-end { "play_id": 9876, "listened_duration": 185, "was_skipped": false, "stop_reason": "ended" // ended|next|prev|pause_timeout|close|unknown } → { "success": true, "updated": true }

Rating

POST /api/muzibu/{type}/{id}/rate // type = songs | albums | playlists | genres | sectors | radios Authorization: Bearer {token}

8. Kuyruk & AI Asistan

Kuyruk (Queue) API

MethodEndpointAçıklama
GET/api/muzibu/queue/initialSayfa açılışında ilk kuyruk
POST/api/muzibu/queue/refillContext-based sonsuz kuyruk yenileme

AI Playlist Oluşturma

MethodEndpointAuthAçıklama
POST/api/muzibu/ai/playlist/createsanctumAI ile playlist oluştur (max 20/gün)
POST/api/muzibu/ai/favorite/addsanctumAI ile favorilere ekle
POST/api/muzibu/ai/play/{type}/{id}sanctum + PremiumAI ile oynat
POST/api/muzibu/ai/queue/addsanctum + PremiumAI ile kuyruğa ekle

9. Profil, İstatistik & Cihaz Yönetimi

Profil API

MethodEndpointAçıklama
GET/api/v1/profileProfil bilgisi
PUT/api/v1/profileProfil güncelle (name, email, phone, bio)
POST/api/v1/profile/change-passwordŞifre değiştir
POST/api/v1/profile/avatarAvatar yükle (max 2MB, JPEG/PNG/GIF)
DELETE/api/v1/profile/avatarAvatar sil
DELETE/api/v1/profile/accountHesap sil (şifre gerekli, soft delete)

İstatistikler API

MethodEndpointParamsAçıklama
GET/api/muzibu/listening-history?period=today|week|month|all&device=mobile|desktop&per_page=20Dinleme geçmişi (paginated)
GET/api/muzibu/stats?period=today|week|month|allKullanıcı istatistikleri
// Stats Response: { "period": "month", "total_plays": 247, "total_duration_seconds": 52340, "total_duration_formatted": "14 saat 32 dakika", "average_duration_seconds": 185, "skip_rate": 12.5, "top_songs": [ { "song_id": 42, "title": "Yalnızlık Senfonisi", "artist": "Sezen Aksu", "cover_url": "...", "play_count": 23, "total_listened": 4255 } ], "device_distribution": { "mobile": 180, "desktop": 67 } } // Listening History Item: { "play_id": 9876, "song_id": 42, "title": "Yalnızlık Senfonisi", "artist": "Sezen Aksu", "album": "Gülümse", "duration": 222, "cover_url": "...", "color_hash": "15,80,65,...", "listened_duration": 185, "was_skipped": false, "stop_reason": "ended", "source_type": "playlist", "device_type": "mobile", "played_at": "2026-02-24T14:30:00Z" }

Cihaz Yönetimi

MethodEndpointAuthAçıklama
POST/api/muzibu/device-profile-Cihaz profili kaydet
GET/api/muzibu/device-profiles-Cihaz profilleri listele
DELETE/api/muzibu/device-profiles/{id}sanctumCihaz sil

Abonelik API

GET /api/v1/subscription Authorization: Bearer {token} { "is_premium": true, "subscription_expires_at": "2026-12-31T23:59:59", "active": { "subscription_id": 15, "status": "active", // active | trial "plan_name": "Premium Yıllık", "cycle_label": "Yıllık", "price": 299.99, "currency": "TRY", "current_period_start": "2026-01-01T00:00:00Z", "current_period_end": "2026-12-31T23:59:59Z", "days_remaining": 310, "auto_renew": true, "has_trial": false }, "pending_chain": [ { "subscription_id": 16, "plan_name": "Premium Aylık", "current_period_start": "2027-01-01T00:00:00Z", "current_period_end": "2027-01-31T23:59:59Z", "days_remaining": 341, "chain_position": 1 } ] }

10. Tasarım Sistemi

Renk Paleti

Primary (Coral)
#ff7f50
Primary Dark
#ff6347
Primary Light
#ff9966
Background
#000000
Surface
#121212
Card
#1a1a1a
Elevated
#282828
Text Secondary
#B3B3B3

Font

Figtree — Google Fonts, geometric humanist sans-serif. Expo'da expo-google-fonts ile yükle.

Dinamik Gradient (color_hash)

// Her şarkının color_hash alanı 9 sayıdan oluşur (3 HSL renk): "15,80,65,200,70,55,340,65,70" → hsl(15, 80%, 65%), hsl(200, 70%, 55%), hsl(340, 65%, 70%) // Player arka planı, progress bar, mini player border'ı // bu renklerden gradient oluşturulur: function parseColorHash(hash: string) { const nums = hash.split(',').map(Number); return [ `hsl(${nums[0]}, ${nums[1]}%, ${nums[2]}%)`, `hsl(${nums[3]}, ${nums[4]}%, ${nums[5]}%)`, `hsl(${nums[6]}, ${nums[7]}%, ${nums[8]}%)`, ]; }

UI Pattern'ler

  • Her zaman dark mode (light mode yok)
  • Border radius: Büyük kartlar 16px, küçük kartlar 8px, butonlar full
  • Cover görselleri: Şarkı/Album 8px, Sanatçı 50% (daire)
  • Mini player: Altta sabit, backdrop-blur, animated gradient border
  • İkon seti: FontAwesome 6 (fas, far)
  • Translatable alanlar JSON gelir → field.tr kullan

11. Geliştirme Fazları

Faz 1: Temel Altyapı

  • Expo Router kurulumu, tab navigation
  • Axios instance + token interceptor
  • Zustand auth store + SecureStore token
  • Login / Register / Forgot Password ekranları
  • Temel tip tanımları (TypeScript)

Faz 2: İçerik Gösterimi

  • Ana sayfa: Son dinlenenler, Popüler, Öne çıkan playlistler
  • Arama ekranı: Tür grid + search bar
  • Playlist detay ekranı
  • Albüm detay ekranı
  • Sanatçı profil ekranı
  • Kitaplık: Playlistlerim, Favori şarkılar

Faz 3: Player (En Kritik)

  • Stream URL alma + XOR decode
  • expo-av veya react-native-track-player entegrasyonu
  • HLS + MP3 stream desteği
  • Mini player (tab bar üstünde)
  • Full screen player (swipe-up gesture)
  • Background playback + notification controls
  • Kuyruk yönetimi (queue/refill)
  • 3 aşamalı dinleme takibi (track-start/hit/end)

Faz 4: Etkileşim

  • Favori toggle (kalp animasyonu)
  • Playlist oluşturma / düzenleme / silme
  • Şarkıyı playliste ekleme (bottom sheet)
  • Pull-to-refresh tüm listelerde
  • Sıralama değiştirme (drag & drop)

Faz 5: Profil & İstatistik

  • Profil ekranı (avatar, bilgi, düzenleme)
  • İstatistikler (toplam dinleme, top şarkılar, cihaz dağılımı)
  • Dinleme geçmişi (filtrelenebilir)
  • Abonelik detayı ekranı
  • Cihaz yönetimi
  • Şifre değiştirme
  • Hesap silme

Faz 6: Polish & Optimizasyon

  • Skeleton loading states
  • Error boundary & retry mekanizması
  • Offline cache (son dinlenenler)
  • Haptic feedback
  • Animasyonlar (Reanimated)
  • App icon & splash screen
  • EAS Build (iOS + Android)

12. Kritik Notlar & Uyarılar

1. Translatable Alanlar: title, slug, lyrics, description alanları JSON gelir.
Gösterim: item.title?.tr || item.title?.en || 'Bilinmeyen'
Bazen düz string gelir (artist_title gibi) — her ikisini de handle et.
2. Stream Güvenlik: URL'ler XOR-encrypted gelir. Decode etmeden kullanılamaz.
_ = encrypted data, __ = key, ___ = timestamp
3. Auth Guard: Bazı endpoint'ler auth:sanctum,web middleware kullanır.
Mobil'den sadece Authorization: Bearer {token} göndermek yeterli.
4. Premium Gate: Stream endpoint guest'e 401, free user'a 402 döner.
402 aldığında abonelik sayfasına yönlendir, şarkı bilgisini göster ama çalma.
5. Cache Süresi: Recent: 2dk, Popular: 30dk, Song: 24h, Premium: 5dk.
React Query staleTime ayarlarını buna göre yapılandır.
6. Pagination: Laravel standart paginator kullanılır.
Response: { data: [...], current_page, last_page, per_page, total }
7. HLS Key Request: iOS/Android native player key request'ini otomatik yapar.
Master playlist'teki #EXT-X-KEY:URI= satırı key URL'i içerir. Ek auth header gerekmez — key URL signed.
8. Test API Base URL:
Test: https://mztest.muzibu.com
Production: https://muzibu.com
Ayarlanabilir olsun — constants/api.ts'de env-based.

13. Mac Claude Başlangıç Prompt'u

Bu prompt'u Mac'teki Claude'a ilk mesaj olarak ver. Yukarıdaki tüm dokümanı CLAUDE.md olarak projeye koy.
Sen NOVA'sın — Muzibu mobil uygulamasının React Native geliştiricisi. PROJE: Muzibu — Türkçe müzik streaming platformu (iOS + Android) BACKEND: Laravel + Sanctum + HLS + AES-128 (ATLAS yönetiyor, mztest.muzibu.com) STACK: React Native + Expo (SDK 52+), Expo Router, TypeScript, Zustand, @tanstack/react-query, NativeWind, expo-av, expo-secure-store GÖREV: Faz 1'den başla, adım adım ilerle. ÖNEMLİ KURALLAR: 1. API base URL: https://mztest.muzibu.com (test ortamı) 2. Auth: Sanctum Bearer Token → expo-secure-store'da sakla 3. Stream URL'leri XOR-encrypted gelir, decode etmen lazım (bkz: CLAUDE.md §6) 4. title/slug/lyrics alanları JSON (translatable) — .tr key'ini kullan 5. Her zaman dark mode. Primary renk: #ff7f50 (coral) 6. Font: Figtree (expo-google-fonts) 7. Backend'e API ihtiyacın olursa "📡 ATLAS'a sor:" formatında yaz CLAUDE.md dosyasında tüm endpoint'ler, response formatları, stream decode mantığı, ve tasarım detayları mevcut. Oku ve başla. İlk adım: Faz 1 — Expo projesi oluştur, tab navigation kur, auth flow yaz.
24 Şubat 2026 • Muzibu.com