Skip to content

Mobil Araçlar Rehberi (Mobile Tools Guide)

Mobil uygulama geliştirmede kullanılan temel araçlar, servisler ve kütüphaneler. Firebase, bildirim sistemleri, BaaS platformları, UI kütüphaneleri, veritabanları, CI/CD, test araçları ve paket yönetimi konularını kapsar.



1. Firebase

Firebase Nedir? (What is Firebase?)

Firebase, Google tarafından sunulan kapsamlı bir mobil ve web uygulama geliştirme platformudur (comprehensive app development platform). Backend altyapısı kurmadan (without setting up backend infrastructure) kimlik doğrulama, veritabanı, dosya depolama, bildirim ve analitik gibi servisleri hazır olarak sunar.

Resmi Site (Official Site): https://firebase.google.com

Firebase Servisleri Tablosu (Firebase Services Table)

Servis (Service)Kategori (Category)Açıklama (Description)Ücretsiz Katman (Free Tier)
AuthenticationKimlik DoğrulamaEmail, Google, Apple, Phone, AnonymousSınırsız (Unlimited)
Cloud FirestoreVeritabanı (Database)NoSQL belge tabanlı DB (document-based)1 GiB depolama, 50K okuma/gün
Realtime DatabaseVeritabanı (Database)Gerçek zamanlı JSON veritabanı1 GB depolama, 10 GB/ay transfer
Cloud StorageDosya Depolama (File Storage)Dosya yükleme/indirme (upload/download)5 GB depolama
Cloud Messaging (FCM)Bildirimler (Notifications)Push bildirim gönderimiSınırsız (Unlimited)
CrashlyticsHata İzleme (Crash Reporting)Gerçek zamanlı çökme raporlarıSınırsız (Unlimited)
AnalyticsAnalitik (Analytics)Kullanıcı davranış analiziSınırsız (Unlimited)
Remote ConfigYapılandırma (Configuration)Uzaktan uygulama ayarlarıSınırsız (Unlimited)
Dynamic LinksDerin Bağlantılar (Deep Links)Platformlar arası akıllı linklerSınırsız (Unlimited)
App DistributionDağıtım (Distribution)Beta test dağıtımıSınırsız (Unlimited)
Cloud FunctionsSunucusuz (Serverless)Backend fonksiyonları125K çağrı/ay
HostingBarındırma (Hosting)Statik site barındırma10 GB depolama, 360 MB/gün
Performance MonitoringPerformans (Performance)Uygulama performans takibiSınırsız (Unlimited)
Test LabTest (Testing)Gerçek cihazlarda test15 test/gün (sanal), 5 test/gün (fiziksel)

Firebase Kurulumu (Firebase Setup)

React Native Kurulumu (React Native Setup)

bash
# 1. React Native Firebase paketini yükle (Install RN Firebase)
npm install @react-native-firebase/app

# 2. İhtiyacınıza göre modül ekleyin (Add modules as needed)
npm install @react-native-firebase/auth
npm install @react-native-firebase/firestore
npm install @react-native-firebase/storage
npm install @react-native-firebase/messaging
npm install @react-native-firebase/crashlytics
npm install @react-native-firebase/analytics

# 3. iOS bağımlılıklarını yükleyin (Install iOS dependencies)
cd ios && pod install && cd ..

React Native yapılandırma adımları (Configuration Steps):

  1. Firebase Console'dan yeni proje oluşturun (Create new project from Firebase Console)
  2. iOS uygulaması ekleyin → GoogleService-Info.plist dosyasını ios/ klasörüne koyun
  3. Android uygulaması ekleyin → google-services.json dosyasını android/app/ klasörüne koyun
  4. android/build.gradle dosyasına Google Services plugin ekleyin:
groovy
// android/build.gradle
buildscript {
    dependencies {
        // ... mevcut bağımlılıklar (existing dependencies)
        classpath 'com.google.gms:google-services:4.4.2'
    }
}
groovy
// android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
  1. iOS için AppDelegate.mm dosyasını güncelleyin:
objc
#import <Firebase.h>

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [FIRApp configure]; // Firebase başlat (Initialize Firebase)
  // ... diğer kodlar (other code)
}

Flutter Kurulumu (Flutter Setup)

bash
# 1. Firebase CLI ve FlutterFire CLI yükleyin (Install Firebase CLI & FlutterFire CLI)
npm install -g firebase-tools
dart pub global activate flutterfire_cli

# 2. Firebase'e giriş yapın (Login to Firebase)
firebase login

# 3. FlutterFire yapılandırması (FlutterFire configuration)
flutterfire configure

# 4. Gerekli paketleri ekleyin (Add required packages)
flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add cloud_firestore
flutter pub add firebase_storage
flutter pub add firebase_messaging
flutter pub add firebase_crashlytics
flutter pub add firebase_analytics

Flutter yapılandırma (Flutter Configuration):

dart
// lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // FlutterFire CLI tarafından oluşturulur (generated by FlutterFire CLI)

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}

Authentication (Kimlik Doğrulama)

Firebase Authentication birden fazla kimlik doğrulama yöntemi destekler (supports multiple auth methods).

Email/Password Authentication

React Native:

javascript
import auth from '@react-native-firebase/auth';

// Kayıt (Register)
async function register(email, password) {
  try {
    const userCredential = await auth().createUserWithEmailAndPassword(email, password);
    console.log('Kullanıcı oluşturuldu (User created):', userCredential.user.uid);
    return userCredential.user;
  } catch (error) {
    if (error.code === 'auth/email-already-in-use') {
      console.log('Bu email zaten kullanımda (Email already in use)');
    }
    if (error.code === 'auth/invalid-email') {
      console.log('Geçersiz email adresi (Invalid email)');
    }
    throw error;
  }
}

// Giriş (Login)
async function login(email, password) {
  try {
    const userCredential = await auth().signInWithEmailAndPassword(email, password);
    console.log('Giriş başarılı (Login successful):', userCredential.user.uid);
    return userCredential.user;
  } catch (error) {
    if (error.code === 'auth/user-not-found') {
      console.log('Kullanıcı bulunamadı (User not found)');
    }
    if (error.code === 'auth/wrong-password') {
      console.log('Yanlış şifre (Wrong password)');
    }
    throw error;
  }
}

// Çıkış (Logout)
async function logout() {
  await auth().signOut();
  console.log('Çıkış yapıldı (Signed out)');
}

// Oturum durumu dinleyici (Auth state listener)
auth().onAuthStateChanged((user) => {
  if (user) {
    console.log('Kullanıcı giriş yapmış (User signed in):', user.uid);
  } else {
    console.log('Kullanıcı çıkış yapmış (User signed out)');
  }
});

Flutter:

dart
import 'package:firebase_auth/firebase_auth.dart';

final FirebaseAuth _auth = FirebaseAuth.instance;

// Kayıt (Register)
Future<User?> register(String email, String password) async {
  try {
    final credential = await _auth.createUserWithEmailAndPassword(
      email: email,
      password: password,
    );
    print('Kullanıcı oluşturuldu: ${credential.user?.uid}');
    return credential.user;
  } on FirebaseAuthException catch (e) {
    if (e.code == 'email-already-in-use') {
      print('Bu email zaten kullanımda');
    }
    rethrow;
  }
}

// Giriş (Login)
Future<User?> login(String email, String password) async {
  try {
    final credential = await _auth.signInWithEmailAndPassword(
      email: email,
      password: password,
    );
    return credential.user;
  } on FirebaseAuthException catch (e) {
    print('Giriş hatası: ${e.message}');
    rethrow;
  }
}

// Oturum durumu dinleyici (Auth state listener)
_auth.authStateChanges().listen((User? user) {
  if (user != null) {
    print('Kullanıcı giriş yapmış: ${user.uid}');
  } else {
    print('Kullanıcı çıkış yapmış');
  }
});

Google Sign-In

React Native:

javascript
import { GoogleSignin } from '@react-native-google-signin/google-signin';
import auth from '@react-native-firebase/auth';

// Yapılandırma (Configuration)
GoogleSignin.configure({
  webClientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
});

async function googleSignIn() {
  // Google giriş ekranını aç (Open Google sign-in screen)
  const { idToken } = await GoogleSignin.signIn();
  // Firebase credential oluştur (Create Firebase credential)
  const googleCredential = auth.GoogleAuthProvider.credential(idToken);
  // Firebase ile giriş yap (Sign in with Firebase)
  return auth().signInWithCredential(googleCredential);
}

Flutter:

dart
import 'package:google_sign_in/google_sign_in.dart';

Future<UserCredential> googleSignIn() async {
  final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
  final GoogleSignInAuthentication? googleAuth = await googleUser?.authentication;

  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth?.accessToken,
    idToken: googleAuth?.idToken,
  );

  return await FirebaseAuth.instance.signInWithCredential(credential);
}

Apple Sign-In

React Native:

javascript
import { appleAuth } from '@invertase/react-native-apple-authentication';
import auth from '@react-native-firebase/auth';

async function appleSignIn() {
  // Apple giriş isteği (Apple sign-in request)
  const appleAuthResponse = await appleAuth.performRequest({
    requestedOperation: appleAuth.Operation.LOGIN,
    requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
  });

  const { identityToken, nonce } = appleAuthResponse;
  const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce);
  return auth().signInWithCredential(appleCredential);
}

Phone Authentication (Telefon ile Doğrulama)

React Native:

javascript
import auth from '@react-native-firebase/auth';

// SMS kodu gönder (Send SMS code)
async function sendVerificationCode(phoneNumber) {
  const confirmation = await auth().signInWithPhoneNumber(phoneNumber);
  return confirmation; // Doğrulama nesnesini sakla (Store confirmation object)
}

// SMS kodunu doğrula (Verify SMS code)
async function verifyCode(confirmation, code) {
  try {
    await confirmation.confirm(code);
    console.log('Telefon doğrulaması başarılı (Phone verification successful)');
  } catch (error) {
    console.log('Geçersiz kod (Invalid code)');
  }
}

Firestore (Bulut Veritabanı / Cloud Database)

Cloud Firestore, Firebase'in NoSQL belge tabanlı bulut veritabanıdır (NoSQL document-based cloud database). Gerçek zamanlı senkronizasyon (real-time sync) ve çevrimdışı destek (offline support) sunar.

CRUD İşlemleri (CRUD Operations)

React Native:

javascript
import firestore from '@react-native-firebase/firestore';

// ---------- CREATE (Oluşturma) ----------

// Otomatik ID ile belge ekle (Add document with auto ID)
async function addUser(userData) {
  const docRef = await firestore().collection('users').add({
    name: userData.name,
    email: userData.email,
    age: userData.age,
    createdAt: firestore.FieldValue.serverTimestamp(),
  });
  console.log('Belge eklendi, ID (Document added, ID):', docRef.id);
  return docRef.id;
}

// Belirli ID ile belge oluştur (Create document with specific ID)
async function setUser(userId, userData) {
  await firestore().collection('users').doc(userId).set({
    name: userData.name,
    email: userData.email,
    age: userData.age,
    updatedAt: firestore.FieldValue.serverTimestamp(),
  });
}

// ---------- READ (Okuma) ----------

// Tek belge oku (Read single document)
async function getUser(userId) {
  const doc = await firestore().collection('users').doc(userId).get();
  if (doc.exists) {
    console.log('Kullanıcı verisi (User data):', doc.data());
    return { id: doc.id, ...doc.data() };
  } else {
    console.log('Belge bulunamadı (Document not found)');
    return null;
  }
}

// Tüm belgeleri oku (Read all documents)
async function getAllUsers() {
  const snapshot = await firestore().collection('users').get();
  const users = snapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data(),
  }));
  return users;
}

// ---------- UPDATE (Güncelleme) ----------

// Belge güncelle (Update document)
async function updateUser(userId, updates) {
  await firestore().collection('users').doc(userId).update({
    ...updates,
    updatedAt: firestore.FieldValue.serverTimestamp(),
  });
}

// Belirli alanı artır (Increment specific field)
async function incrementLoginCount(userId) {
  await firestore().collection('users').doc(userId).update({
    loginCount: firestore.FieldValue.increment(1),
  });
}

// Diziye eleman ekle (Add element to array)
async function addFavorite(userId, itemId) {
  await firestore().collection('users').doc(userId).update({
    favorites: firestore.FieldValue.arrayUnion(itemId),
  });
}

// ---------- DELETE (Silme) ----------

// Belge sil (Delete document)
async function deleteUser(userId) {
  await firestore().collection('users').doc(userId).delete();
}

// Belirli alanı sil (Delete specific field)
async function removeField(userId, fieldName) {
  await firestore().collection('users').doc(userId).update({
    [fieldName]: firestore.FieldValue.delete(),
  });
}

Sorgu ve Filtreleme (Query & Filtering)

javascript
const usersRef = firestore().collection('users');

// Basit sorgu (Simple query)
const activeUsers = await usersRef
  .where('isActive', '==', true)
  .get();

// Birden fazla koşul (Multiple conditions)
const filteredUsers = await usersRef
  .where('age', '>=', 18)
  .where('age', '<=', 30)
  .where('city', '==', 'Istanbul')
  .get();

// Sıralama ve limit (Ordering and limit)
const recentUsers = await usersRef
  .orderBy('createdAt', 'desc')
  .limit(10)
  .get();

// Sayfalama (Pagination)
const firstPage = await usersRef
  .orderBy('name')
  .limit(20)
  .get();

const lastDoc = firstPage.docs[firstPage.docs.length - 1];
const secondPage = await usersRef
  .orderBy('name')
  .startAfter(lastDoc)
  .limit(20)
  .get();

// Dizi içinde arama (Array contains)
const jsDevelopers = await usersRef
  .where('skills', 'array-contains', 'JavaScript')
  .get();

// Birden fazla değer arama (Where in)
const specificCities = await usersRef
  .where('city', 'in', ['Istanbul', 'Ankara', 'Izmir'])
  .get();

Gerçek Zamanlı Dinleyici (Real-time Listener)

javascript
// Tek belge dinleyici (Single document listener)
const unsubscribeUser = firestore()
  .collection('users')
  .doc('user123')
  .onSnapshot(
    (doc) => {
      if (doc.exists) {
        console.log('Güncel veri (Current data):', doc.data());
      }
    },
    (error) => {
      console.error('Dinleyici hatası (Listener error):', error);
    }
  );

// Koleksiyon dinleyici (Collection listener)
const unsubscribeCollection = firestore()
  .collection('messages')
  .where('chatId', '==', 'chat123')
  .orderBy('timestamp', 'desc')
  .limit(50)
  .onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === 'added') {
        console.log('Yeni mesaj (New message):', change.doc.data());
      }
      if (change.type === 'modified') {
        console.log('Değişen mesaj (Modified message):', change.doc.data());
      }
      if (change.type === 'removed') {
        console.log('Silinen mesaj (Removed message):', change.doc.data());
      }
    });
  });

// Dinleyiciyi kaldır (Unsubscribe listener) - Component unmount'ta çağırın
unsubscribeUser();
unsubscribeCollection();

Realtime Database vs Firestore Karşılaştırma (Comparison)

Özellik (Feature)Realtime DatabaseCloud Firestore
Veri Modeli (Data Model)Büyük JSON ağacı (Large JSON tree)Koleksiyon ve belge (Collection & document)
Sorgu (Queries)Sınırlı, tek boyutlu (Limited, single dimension)Gelişmiş, bileşik sorgular (Advanced, composite)
Ölçeklenme (Scaling)Tek bölge (Single region)Çoklu bölge, otomatik ölçek (Multi-region, auto-scale)
Çevrimdışı (Offline)Mobilde desteklerMobil + Web destekler
Fiyatlandırma (Pricing)Bant genişliği + depolamaOkuma/yazma işlem sayısı
Gerçek Zamanlı (Real-time)Çok hızlı (~ms)Hızlı (~1-2s)
Yapı (Structure)Derin iç içe geçme (Deep nesting)Düz koleksiyonlar (Flat collections)
İdeal Kullanım (Best For)Sohbet, canlı durumKarmaşık sorgular, büyük veri
Önerilen (Recommended)Eski projeler, basit yapıYeni projeler için önerilen

Öneri (Recommendation): Yeni projelerde Cloud Firestore kullanın. Daha güçlü sorgu yetenekleri, daha iyi ölçeklenme ve aktif geliştirme desteği sunar.


Cloud Storage (Bulut Depolama)

Dosya yükleme, indirme ve yönetme servisidir (file upload, download and management service).

javascript
import storage from '@react-native-firebase/storage';

// Dosya yükleme (Upload file)
async function uploadFile(localPath, remotePath) {
  const reference = storage().ref(remotePath);
  const task = reference.putFile(localPath);

  // İlerleme takibi (Progress tracking)
  task.on('state_changed', (snapshot) => {
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log(`Yükleniyor (Uploading): ${progress.toFixed(1)}%`);
  });

  await task;
  const downloadURL = await reference.getDownloadURL();
  console.log('İndirme URL (Download URL):', downloadURL);
  return downloadURL;
}

// Profil fotoğrafı yükleme (Upload profile photo)
async function uploadProfilePhoto(userId, photoUri) {
  const filename = `profile_photos/${userId}_${Date.now()}.jpg`;
  const reference = storage().ref(filename);

  await reference.putFile(photoUri);
  const url = await reference.getDownloadURL();

  // Firestore'da profil URL'sini güncelle (Update profile URL in Firestore)
  await firestore().collection('users').doc(userId).update({
    photoURL: url,
  });

  return url;
}

// Dosya silme (Delete file)
async function deleteFile(remotePath) {
  await storage().ref(remotePath).delete();
  console.log('Dosya silindi (File deleted)');
}

// Dosya listele (List files)
async function listFiles(folderPath) {
  const result = await storage().ref(folderPath).listAll();
  const urls = await Promise.all(
    result.items.map(item => item.getDownloadURL())
  );
  return urls;
}

Cloud Messaging / FCM (Push Bildirimler)

Firebase Cloud Messaging, platformlar arası push bildirim gönderme servisidir (cross-platform push notification service).

javascript
import messaging from '@react-native-firebase/messaging';

// Bildirim izni iste (Request notification permission)
async function requestPermission() {
  const authStatus = await messaging().requestPermission();
  const enabled =
    authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
    authStatus === messaging.AuthorizationStatus.PROVISIONAL;

  if (enabled) {
    console.log('Bildirim izni verildi (Notification permission granted)');
    const token = await messaging().getToken();
    console.log('FCM Token:', token);
    // Token'ı sunucuya kaydet (Save token to server)
    await saveTokenToServer(token);
  }
  return enabled;
}

// Token yenilenme dinleyici (Token refresh listener)
messaging().onTokenRefresh(async (token) => {
  console.log('Yeni FCM Token:', token);
  await saveTokenToServer(token);
});

// Ön planda bildirim dinle (Listen for foreground notifications)
messaging().onMessage(async (remoteMessage) => {
  console.log('Ön plan bildirimi (Foreground notification):', remoteMessage);
  // Yerel bildirim göster (Show local notification)
  showLocalNotification(remoteMessage);
});

// Arka planda bildirim dinle (Listen for background notifications)
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  console.log('Arka plan bildirimi (Background notification):', remoteMessage);
});

// Bildirime tıklanınca (When notification is tapped)
messaging().onNotificationOpenedApp((remoteMessage) => {
  console.log('Bildirime tıklandı (Notification tapped):', remoteMessage.data);
  // İlgili ekrana yönlendir (Navigate to relevant screen)
  navigateToScreen(remoteMessage.data);
});

// Uygulama kapalıyken bildirime tıklanmış mı kontrol et (Check if app opened from notification)
messaging()
  .getInitialNotification()
  .then((remoteMessage) => {
    if (remoteMessage) {
      console.log('Uygulama bildirimden açıldı (App opened from notification)');
      navigateToScreen(remoteMessage.data);
    }
  });

// Konuya abone ol (Subscribe to topic)
await messaging().subscribeToTopic('news');
await messaging().subscribeToTopic('promotions');

Crashlytics (Çökme Raporlama / Crash Reporting)

javascript
import crashlytics from '@react-native-firebase/crashlytics';

// Kullanıcı bilgisi ekle (Set user info)
crashlytics().setUserId('user123');
crashlytics().setAttribute('role', 'premium');
crashlytics().setAttributes({
  email: 'user@example.com',
  plan: 'premium',
});

// Özel log mesajı (Custom log message)
crashlytics().log('Kullanıcı sepete ürün ekledi (User added item to cart)');

// Hata yakala ve raporla (Catch and report error)
try {
  await riskyOperation();
} catch (error) {
  crashlytics().recordError(error);
  crashlytics().log(`Hata detayı (Error detail): ${error.message}`);
}

// Manuel çökme testi (Manual crash test) - sadece test için
// crashlytics().crash();

Analytics (Analitik)

javascript
import analytics from '@react-native-firebase/analytics';

// Ekran görüntüleme (Screen view)
await analytics().logScreenView({
  screen_name: 'ProductDetail',
  screen_class: 'ProductDetailScreen',
});

// Özel olay (Custom event)
await analytics().logEvent('add_to_cart', {
  item_id: 'SKU123',
  item_name: 'Laptop',
  price: 2999.99,
  currency: 'TRY',
});

// Satın alma olayı (Purchase event)
await analytics().logPurchase({
  value: 2999.99,
  currency: 'TRY',
  items: [{ item_id: 'SKU123', item_name: 'Laptop', quantity: 1 }],
});

// Kullanıcı özelliği (User property)
await analytics().setUserProperty('preferred_language', 'tr');

Remote Config (Uzaktan Yapılandırma)

javascript
import remoteConfig from '@react-native-firebase/remote-config';

// Varsayılan değerler ayarla (Set default values)
await remoteConfig().setDefaults({
  welcome_message: 'Hoşgeldiniz!',
  feature_new_ui: false,
  min_app_version: '1.0.0',
  maintenance_mode: false,
});

// Yapılandırma ayarları (Configuration settings)
await remoteConfig().setConfigSettings({
  minimumFetchIntervalMillis: 300000, // 5 dakika (5 minutes)
});

// Sunucudan al ve etkinleştir (Fetch from server and activate)
await remoteConfig().fetchAndActivate();

// Değerleri oku (Read values)
const welcomeMsg = remoteConfig().getValue('welcome_message').asString();
const isNewUi = remoteConfig().getValue('feature_new_ui').asBoolean();
const minVersion = remoteConfig().getValue('min_app_version').asString();

console.log('Karşılama mesajı (Welcome message):', welcomeMsg);

// Feature flag kontrolü (Feature flag check)
if (isNewUi) {
  // Yeni UI göster (Show new UI)
} else {
  // Eski UI göster (Show old UI)
}

Not (Note): Firebase Dynamic Links kullanımdan kaldırılmıştır (deprecated). Yeni projeler için alternatif olarak Branch.io veya Adjust kullanın.

javascript
import dynamicLinks from '@react-native-firebase/dynamic-links';

// Dinamik link oluştur (Create dynamic link)
const link = await dynamicLinks().buildShortLink({
  link: 'https://myapp.com/product/123',
  domainUriPrefix: 'https://myapp.page.link',
  android: {
    packageName: 'com.myapp.android',
  },
  ios: {
    bundleId: 'com.myapp.ios',
    appStoreId: '123456789',
  },
});

// Gelen dinamik linki dinle (Listen for incoming dynamic link)
dynamicLinks().onLink((link) => {
  console.log('Dinamik link alındı (Dynamic link received):', link.url);
  handleDeepLink(link.url);
});

App Distribution (Uygulama Dağıtımı)

Firebase App Distribution, beta test dağıtımı için kullanılır (used for beta test distribution).

bash
# Firebase CLI ile dağıtım (Distribution via Firebase CLI)

# Android APK dağıt (Distribute Android APK)
firebase appdistribution:distribute app-release.apk \
  --app YOUR_APP_ID \
  --groups "beta-testers" \
  --release-notes "Yeni özellikler eklendi (New features added)"

# iOS IPA dağıt (Distribute iOS IPA)
firebase appdistribution:distribute App.ipa \
  --app YOUR_IOS_APP_ID \
  --groups "ios-testers" \
  --release-notes "Bug düzeltmeleri (Bug fixes)"

Firebase Fiyatlandırma (Firebase Pricing)

Özellik (Feature)Spark (Ücretsiz / Free)Blaze (Kullandıkça Öde / Pay as you go)
Fiyat (Price)$0Kullanıma göre (Usage-based)
AuthenticationSınırsız (Unlimited)Sınırsız (Unlimited)
Firestore Depolama1 GiB$0.18/GiB
Firestore Okuma50K/gün$0.06/100K
Firestore Yazma20K/gün$0.18/100K
Firestore Silme20K/gün$0.02/100K
Cloud Storage5 GB$0.026/GB
Cloud FunctionsYok (None)2M çağrı/ay ücretsiz, sonra $0.40/M
Hosting10 GB depolama$0.026/GB
Realtime DB1 GB depolama, 10 GB/ay$5/GB depolama, $1/GB transfer
FCMSınırsız (Unlimited)Sınırsız (Unlimited)
CrashlyticsSınırsız (Unlimited)Sınırsız (Unlimited)
AnalyticsSınırsız (Unlimited)Sınırsız (Unlimited)
Remote ConfigSınırsız (Unlimited)Sınırsız (Unlimited)
Test Lab15 sanal/gün, 5 fiziksel/günKullanıma göre (Usage-based)

İpucu (Tip): Çoğu küçük/orta ölçekli uygulama (small/medium apps) Spark planıyla başlayabilir. Cloud Functions kullanmak istiyorsanız Blaze planına geçmeniz gerekir, ancak ücretsiz kotalar hâlâ geçerlidir.


2. Bildirim Sistemleri (Notification Systems)

Bildirim Türleri (Notification Types)

Tür (Type)Açıklama (Description)Kullanım Alanı (Use Case)
Remote (Uzak)Sunucudan gönderilen bildirimlerMesaj, kampanya, haber
Local (Yerel)Cihaz üzerinde tetiklenen bildirimlerHatırlatıcı, zamanlayıcı, alarm
Silent (Sessiz)Kullanıcıya gösterilmeyen bildirimlerArka plan veri senkronizasyonu
Rich (Zengin)Medya içeren bildirimlerResim, video, eylem düğmeleri

Platform Bildirim Servisleri (Platform Notification Services)

Servis (Service)PlatformAçıklama (Description)
FCM (Firebase Cloud Messaging)Android + iOS + WebGoogle'ın çapraz platform bildirim servisi
APNs (Apple Push Notification service)iOSApple'ın yerel bildirim servisi
OneSignalAndroid + iOS + WebÜcretsiz çapraz platform bildirim hizmeti
Expo NotificationsExpo (React Native)Expo'nun yerleşik bildirim API'si

FCM Kullanımı (FCM Usage)

FCM yapılandırması için yukarıdaki Firebase bölümüne bakın. Sunucu tarafından bildirim gönderme örneği (server-side notification example):

javascript
// Node.js sunucu tarafı (Server-side)
const admin = require('firebase-admin');
admin.initializeApp();

// Tek cihaza bildirim gönder (Send to single device)
async function sendToDevice(token, title, body, data = {}) {
  const message = {
    notification: { title, body },
    data,
    token,
    android: {
      priority: 'high',
      notification: {
        channelId: 'default',
        sound: 'default',
      },
    },
    apns: {
      payload: {
        aps: {
          sound: 'default',
          badge: 1,
        },
      },
    },
  };

  const response = await admin.messaging().send(message);
  console.log('Bildirim gönderildi (Notification sent):', response);
}

// Konuya bildirim gönder (Send to topic)
async function sendToTopic(topic, title, body) {
  await admin.messaging().send({
    notification: { title, body },
    topic,
  });
}

// Toplu bildirim gönder (Send batch notifications)
async function sendMulticast(tokens, title, body) {
  const message = {
    notification: { title, body },
    tokens, // Maksimum 500 token
  };
  const response = await admin.messaging().sendEachForMulticast(message);
  console.log(`${response.successCount} başarılı, ${response.failureCount} başarısız`);
}

OneSignal Entegrasyonu (OneSignal Integration)

javascript
// React Native OneSignal kurulumu (Setup)
// npm install react-native-onesignal

import { OneSignal } from 'react-native-onesignal';

// Başlatma (Initialize)
OneSignal.initialize('YOUR_ONESIGNAL_APP_ID');

// Bildirim izni iste (Request permission)
OneSignal.Notifications.requestPermission(true);

// Bildirim dinleyici (Notification listener)
OneSignal.Notifications.addEventListener('foregroundWillDisplay', (event) => {
  console.log('Bildirim alındı (Notification received):', event);
  event.getNotification().display(); // Bildirimi göster
});

// Bildirime tıklama dinleyici (Click listener)
OneSignal.Notifications.addEventListener('click', (event) => {
  console.log('Bildirime tıklandı (Notification clicked):', event);
  const data = event.notification.additionalData;
  navigateToScreen(data);
});

// Etiket ekleme (Add tags)
OneSignal.User.addTags({ user_type: 'premium', language: 'tr' });

Expo Notifications

javascript
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';

// İzin iste ve token al (Request permission and get token)
async function registerForPushNotifications() {
  if (!Device.isDevice) {
    alert('Fiziksel cihaz gerekli (Physical device required)');
    return;
  }

  const { status: existingStatus } = await Notifications.getPermissionsAsync();
  let finalStatus = existingStatus;

  if (existingStatus !== 'granted') {
    const { status } = await Notifications.requestPermissionsAsync();
    finalStatus = status;
  }

  if (finalStatus !== 'granted') {
    alert('Bildirim izni verilmedi (Permission not granted)');
    return;
  }

  const token = (await Notifications.getExpoPushTokenAsync()).data;
  console.log('Expo Push Token:', token);
  return token;
}

// Yerel bildirim gönder (Send local notification)
async function sendLocalNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: 'Hatırlatma (Reminder)',
      body: 'Görevinizi tamamlamayı unutmayın! (Don\'t forget your task!)',
      data: { screen: 'TaskList' },
      sound: 'default',
    },
    trigger: {
      seconds: 60, // 60 saniye sonra (after 60 seconds)
    },
  });
}

// Bildirim alındığında (When notification received)
Notifications.addNotificationReceivedListener((notification) => {
  console.log('Bildirim alındı:', notification);
});

// Bildirime tıklandığında (When notification tapped)
Notifications.addNotificationResponseReceivedListener((response) => {
  const data = response.notification.request.content.data;
  navigateToScreen(data.screen);
});

Bildirim İzin Yönetimi (Notification Permission Management)

javascript
import { Platform, Alert, Linking } from 'react-native';
import messaging from '@react-native-firebase/messaging';

async function checkAndRequestPermission() {
  if (Platform.OS === 'ios') {
    const authStatus = await messaging().requestPermission();
    if (authStatus === messaging.AuthorizationStatus.DENIED) {
      Alert.alert(
        'Bildirimler Kapalı (Notifications Disabled)',
        'Bildirimleri açmak için Ayarlar\'a gidin (Go to Settings to enable notifications)',
        [
          { text: 'İptal (Cancel)', style: 'cancel' },
          { text: 'Ayarlar (Settings)', onPress: () => Linking.openSettings() },
        ]
      );
      return false;
    }
    return true;
  }

  // Android 13+ için izin gerekli (Permission required for Android 13+)
  if (Platform.OS === 'android' && Platform.Version >= 33) {
    const { PermissionsAndroid } = require('react-native');
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
    );
    return granted === PermissionsAndroid.RESULTS.GRANTED;
  }

  return true; // Android 12 ve altı, izin gerekmiyor
}

3. BaaS Karşılaştırma (BaaS Comparison)

Backend-as-a-Service (BaaS) platformları, sunucu tarafı altyapı kurmadan backend özellikleri sunar.

Özellik (Feature)FirebaseSupabaseAppwriteAWS AmplifyPocketBase
GeliştiriciGoogleTopluluk (Open-source)Topluluk (Open-source)AmazonTopluluk (Open-source)
Veritabanı (Database)Firestore (NoSQL)PostgreSQL (SQL)MariaDBDynamoDBSQLite
Auth YöntemleriEmail, Google, Apple, Phone, AnonymousEmail, OAuth, Magic Link, PhoneEmail, OAuth, Phone, Magic URLCognito (Email, Social, Phone)Email, OAuth
Dosya Depolama (Storage)Cloud StorageS3-uyumlu (S3-compatible)Yerleşik (Built-in)S3Yerleşik (Built-in)
Push BildirimFCM (dahili)Harici servis gerekliPush desteği varPinpointHarici servis gerekli
Gerçek Zamanlı (Real-time)Firestore ListenersPostgreSQL RealtimeWebSocketAppSync (GraphQL)SSE (Server-Sent Events)
Fonksiyonlar (Functions)Cloud FunctionsEdge Functions (Deno)Cloud FunctionsLambdaYok (Go ile genişletilir)
Self-HostHayır (No)Evet (Yes)Evet (Yes)Kısmi (Partial)Evet (Yes)
Ücretsiz Katman (Free Tier)Spark (cömert)500 MB DB, 1 GB StorageSelf-host: sınırsız12 ay ücretsizSelf-host: sınırsız
SDK DesteğiiOS, Android, Web, Flutter, UnityJS, Flutter, Swift, KotlinJS, Flutter, Swift, AndroidJS, iOS, Android, FlutterJS, Dart (topluluk)
Admin PanelFirebase ConsoleSupabase DashboardAppwrite ConsoleAWS ConsoleYerleşik Admin UI
Fiyatlandırma (Pricing)Kullanıma göre (Pay-as-you-go)$0 → $25/ay → Kullanıma göreSelf-host: ücretsiz, Cloud: $15/ayKullanıma göreÜcretsiz (Self-host)
En İyi KullanımHızlı prototip, küçük-orta projeSQL seven ekipler, open-sourceSelf-host isteyen ekiplerAWS ekosistemi kullanıcılarıTek dosya, basit projeler

BaaS Seçim Rehberi (BaaS Selection Guide)

  • Firebase: Hızlı başlangıç, Google ekosistemi, küçük-orta projeler
  • Supabase: PostgreSQL tercih edenler, açık kaynak, SQL sorguları gerekli projeler
  • Appwrite: Kendi sunucunuzda barındırmak isteyenler, veri gizliliği öncelikli projeler
  • AWS Amplify: Zaten AWS kullanan ekipler, kurumsal projeler
  • PocketBase: Tek dosya backend, hızlı prototip, Go bilgisi olanlar

4. Mobil UI Kütüphaneleri (Mobile UI Libraries)

React Native UI Kütüphaneleri (React Native UI Libraries)

Kütüphane (Library)Açıklama (Description)Tema (Theming)Boyut (Size)Popülerlik
React Native PaperMaterial Design 3 bileşenleriEvet, kapsamlıOrta⭐ En popüler
NativeBasePlatformlar arası UI bileşenleriEvetBüyükYüksek
TamaguiOptimize, evrensel UI (web + native)Evet, güçlüHafif (compile-time)Yükselen
Gluestack UINativeBase'in yeni nesil haliEvetHafifYeni
React Native ElementsBasit, özelleştirilebilir bileşenlerKısmiOrtaYüksek
Shoutem UIHazır bileşen setiEvetBüyükOrta
javascript
// React Native Paper kullanım örneği (Usage example)
import { Provider as PaperProvider, Button, Card, Text } from 'react-native-paper';

function App() {
  return (
    <PaperProvider>
      <Card>
        <Card.Title title="Ürün Adı (Product Name)" />
        <Card.Content>
          <Text variant="bodyMedium">Ürün açıklaması (Product description)</Text>
        </Card.Content>
        <Card.Actions>
          <Button mode="contained" onPress={() => console.log('Sepete eklendi')}>
            Sepete Ekle (Add to Cart)
          </Button>
        </Card.Actions>
      </Card>
    </PaperProvider>
  );
}

// Tamagui kullanım örneği (Usage example)
import { Button, H1, Paragraph, YStack } from 'tamagui';

function Screen() {
  return (
    <YStack padding="$4" gap="$3">
      <H1>Başlık (Title)</H1>
      <Paragraph>İçerik metni (Content text)</Paragraph>
      <Button theme="blue" size="$4">
        Devam Et (Continue)
      </Button>
    </YStack>
  );
}

Flutter UI Kütüphaneleri (Flutter UI Libraries)

Kütüphane (Library)Açıklama (Description)Platform Görünümü
Material 3Google'ın Material Design 3Android (varsayılan)
CupertinoApple iOS tarzı bileşenleriOS (yerel görünüm)
FlutterFlowSürükle-bırak UI oluşturucuHer iki platform
GetWidget1000+ hazır bileşenHer iki platform
Flutter NeumorphicNeumorphic tasarım bileşenleriHer iki platform
dart
// Material 3 ve Cupertino birlikte kullanımı (Combined usage)
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:io' show Platform;

Widget buildButton(String text, VoidCallback onPressed) {
  if (Platform.isIOS) {
    return CupertinoButton.filled(
      onPressed: onPressed,
      child: Text(text),
    );
  }
  return FilledButton(
    onPressed: onPressed,
    child: Text(text),
  );
}

// Material 3 tema yapılandırması (Theme configuration)
MaterialApp(
  theme: ThemeData(
    useMaterial3: true,
    colorSchemeSeed: Colors.blue,
    brightness: Brightness.light,
  ),
  darkTheme: ThemeData(
    useMaterial3: true,
    colorSchemeSeed: Colors.blue,
    brightness: Brightness.dark,
  ),
);

İkon Kütüphaneleri (Icon Libraries)

Kütüphane (Library)Platformİkon SayısıKullanım
@expo/vector-iconsReact Native (Expo)3000+<Ionicons name="heart" size={24} />
react-native-vector-iconsReact Native (Bare)3000+<Icon name="heart" size={24} />
flutter_iconsFlutterÇoklu setIcon(Icons.favorite)
Phosphor IconsRN + Flutter7000+Tutarlı, modern tasarım
LucideReact Native1500+Hafif, SVG tabanlı

Animasyon Kütüphaneleri (Animation Libraries)

Kütüphane (Library)PlatformAçıklama (Description)Performans
LottieRN + FlutterAfter Effects JSON animasyonlarıİyi, önceden hazırlanmış
RiveRN + Flutterİnteraktif, durum bazlı animasyonlarÇok iyi, küçük dosya boyutu
ReanimatedReact NativeGelişmiş, UI thread animasyonlarıMükemmel, 60/120 FPS
MotiReact NativeReanimated üzerine deklaratif APIÇok iyi
Flutter AnimateFlutterKolay zincirleme animasyonlarİyi
Rive (Flutter)Flutterİnteraktif animasyon motoruÇok iyi
javascript
// Lottie kullanımı (Lottie usage) - React Native
import LottieView from 'lottie-react-native';

<LottieView
  source={require('./animations/loading.json')}
  autoPlay
  loop
  style={{ width: 200, height: 200 }}
/>

// Reanimated kullanımı (Reanimated usage)
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  withTiming,
} from 'react-native-reanimated';

function AnimatedBox() {
  const offset = useSharedValue(0);
  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: withSpring(offset.value) }],
  }));

  return (
    <Animated.View style={[styles.box, animatedStyle]}>
      <Button title="Hareket Et (Move)" onPress={() => { offset.value = offset.value === 0 ? 200 : 0; }} />
    </Animated.View>
  );
}
dart
// Lottie kullanımı (Lottie usage) - Flutter
import 'package:lottie/lottie.dart';

Lottie.asset(
  'assets/animations/loading.json',
  width: 200,
  height: 200,
  repeat: true,
);

// Rive kullanımı (Rive usage) - Flutter
import 'package:rive/rive.dart';

const RiveAnimation.asset(
  'assets/animations/button.riv',
  fit: BoxFit.contain,
);

5. Mobil Veritabanları (Mobile Databases)

Cihaz üzerinde (on-device) veri depolama çözümleri.

Karşılaştırma Tablosu (Comparison Table)

Çözüm (Solution)PlatformTür (Type)Sorgulama (Querying)Şifreleme (Encryption)PerformansBoyut
AsyncStorageReact NativeAnahtar-değer (Key-value)Yok (None)YokDüşük-OrtaKüçük
SecureStoreExpo (RN)Anahtar-değer, şifreliYokEvet (Keychain/Keystore)OrtaKüçük
MMKVReact NativeAnahtar-değerYokEvet (opsiyonel)Çok hızlıKüçük
SQLiteRN + Flutterİlişkisel SQL (Relational)SQL sorgularıOpsiyonel (SQLCipher)YüksekOrta
RealmRN + FlutterNesne tabanlı (Object-based)Realm Query LanguageEvetÇok yüksekOrta
HiveFlutterNoSQL, anahtar-değerSınırlıEvet (AES)Çok hızlıKüçük
WatermelonDBReact Nativeİlişkisel, lazySQL (SQLite tabanlı)OpsiyonelÇok yüksek (lazy loading)Orta
IsarFlutterNoSQL, tam metin aramaCRUD + Full-textOpsiyonelÇok yüksekOrta
DriftFlutterTip-güvenli SQL (Type-safe SQL)SQL (kod oluşturma)OpsiyonelYüksekOrta

Ne Zaman Hangisi? (When to Use Which?)

İhtiyaç (Need)Önerilen (Recommended)
Basit ayarlar, token saklama (Simple settings)MMKV veya SecureStore
Hassas veri (şifre, token) (Sensitive data)SecureStore (Expo) veya Keychain/Keystore
Küçük JSON verileri (Small JSON data)MMKV veya AsyncStorage
İlişkisel veri, karmaşık sorgular (Relational data)SQLite veya WatermelonDB
Nesne tabanlı, senkronizasyon (Object-based, sync)Realm
Flutter'da hızlı yerel depolamaHive veya Isar
Büyük veri, performans kritik (Large data, perf-critical)WatermelonDB (RN) veya Isar (Flutter)

Kullanım Örnekleri (Usage Examples)

javascript
// ---------- MMKV (React Native) ----------
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

// Veri kaydet (Save data)
storage.set('user.name', 'Fahri');
storage.set('user.age', 28);
storage.set('user.isPremium', true);
storage.set('user.settings', JSON.stringify({ theme: 'dark', lang: 'tr' }));

// Veri oku (Read data)
const name = storage.getString('user.name');    // 'Fahri'
const age = storage.getNumber('user.age');       // 28
const isPremium = storage.getBoolean('user.isPremium'); // true
const settings = JSON.parse(storage.getString('user.settings') ?? '{}');

// Veri sil (Delete data)
storage.delete('user.name');

// Tüm anahtarlar (All keys)
const allKeys = storage.getAllKeys(); // ['user.age', 'user.isPremium', ...]

// Şifreli depolama (Encrypted storage)
const secureStorage = new MMKV({
  id: 'secure-storage',
  encryptionKey: 'my-encryption-key',
});
javascript
// ---------- WatermelonDB (React Native) ----------
import { Database, Model, Q } from '@nozbe/watermelondb';
import { field, date, children } from '@nozbe/watermelondb/decorators';

// Model tanımla (Define model)
class Post extends Model {
  static table = 'posts';
  static associations = {
    comments: { type: 'has_many', foreignKey: 'post_id' },
  };

  @field('title') title;
  @field('body') body;
  @field('is_published') isPublished;
  @date('created_at') createdAt;
  @children('comments') comments;
}

// Sorgu örnekleri (Query examples)
const publishedPosts = await database
  .get('posts')
  .query(Q.where('is_published', true))
  .fetch();

const recentPosts = await database
  .get('posts')
  .query(
    Q.where('is_published', true),
    Q.sortBy('created_at', Q.desc),
    Q.take(10)
  )
  .fetch();
dart
// ---------- Hive (Flutter) ----------
import 'package:hive_flutter/hive_flutter.dart';

// Başlatma (Initialize)
await Hive.initFlutter();
var box = await Hive.openBox('settings');

// Veri kaydet (Save data)
await box.put('theme', 'dark');
await box.put('language', 'tr');
await box.put('user', {'name': 'Fahri', 'age': 28});

// Veri oku (Read data)
String theme = box.get('theme', defaultValue: 'light');
Map user = box.get('user');

// Veri sil (Delete data)
await box.delete('theme');

// Şifreli kutu (Encrypted box)
final encryptionKey = Hive.generateSecureKey();
var secureBox = await Hive.openBox('secure',
  encryptionCipher: HiveAesCipher(encryptionKey),
);
dart
// ---------- Isar (Flutter) ----------
import 'package:isar/isar.dart';

part 'user.g.dart'; // Kod oluşturma (Code generation)

@collection
class User {
  Id id = Isar.autoIncrement;

  @Index()
  late String name;

  late int age;

  @Index(type: IndexType.value)
  late String email;
}

// Kullanım (Usage)
final isar = await Isar.open([UserSchema]);

// Yazma (Write)
await isar.writeTxn(() async {
  final user = User()
    ..name = 'Fahri'
    ..age = 28
    ..email = 'fahri@example.com';
  await isar.users.put(user);
});

// Sorgulama (Query)
final users = await isar.users
    .filter()
    .ageGreaterThan(18)
    .and()
    .nameContains('Fah')
    .sortByName()
    .findAll();

// Tam metin arama (Full-text search)
final results = await isar.users
    .filter()
    .nameContains('fahri', caseSensitive: false)
    .findAll();

6. CI/CD & Build Araçları (CI/CD & Build Tools)

CI/CD Platformları Karşılaştırma (CI/CD Platforms Comparison)

Araç (Tool)Platform DesteğiÜcretsiz KatmanÖzellik (Feature)
FastlaneiOS + AndroidAçık kaynak (Open-source)Yerel otomasyon, kod imzalama, mağaza yükleme
EAS BuildExpo (React Native)30 build/ayBulut build, OTA güncelleme, mağaza submit
CodemagicFlutter + RN + Native500 build dakikası/ayFlutter'a özel, kod imzalama
GitHub ActionsTüm platformlar2000 dakika/ayEsnek, geniş marketplace
App CenteriOS + Android + RNSınırsız build (bazı limitler)Microsoft, test + dağıtım + analitik
BitriseiOS + Android + Flutter + RN300 kredi/ayMobil odaklı, hazır adımlar

Fastlane

Fastlane, mobil uygulama build, test ve dağıtım süreçlerini otomatikleştiren açık kaynak bir araçtır.

ruby
# fastlane/Fastfile

default_platform(:ios)

platform :ios do
  desc "Beta dağıtımı (Beta distribution)"
  lane :beta do
    increment_build_number
    build_app(
      scheme: "MyApp",
      export_method: "ad-hoc"
    )
    upload_to_testflight
    slack(message: "iOS beta yüklendi! (iOS beta uploaded!)")
  end

  desc "App Store'a yükleme (Upload to App Store)"
  lane :release do
    increment_build_number
    build_app(
      scheme: "MyApp",
      export_method: "app-store"
    )
    upload_to_app_store(
      submit_for_review: true,
      automatic_release: false
    )
  end
end

platform :android do
  desc "Play Store internal test"
  lane :beta do
    gradle(
      task: "bundle",
      build_type: "Release"
    )
    upload_to_play_store(
      track: "internal",
      aab: "app/build/outputs/bundle/release/app-release.aab"
    )
  end

  desc "Play Store production"
  lane :release do
    gradle(task: "bundle", build_type: "Release")
    upload_to_play_store(track: "production")
  end
end

EAS Build (Expo Application Services)

bash
# EAS CLI kurulumu (Install EAS CLI)
npm install -g eas-cli

# Giriş ve yapılandırma (Login and configure)
eas login
eas build:configure
json
// eas.json
{
  "cli": { "version": ">= 5.0.0" },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": { "simulator": true }
    },
    "preview": {
      "distribution": "internal",
      "android": { "buildType": "apk" }
    },
    "production": {
      "autoIncrement": true
    }
  },
  "submit": {
    "production": {
      "ios": {
        "appleId": "your@email.com",
        "ascAppId": "1234567890",
        "appleTeamId": "TEAM_ID"
      },
      "android": {
        "serviceAccountKeyPath": "./google-service-account.json",
        "track": "internal"
      }
    }
  }
}
bash
# Build komutları (Build commands)
eas build --platform ios --profile production   # iOS production build
eas build --platform android --profile preview  # Android preview build
eas build --platform all --profile production   # Her iki platform

# Mağazaya gönder (Submit to store)
eas submit --platform ios --profile production
eas submit --platform android --profile production

# OTA güncelleme (Over-the-Air update)
eas update --branch production --message "Bug düzeltmesi (Bug fix)"

GitHub Actions - Mobil CI/CD

yaml
# .github/workflows/mobile-ci.yml
name: Mobile CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  # React Native Test
  test-rn:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run test -- --coverage

  # Android Build
  build-android:
    needs: test-rn
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - name: Android Build
        working-directory: android
        run: ./gradlew assembleRelease
      - uses: actions/upload-artifact@v4
        with:
          name: android-release
          path: android/app/build/outputs/apk/release/

  # iOS Build
  build-ios:
    needs: test-rn
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: cd ios && pod install
      - name: iOS Build
        run: |
          xcodebuild -workspace ios/MyApp.xcworkspace \
            -scheme MyApp \
            -configuration Release \
            -sdk iphoneos \
            -archivePath build/MyApp.xcarchive \
            archive

Codemagic (Flutter CI/CD)

yaml
# codemagic.yaml
workflows:
  flutter-production:
    name: Flutter Production
    max_build_duration: 60
    environment:
      flutter: stable
      xcode: latest
      cocoapods: default
      groups:
        - app_store_credentials
        - google_play
    triggering:
      events:
        - push
      branch_patterns:
        - pattern: main
          include: true
    scripts:
      - name: Bağımlılıkları yükle (Install dependencies)
        script: flutter pub get
      - name: Testleri çalıştır (Run tests)
        script: flutter test
      - name: Android build
        script: flutter build appbundle --release
      - name: iOS build
        script: flutter build ipa --release --export-options-plist=/path/to/ExportOptions.plist
    artifacts:
      - build/**/outputs/**/*.aab
      - build/ios/ipa/*.ipa
    publishing:
      google_play:
        credentials: $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
        track: internal
      app_store_connect:
        auth: integration

7. Test & Debug Araçları (Test & Debug Tools)

Test & Debug Araçları Karşılaştırma (Comparison)

Araç (Tool)PlatformTür (Type)Açıklama (Description)
FlipperReact NativeDebugAğ, veritabanı, layout inceleme
React Native DebuggerReact NativeDebugRedux DevTools + Chrome DevTools
ReactotronReact NativeDebugAPI izleme, state görüntüleme, benchmark
Flutter DevToolsFlutterDebug + ProfilWidget ağacı, performans, bellek
DetoxReact NativeE2E TestGri kutu E2E test framework
PatrolFlutterE2E TestYerel UI etkileşimi destekli E2E
MaestroRN + Flutter + NativeE2E TestBasit YAML tabanlı UI testleri
Firebase Test LabAndroid + iOSBulut TestGerçek cihazlarda otomatik test

Detox (React Native E2E Test)

javascript
// e2e/login.test.js
describe('Giriş Ekranı (Login Screen)', () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('başarılı giriş yapabilmeli (should login successfully)', async () => {
    // Email gir (Enter email)
    await element(by.id('email-input')).typeText('test@example.com');
    // Şifre gir (Enter password)
    await element(by.id('password-input')).typeText('password123');
    // Giriş butonuna tıkla (Tap login button)
    await element(by.id('login-button')).tap();
    // Ana ekranın görünmesini bekle (Wait for home screen)
    await waitFor(element(by.id('home-screen')))
      .toBeVisible()
      .withTimeout(5000);
    // Karşılama mesajını kontrol et (Check welcome message)
    await expect(element(by.text('Hoşgeldiniz'))).toBeVisible();
  });

  it('hatalı girişte uyarı göstermeli (should show error on invalid login)', async () => {
    await element(by.id('email-input')).typeText('wrong@example.com');
    await element(by.id('password-input')).typeText('wrongpass');
    await element(by.id('login-button')).tap();

    await waitFor(element(by.text('Geçersiz kimlik bilgileri')))
      .toBeVisible()
      .withTimeout(3000);
  });
});

Flutter Test

dart
// test/widget_test.dart (Birim ve Widget testleri / Unit and Widget tests)
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/screens/login_screen.dart';

void main() {
  group('LoginScreen', () {
    testWidgets('başarılı giriş (successful login)', (tester) async {
      await tester.pumpWidget(const MaterialApp(home: LoginScreen()));

      // Email gir (Enter email)
      await tester.enterText(find.byKey(const Key('email-input')), 'test@example.com');
      // Şifre gir (Enter password)
      await tester.enterText(find.byKey(const Key('password-input')), 'password123');
      // Giriş butonuna tıkla (Tap login button)
      await tester.tap(find.byKey(const Key('login-button')));
      await tester.pumpAndSettle();

      // Sonucu doğrula (Verify result)
      expect(find.text('Hoşgeldiniz'), findsOneWidget);
    });
  });
}
dart
// integration_test/app_test.dart (Entegrasyon testi / Integration test)
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:my_app/main.dart' as app;

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('tam uygulama akışı (full app flow)', (tester) async {
    app.main();
    await tester.pumpAndSettle();

    // Giriş yap (Login)
    await tester.enterText(find.byKey(const Key('email')), 'test@example.com');
    await tester.enterText(find.byKey(const Key('password')), 'pass123');
    await tester.tap(find.byKey(const Key('login-btn')));
    await tester.pumpAndSettle();

    // Ana sayfa kontrolü (Home page check)
    expect(find.text('Ana Sayfa'), findsOneWidget);
  });
}

Patrol (Flutter E2E with Native)

dart
// integration_test/notifications_test.dart
import 'package:patrol/patrol.dart';

void main() {
  patrolTest('bildirim izni testi (notification permission test)', ($) async {
    await $.pumpWidgetAndSettle(const MyApp());

    // Bildirim izni butonuna tıkla (Tap notification permission button)
    await $('Bildirimlere İzin Ver').tap();

    // Yerel izin dialogunu kabul et (Accept native permission dialog)
    await $.native.tap(NativeSelector(text: 'Allow'));

    // Sonucu doğrula (Verify result)
    expect($('Bildirimler Açık'), findsOneWidget);
  });
}

Firebase Test Lab

bash
# Android testlerini Firebase Test Lab'da çalıştır (Run Android tests on Firebase Test Lab)
gcloud firebase test android run \
  --type instrumentation \
  --app app-debug.apk \
  --test app-debug-androidTest.apk \
  --device model=Pixel6,version=33,locale=tr,orientation=portrait \
  --device model=Pixel4,version=30,locale=tr \
  --timeout 300s \
  --results-dir test-results

# Robo test (otomatik UI keşfi / automatic UI exploration)
gcloud firebase test android run \
  --type robo \
  --app app-release.apk \
  --device model=Pixel6,version=33 \
  --timeout 120s

# iOS testleri (iOS tests)
gcloud firebase test ios run \
  --test ios_test.zip \
  --device model=iphone14pro,version=16.6

Reactotron Yapılandırma (Reactotron Configuration)

javascript
// ReactotronConfig.js
import Reactotron from 'reactotron-react-native';
import { reactotronRedux } from 'reactotron-redux';
import reactotronZustand from 'reactotron-plugin-zustand';

const reactotron = Reactotron
  .configure({ name: 'MyApp' })
  .useReactNative({
    networking: { ignoreUrls: /symbolicate/ },
    errors: { veto: () => false },
    editor: true,
    overlay: true,
  })
  .use(reactotronRedux())
  .connect();

// API çağrılarını logla (Log API calls)
reactotron.onCustomCommand({
  command: 'clearAsyncStorage',
  handler: () => {
    AsyncStorage.clear();
    reactotron.display({ name: 'AsyncStorage', value: 'Temizlendi (Cleared)' });
  },
});

export default reactotron;

8. Paket & Versiyon Yönetimi (Package & Version Management)

SemVer (Semantic Versioning / Anlamsal Sürümleme)

SemVer formatı: MAJOR.MINOR.PATCH (örn. 2.4.1)

Bileşen (Component)Açıklama (Description)Ne Zaman Artırılır? (When to Increment?)
MAJORAna sürüm (Major version)Geriye uyumsuz değişiklikler (Breaking changes)
MINORKüçük sürüm (Minor version)Geriye uyumlu yeni özellikler (Backward-compatible features)
PATCHYama sürümü (Patch version)Geriye uyumlu hata düzeltmeleri (Bug fixes)

Sürüm Aralığı Sembolleri (Version Range Symbols)

Sembol (Symbol)Anlamı (Meaning)Örnek (Example)Eşleşen Aralık (Matched Range)
^ (Caret)MINOR ve PATCH güncellenebilir^2.4.1>=2.4.1 <3.0.0
~ (Tilde)Sadece PATCH güncellenebilir~2.4.1>=2.4.1 <2.5.0
Tam (Exact)Sadece belirtilen sürüm2.4.1Yalnızca 2.4.1
>=Belirtilen ve üstü>=2.4.12.4.1 ve sonrası
*Herhangi bir sürüm*Tüm sürümler (önerilmez)

Öneri (Recommendation): Çoğu paket için ^ (caret) kullanın. Kritik paketlerde (native modüller gibi) tam sürüm (exact) tercih edin.


React Native Paket Yönetimi (React Native Package Management)

package.json Yapısı (Structure)

json
{
  "name": "my-app",
  "version": "1.2.0",
  "dependencies": {
    "react": "18.2.0",
    "react-native": "0.73.4",
    "@react-native-firebase/app": "^19.0.0",
    "react-native-reanimated": "~3.6.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "typescript": "^5.3.0",
    "jest": "^29.7.0",
    "eslint": "^8.56.0"
  }
}

Temel Komutlar (Essential Commands)

bash
# Bağımlılıkları yükle (Install dependencies)
npm install           # veya: yarn install

# Paket ekle (Add package)
npm install lodash    # dependencies'e ekler
npm install -D jest   # devDependencies'e ekler

# Güncel olmayan paketleri kontrol et (Check outdated packages)
npm outdated

# Örnek çıktı (Example output):
# Package                Current  Wanted  Latest
# react-native           0.73.2   0.73.4  0.74.0
# @react-navigation/...  6.1.9    6.1.11  7.0.0

# Güvenlik denetimi (Security audit)
npm audit
npm audit fix          # Otomatik düzelt (Auto-fix)
npm audit fix --force  # Zorla düzelt (dikkatli olun / be careful)

# npm-check-updates (ncu) - tüm paketleri güncellemek için
npx npm-check-updates         # Güncelleme listesini göster (Show update list)
npx npm-check-updates -u      # package.json'ı güncelle (Update package.json)
npx npm-check-updates -i      # İnteraktif seçim (Interactive selection)

# Expo projeleri için (For Expo projects)
npx expo-doctor               # Uyumluluk kontrolü (Compatibility check)
npx expo install --check       # SDK uyumlu sürümleri kontrol et

# Paket bilgisi (Package info)
npm info react-native versions # Mevcut sürümler (Available versions)
npm ls react-native            # Bağımlılık ağacı (Dependency tree)

Flutter Paket Yönetimi (Flutter Package Management)

pubspec.yaml Yapısı (Structure)

yaml
name: my_app
description: Uygulama açıklaması (App description)
version: 1.2.0+3  # version+buildNumber

environment:
  sdk: '>=3.2.0 <4.0.0'
  flutter: '>=3.16.0'

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.24.0
  cloud_firestore: ^4.14.0
  provider: ^6.1.0
  http: ^1.2.0
  shared_preferences: ^2.2.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0
  build_runner: ^2.4.0
  mockito: ^5.4.0

Temel Komutlar (Essential Commands)

bash
# Bağımlılıkları yükle (Install dependencies)
flutter pub get

# Paket ekle (Add package)
flutter pub add provider
flutter pub add --dev mockito

# Güncel olmayan paketleri kontrol et (Check outdated)
flutter pub outdated

# Paketleri güncelle (Upgrade packages)
flutter pub upgrade                    # pubspec.yaml aralığında güncelle
flutter pub upgrade --major-versions   # Major sürümlere de güncelle

# Paket arama (Search packages)
# pub.dev adresinden arayın (Search on pub.dev)

# Bağımlılık çözünürlüğü (Dependency resolution)
flutter pub deps           # Bağımlılık ağacı (Dependency tree)

# Kod oluşturma (Code generation)
dart run build_runner build --delete-conflicting-outputs

npm vs yarn vs Flutter Hızlı Referans (Quick Reference)

İşlem (Operation)npmyarnFlutter
Yükle (Install)npm installyarnflutter pub get
Paket ekle (Add)npm install pkgyarn add pkgflutter pub add pkg
Dev paket eklenpm install -D pkgyarn add -D pkgflutter pub add --dev pkg
Paket sil (Remove)npm uninstall pkgyarn remove pkgPubspec'ten sil + pub get
Güncelle (Update)npm updateyarn upgradeflutter pub upgrade
Güncel olmayan (Outdated)npm outdatedyarn outdatedflutter pub outdated
Çalıştır (Run script)npm run devyarn devflutter run
Güvenlik (Audit)npm audityarn auditN/A
Temizle (Clean)rm -rf node_modulesyarn cache cleanflutter clean
Lock dosyasıpackage-lock.jsonyarn.lockpubspec.lock
Registrynpmjs.comnpmjs.compub.dev

Best Practices (En İyi Uygulamalar)

  1. Lock dosyasını commit edin (Commit lock file):

    • package-lock.json veya yarn.lock dosyasını her zaman Git'e commit edin
    • pubspec.lock dosyasını uygulama projelerinde commit edin (kütüphanelerde değil)
  2. Paketleri tek tek güncelleyin (Update packages one by one):

    bash
    # Kötü yaklaşım (Bad approach)
    npx ncu -u && npm install  # Hepsini birden güncelleme
    
    # İyi yaklaşım (Good approach)
    npm install react-native@0.73.4  # Tek tek, test ederek güncelle
    npm test                          # Her güncellemeden sonra test et
  3. Dependabot / Renovate kullanın:

    yaml
    # .github/dependabot.yml
    version: 2
    updates:
      - package-ecosystem: "npm"
        directory: "/"
        schedule:
          interval: "weekly"
        open-pull-requests-limit: 10
        labels:
          - "dependencies"
        ignore:
          - dependency-name: "react-native"
            update-types: ["version-update:semver-major"]
  4. Güvenlik kontrolü otomatikleştirin (Automate security checks):

    yaml
    # CI/CD pipeline'a ekleyin (Add to CI/CD pipeline)
    - name: Güvenlik denetimi (Security audit)
      run: npm audit --production --audit-level=high
  5. Kullanılmayan bağımlılıkları temizleyin (Clean unused dependencies):

    bash
    # React Native
    npx depcheck  # Kullanılmayan paketleri bul (Find unused packages)
    
    # Flutter
    dart pub deps --no-dev  # Bağımlılık ağacını incele

9. Diğer Araçlar (Other Tools)

OTA Güncelleme (Over-the-Air Updates)

Araç (Tool)PlatformAçıklama (Description)
Expo Updates / EAS UpdateExpo (RN)JavaScript bundle güncelleme, anında yayınlama
CodePush (App Center)React NativeMicrosoft'un OTA çözümü (kullanımdan kalkıyor)
ShorebirdFlutterFlutter için code push çözümü
javascript
// Expo Updates kullanımı (Expo Updates usage)
import * as Updates from 'expo-updates';

async function checkForUpdates() {
  try {
    const update = await Updates.checkForUpdateAsync();
    if (update.isAvailable) {
      await Updates.fetchUpdateAsync();
      // Kullanıcıya sor veya otomatik yeniden başlat
      Alert.alert(
        'Güncelleme Mevcut (Update Available)',
        'Yeni bir güncelleme indirildi. Uygulamayı yeniden başlatmak ister misiniz?',
        [
          { text: 'Sonra (Later)', style: 'cancel' },
          { text: 'Yeniden Başlat (Restart)', onPress: () => Updates.reloadAsync() },
        ]
      );
    }
  } catch (error) {
    console.log('Güncelleme kontrolü hatası (Update check error):', error);
  }
}

Hata İzleme & Performans (Error Tracking & Performance)

javascript
// Sentry kurulumu (Sentry setup) - React Native
// npm install @sentry/react-native

import * as Sentry from '@sentry/react-native';

Sentry.init({
  dsn: 'https://your-dsn@sentry.io/project-id',
  tracesSampleRate: 1.0,
  environment: __DEV__ ? 'development' : 'production',
});

// Hata yakalama (Error capture)
try {
  await riskyOperation();
} catch (error) {
  Sentry.captureException(error);
  Sentry.addBreadcrumb({
    category: 'user-action',
    message: 'Kullanıcı ödeme yaptı (User made payment)',
    level: 'info',
  });
}

// Performans izleme (Performance monitoring)
const transaction = Sentry.startTransaction({ name: 'loadProducts' });
const span = transaction.startChild({ op: 'db.query' });
await fetchProducts();
span.finish();
transaction.finish();

Ödeme Sistemleri (Payment Systems)

Araç (Tool)PlatformAçıklama (Description)Komisyon
RevenueCatRN + Flutter + NativeAbonelik yönetimi (Subscription management)$0-$2500/ay gelir: ücretsiz
StripeRN + Flutter + WebKapsamlı ödeme altyapısı%2.9 + $0.30
In-App PurchasesiOS + AndroidMağaza içi satın almaApple: %30, Google: %15-30
javascript
// RevenueCat kullanımı (RevenueCat usage)
import Purchases from 'react-native-purchases';

// Başlatma (Initialize)
Purchases.configure({ apiKey: 'YOUR_REVENUECAT_API_KEY' });

// Mevcut teklifleri al (Get offerings)
async function getSubscriptionPlans() {
  const offerings = await Purchases.getOfferings();
  if (offerings.current) {
    const packages = offerings.current.availablePackages;
    return packages.map(pkg => ({
      identifier: pkg.identifier,
      price: pkg.product.priceString,
      title: pkg.product.title,
    }));
  }
}

// Satın alma (Purchase)
async function purchasePackage(pkg) {
  try {
    const { customerInfo } = await Purchases.purchasePackage(pkg);
    if (customerInfo.entitlements.active['premium']) {
      console.log('Premium aktif (Premium active)');
    }
  } catch (error) {
    if (!error.userCancelled) {
      console.error('Satın alma hatası (Purchase error):', error);
    }
  }
}

// Abonelik durumunu kontrol et (Check subscription status)
async function checkSubscription() {
  const customerInfo = await Purchases.getCustomerInfo();
  return customerInfo.entitlements.active['premium'] !== undefined;
}

Diğer Araçlar Referans Tablosu (Other Tools Reference Table)

Araç (Tool)Kategori (Category)PlatformResmi Link
Expo UpdatesOTA GüncellemeExpo (RN)docs.expo.dev/versions/latest/sdk/updates
SentryHata İzlemeRN + Fluttersentry.io
RevenueCatÖdeme/AbonelikRN + Flutterrevenuecat.com
StripeÖdeme İşlemeRN + Flutterstripe.com
i18nextÇoklu Dil (i18n)React Nativei18next.com
easy_localizationÇoklu Dil (i18n)Flutterpub.dev/packages/easy_localization
react-native-mapsHarita (Maps)React Nativegithub.com/react-native-maps
google_maps_flutterHarita (Maps)Flutterpub.dev/packages/google_maps_flutter
react-native-cameraKamera (Camera)React Nativegithub.com/mrousavy/react-native-vision-camera
cameraKamera (Camera)Flutterpub.dev/packages/camera
react-native-image-pickerGaleri/KameraReact Nativegithub.com/react-native-image-picker
image_pickerGaleri/KameraFlutterpub.dev/packages/image_picker
MapboxHarita (Maps)RN + Fluttermapbox.com
FirebaseBaaSRN + Flutterfirebase.google.com
SupabaseBaaSRN + Fluttersupabase.com
AppwriteBaaSRN + Flutterappwrite.io
OneSignalBildirimRN + Flutteronesignal.com
FastlaneCI/CDiOS + Androidfastlane.tools
CodemagicCI/CDFlutter + RNcodemagic.io

i18n (Çoklu Dil Desteği / Internationalization)

javascript
// React Native - i18next kullanımı (i18next usage)
// npm install i18next react-i18next

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

const resources = {
  tr: {
    translation: {
      welcome: 'Hoşgeldiniz',
      login: 'Giriş Yap',
      register: 'Kayıt Ol',
      settings: 'Ayarlar',
      profile: 'Profil',
      itemCount_one: '{{count}} ürün',
      itemCount_other: '{{count}} ürün',
    },
  },
  en: {
    translation: {
      welcome: 'Welcome',
      login: 'Login',
      register: 'Register',
      settings: 'Settings',
      profile: 'Profile',
      itemCount_one: '{{count}} item',
      itemCount_other: '{{count}} items',
    },
  },
};

i18n.use(initReactI18next).init({
  resources,
  lng: 'tr', // Varsayılan dil (Default language)
  fallbackLng: 'en',
  interpolation: { escapeValue: false },
});

// Kullanım (Usage)
import { useTranslation } from 'react-i18next';

function HomeScreen() {
  const { t, i18n } = useTranslation();

  return (
    <View>
      <Text>{t('welcome')}</Text>
      <Text>{t('itemCount', { count: 5 })}</Text>
      <Button
        title="English"
        onPress={() => i18n.changeLanguage('en')}
      />
    </View>
  );
}

Harita Entegrasyonu (Maps Integration)

javascript
// React Native Maps kullanımı (Usage)
import MapView, { Marker, Callout } from 'react-native-maps';

function MapScreen() {
  const [region, setRegion] = useState({
    latitude: 41.0082,
    longitude: 28.9784,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
  });

  return (
    <MapView
      style={{ flex: 1 }}
      region={region}
      onRegionChangeComplete={setRegion}
      showsUserLocation
      showsMyLocationButton
    >
      <Marker
        coordinate={{ latitude: 41.0082, longitude: 28.9784 }}
        title="İstanbul"
        description="Türkiye'nin en büyük şehri"
      >
        <Callout>
          <View>
            <Text>İstanbul (Istanbul)</Text>
            <Text>Nüfus: ~16 milyon</Text>
          </View>
        </Callout>
      </Marker>
    </MapView>
  );
}

Rehber (Guide)Açıklama (Description)
React Native RehberiReact Native ile mobil uygulama geliştirme
Flutter RehberiFlutter ile çapraz platform geliştirme
Mobil Genel BakışMobil teknolojiler karşılaştırma ve yol haritası
Docker RehberiBackend servisleri konteynerleştirme
API Geliştirme RehberiREST/GraphQL API tasarımı
PostgreSQL RehberiSupabase'in kullandığı veritabanı
Redis RehberiÖnbellekleme ve oturum yönetimi
TypeScript RehberiReact Native ile TypeScript kullanımı

Son Güncelleme (Last Updated): 2026-04-11

Developer Guides & Technical References