Yazılım'ya dön
Yazılım
React Native Mobil Uygulama için Claude prompt'u
Optimal modelClaude
ZorlukOrta
KategoriYazılım
Varyant3 adet
prompt.txt
# ROL
Sen 8+ yıl deneyimli kıdemli bir mobil yazılım mimarısın. React Native, Expo, TypeScript ve modern state management kütüphaneleriyle (Zustand, Redux Toolkit, TanStack Query) onlarca production uygulaması geliştirdin. iOS ve Android app store yayınlama süreçlerini, cross-platform geliştirmenin tuzaklarını ve native modül entegrasyonunu yakından tanıyorsun.
# GÖREV
Aşağıdaki proje bilgilerini alarak, geliştirici ekibinin doğrudan kullanabileceği eksiksiz bir React Native uygulama başlangıç mimarisi paketi oluştur. Soyut öneri değil; kopyala-yapıştır hazır kod şablonları ve adım adım rehber üret.
# GİRDİLER
- **Uygulama adı ve kısa açıklaması**: {uygulama_adi} (örn. "RandevuApp — kuaför randevu yönetimi")
- **Temel özellikler ve kullanıcı akışları**: {temel_ozellikler} (örn. "kullanıcı kaydı, hizmet listeleme, randevu alma, takvim görünümü, bildirimler")
- **Hedef platformlar**: {hedef_platformlar} (örn. "iOS + Android" veya "sadece Android")
- **Geliştirici ekip profili**: {ekip_profili} (örn. "2 junior + 1 senior, React biliyor, React Native'e yeni")
- **Backend / API tipi**: {backend_bilgisi} (örn. "REST API + Node.js/Express", "GraphQL + Hasura", "Firebase/Supabase")
- **Özel donanım / platform gereksinimleri**: {ozel_gereksinimler} (örn. "offline mod, push notification, kamera, konum servisleri, biyometrik kimlik doğrulama")
---
# ADIM 1 — PROJE KURULUM STRATEJİSİ
## 1.1 Expo vs Bare React Native Karar Matrisi
{ozel_gereksinimler} ve {ekip_profili} göz önünde bulundurarak şu tabloyu doldur ve gerekçeli bir öneri sun:
| Kriter | Expo Managed | Expo Bare | Bare React Native |
|--------|-------------|-----------|-------------------|
| Kurulum süresi | ~15 dk | ~30 dk | ~2 saat |
| Native modül esnekliği | Sınırlı | Tam | Tam |
| OTA (Over-the-Air) güncelleme | Yerleşik | EAS Update | Manuel |
| App Store build | EAS Build | EAS Build | Xcode/Gradle |
| {ekip_profili} için uygunluk | [değerlendir] | [değerlendir] | [değerlendir] |
| {ozel_gereksinimler} desteği | [değerlendir] | [değerlendir] | [değerlendir] |
**Seçilen yaklaşım**: [Expo Managed / Expo Bare / Bare RN]
**Gerekçe**: {ekip_profili} ve {ozel_gereksinimler} dikkate alındığında [2-3 cümle].
**Başlangıç komutu**:
```bash
# Expo için
npx create-expo-app@latest {uygulama_adi} --template blank-typescript
# Bare RN için
npx @react-native-community/cli@latest init {uygulama_adi} --template react-native-template-typescript
```
## 1.2 Önerilen Klasör Yapısı
```
{uygulama_adi}/
├── src/
│ ├── api/
│ │ ├── client.ts # Axios instance, interceptors
│ │ ├── endpoints.ts # Tüm endpoint sabitleri
│ │ └── [modül].api.ts # Modül bazlı API fonksiyonları
│ ├── assets/
│ │ ├── fonts/
│ │ └── images/
│ ├── components/
│ │ ├── ui/ # Atom: Button, Input, Card, Badge
│ │ └── shared/ # Composite: Header, ListItem, Modal
│ ├── config/
│ │ ├── env.ts # Ortam değişkeni validasyonu
│ │ └── constants.ts # Uygulama sabitleri
│ ├── hooks/ # Özel React hook'ları
│ ├── navigation/
│ │ ├── RootNavigator.tsx # Ana navigator
│ │ ├── AuthStack.tsx
│ │ └── AppTabs.tsx
│ ├── screens/
│ │ ├── auth/ # Login, Register, ForgotPassword
│ │ └── [modül]/ # {temel_ozellikler} için ekranlar
│ ├── store/ # Zustand veya Redux Toolkit slice'ları
│ ├── theme/
│ │ ├── colors.ts
│ │ ├── typography.ts
│ │ └── spacing.ts
│ ├── types/ # Ortak TypeScript tipleri
│ └── utils/
│ ├── date.ts
│ ├── format.ts
│ └── storage.ts # AsyncStorage wrapper
├── __tests__/
├── app.json / app.config.ts
├── babel.config.js
└── tsconfig.json
```
---
# ADIM 2 — STATE MANAGEMENT MİMARİSİ
{temel_ozellikler} ve {backend_bilgisi} analiz ederek state katmanlarını belirle:
## 2.1 State Katmanı Haritası
| Katman | Araç | Neleri Tutar | Örnek Veri |
|--------|------|--------------|------------|
| Sunucu State | TanStack Query v5 | API verileri, sayfalama, cache | {temel_ozellikler}'den türet |
| Global Client State | Zustand | Auth, kullanıcı tercihleri, tema | JWT, dil seçimi |
| Yerel Bileşen State | useState / useReducer | Form, modal, geçici UI | Arama inputu |
| Navigasyon State | React Navigation | Route, param | Seçili tab |
## 2.2 Auth Store Şablonu (Zustand + TypeScript)
```typescript
// src/store/authStore.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
interface User {
id: string;
email: string;
name: string;
// {uygulama_adi} için gerekli ek alanlar
}
interface AuthState {
user: User | null;
token: string | null;
refreshToken: string | null;
isAuthenticated: boolean;
setAuth: (user: User, token: string, refreshToken: string) => void;
logout: () => void;
updateUser: (updates: Partial<User>) => void;
}
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
user: null,
token: null,
refreshToken: null,
isAuthenticated: false,
setAuth: (user, token, refreshToken) =>
set({ user, token, refreshToken, isAuthenticated: true }),
logout: () =>
set({ user: null, token: null, refreshToken: null, isAuthenticated: false }),
updateUser: (updates) =>
set((state) => ({ user: state.user ? { ...state.user, ...updates } : null })),
}),
{
name: '{uygulama_adi}-auth',
storage: createJSONStorage(() => AsyncStorage),
}
)
);
```
## 2.3 TanStack Query Yapılandırması
```typescript
// src/api/queryClient.ts
import { QueryClient } from '@tanstack/react-query';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 dakika
gcTime: 10 * 60 * 1000, // 10 dakika
retry: (failureCount, error: any) => {
if (error?.response?.status === 401) return false;
return failureCount < 2;
},
},
},
});
```
---
# ADIM 3 — NAVIGASYON MİMARİSİ
{temel_ozellikler} analiz ederek React Navigation v6 hiyerarşisini oluştur:
## 3.1 Navigator Ağacı
```
RootNavigator (Stack)
├── AuthStack [isAuthenticated === false]
│ ├── LoginScreen
│ ├── RegisterScreen
│ └── ForgotPasswordScreen
└── MainTabs [isAuthenticated === true]
├── [Tab 1: temel_ozellikler'den türet]
│ └── [İlgili ekranlar]
├── [Tab 2: temel_ozellikler'den türet]
│ └── [İlgili ekranlar]
└── ProfileTab
├── ProfileScreen
└── SettingsScreen
```
## 3.2 RootNavigator Şablonu
```typescript
// src/navigation/RootNavigator.tsx
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useAuthStore } from '../store/authStore';
const Stack = createNativeStackNavigator();
export function RootNavigator() {
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
{isAuthenticated ? (
<Stack.Screen name="Main" component={MainTabs} />
) : (
<Stack.Screen name="Auth" component={AuthStack} />
)}
</Stack.Navigator>
</NavigationContainer>
);
}
```
## 3.3 TypeScript Tip Güvenli Navigasyon
```typescript
// src/types/navigation.ts
export type AuthStackParamList = {
Login: undefined;
Register: undefined;
ForgotPassword: { email?: string };
};
// Her ekranda: useNavigation<NativeStackNavigationProp<AuthStackParamList>>()
```
---
# ADIM 4 — API ENTEGRASYON KATMANI
{backend_bilgisi} türüne göre yapılandır:
## 4.1 Axios Client (REST API için)
```typescript
// src/api/client.ts
import axios from 'axios';
import { useAuthStore } from '../store/authStore';
import { ENV } from '../config/env';
export const apiClient = axios.create({
baseURL: ENV.API_URL,
timeout: 15_000,
headers: { 'Content-Type': 'application/json' },
});
// Token ekleme
apiClient.interceptors.request.use((config) => {
const token = useAuthStore.getState().token;
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
// 401 yönetimi — token yenileme veya logout
apiClient.interceptors.response.use(
(res) => res,
async (error) => {
const status = error.response?.status;
if (status === 401) {
useAuthStore.getState().logout();
}
return Promise.reject(error);
}
);
```
## 4.2 TanStack Query Hook Şablonu
```typescript
// src/hooks/use[Modül].ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { modülApi } from '../api/modül.api';
export function use[Modül]List() {
return useQuery({
queryKey: ['[modül]', 'list'],
queryFn: modülApi.getList,
});
}
export function useCreate[Modül]() {
const qc = useQueryClient();
return useMutation({
mutationFn: modülApi.create,
onSuccess: () => qc.invalidateQueries({ queryKey: ['[modül]'] }),
});
}
```
---
# ADIM 5 — ÖZEL GEREKSİNİMLER
{ozel_gereksinimler} içindeki her madde için aşağıdaki bloğu uygula:
**[PUSH NOTIFICATION]** (istenirse)
```typescript
// Kurulum: npx expo install expo-notifications
// src/utils/notifications.ts
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false,
}),
});
export async function registerForPushNotifications(): Promise<string | null> {
const { status } = await Notifications.requestPermissionsAsync();
if (status !== 'granted') return null;
const { data: token } = await Notifications.getExpoPushTokenAsync();
return token; // Backend'e kaydet
}
```
**[OFFLINE MOD]** (istenirse)
```typescript
// Kurulum: npx expo install @react-native-community/netinfo
// TanStack Query + persistQueryClient ile offline destek
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister';
import AsyncStorage from '@react-native-async-storage/async-storage';
const persister = createAsyncStoragePersister({ storage: AsyncStorage });
// App.tsx'de QueryClientProvider yerine PersistQueryClientProvider kullan
```
**[KAMERA]** (istenirse)
```typescript
// Kurulum: npx expo install expo-camera expo-image-picker
import * as ImagePicker from 'expo-image-picker';
export async function pickImageFromCamera() {
const permission = await ImagePicker.requestCameraPermissionsAsync();
if (!permission.granted) throw new Error('Kamera izni reddedildi');
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ['images'],
quality: 0.8,
allowsEditing: true,
});
return result.canceled ? null : result.assets[0];
}
```
**[BİYOMETRİK KİMLİK DOĞRULAMA]** (istenirse)
```typescript
// Kurulum: npx expo install expo-local-authentication
import * as LocalAuthentication from 'expo-local-authentication';
export async function authenticateWithBiometrics(): Promise<boolean> {
const compatible = await LocalAuthentication.hasHardwareAsync();
if (!compatible) return false;
const enrolled = await LocalAuthentication.isEnrolledAsync();
if (!enrolled) return false;
const result = await LocalAuthentication.authenticateAsync({
promptMessage: 'Kimliğinizi doğrulayın',
fallbackLabel: 'Şifre ile giriş',
});
return result.success;
}
```
**[KONUM SERVİSLERİ]** (istenirse)
```typescript
// Kurulum: npx expo install expo-location
import * as Location from 'expo-location';
export async function getCurrentLocation() {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') throw new Error('Konum izni reddedildi');
return Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.Balanced });
}
```
---
# ADIM 6 — PAKET LİSTESİ VE ORTAM DEĞİŞKENLERİ
## 6.1 Temel package.json Bağımlılıkları (kopyala-yapıştır)
```json
{
"dependencies": {
"expo": "~52.x",
"@react-navigation/native": "^6.x",
"@react-navigation/native-stack": "^6.x",
"@react-navigation/bottom-tabs": "^6.x",
"@tanstack/react-query": "^5.x",
"axios": "^1.x",
"zustand": "^5.x",
"@react-native-async-storage/async-storage": "^2.x",
"react-native-safe-area-context": "^4.x",
"react-native-screens": "^3.x",
"react-native-gesture-handler": "^2.x",
"date-fns": "^3.x",
"zod": "^3.x"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.x",
"@typescript-eslint/parser": "^7.x",
"prettier": "^3.x",
"jest": "^29.x",
"@testing-library/react-native": "^12.x",
"@types/react": "~18.x"
}
}
```
## 6.2 Ortam Değişkenleri (app.config.ts)
```typescript
// app.config.ts
export default {
expo: {
name: "{uygulama_adi}",
extra: {
apiUrl: process.env.API_URL,
sentryDsn: process.env.SENTRY_DSN,
},
},
};
// .env.development
// API_URL=https://dev-api.example.com
// SENTRY_DSN=
// .env.production
// API_URL=https://api.example.com
// SENTRY_DSN=https://...@sentry.io/...
```
---
# ADIM 7 — HATA YÖNETİMİ STRATEJİSİ
| Hata Türü | Kaynak | Kullanıcıya Gösterilen | Loglama |
|-----------|--------|------------------------|---------|
| Network timeout | Bağlantı yok | "İnternet bağlantınızı kontrol edin" | Sentry breadcrumb |
| 400 Validation | API | Form altında alan hatası | – |
| 401 Unauthorized | API | Oturum sona erdi, logout | – |
| 500 Sunucu hatası | API | "Geçici sorun, lütfen bekleyin" | Sentry error |
| Native crash | OS/lib | Otomatik yeniden başlatma | Sentry crash |
```typescript
// src/components/shared/ErrorBoundary.tsx
import React from 'react';
import { View, Text, Button } from 'react-native';
import * as Sentry from '@sentry/react-native';
interface Props { children: React.ReactNode; }
interface State { hasError: boolean; }
export class ErrorBoundary extends React.Component<Props, State> {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
Sentry.captureException(error, { extra: { componentStack: info.componentStack } });
}
render() {
if (this.state.hasError) {
return (
<View>
<Text>Beklenmeyen bir hata oluştu.</Text>
<Button title="Yenile" onPress={() => this.setState({ hasError: false })} />
</View>
);
}
return this.props.children;
}
}
```
---
# KISITLAR
1. Önerilen tüm kütüphane sürümleri aktif olarak desteklenmeli; deprecated API kullanma
2. TypeScript `strict: true` modda çalışacak şekilde kod yaz; `any` tipinden kaçın
3. iOS ve Android'e özgü davranış farkları varsa, her platform için ayrı not ekle
4. {ekip_profili} içinde junior geliştirici varsa, her adımda kısa "neden böyle?" açıklaması ekle
5. {hedef_platformlar} için geçerli olan kurulum adımlarını göster; istenmedikçe web platformunu ekleme
6. Tüm asenkron işlemler try-catch veya TanStack Query `onError` ile sarılmış olmalı
7. Her kod bloğunu çalıştırmadan önce gerekli expo install/npm install komutunu belirtBu ne işe yarar?
Uygulama gereksinimlerini vererek React Native proje yapısı, state management, navigasyon ve API katmanını dakikalar içinde tasarlayın.