zafer-skills
Expo React Native mobile app development with RevenueCat payments, AdMob ads, i18n localization, onboarding flow, paywall, and NativeTabs navigation
What this skill does
# Expo Mobile Application Development Guide
> **IMPORTANT**: This is a SKILL file, NOT a project. NEVER run npm/bun install in this folder. NEVER create code files here. When creating a new project, ALWAYS ask the user for the project path first or create it in a separate directory (e.g., `~/Projects/app-name`).
This guide is created to provide context when working with Expo projects using Claude Code.
## MANDATORY REQUIREMENTS
When creating a new Expo project, you MUST include ALL of the following:
### Required Screens (ALWAYS CREATE)
- [ ] `src/app/onboarding.tsx` - Swipe-based onboarding with fullscreen background video and gradient overlay
- [ ] `src/app/paywall.tsx` - RevenueCat paywall screen (shown after onboarding)
- [ ] `src/app/settings.tsx` - Settings screen with language, theme, notifications, and reset onboarding options
### Onboarding Video Implementation (REQUIRED)
The onboarding screen MUST have a fullscreen background video. Use a URL, not a local file:
```tsx
import { useVideoPlayer, VideoView } from "expo-video";
const VIDEO_URL =
"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
const player = useVideoPlayer(VIDEO_URL, (player) => {
player.loop = true;
player.muted = true;
player.play();
});
// In render:
<VideoView
player={player}
style={StyleSheet.absoluteFill}
contentFit="cover"
nativeControls={false}
/>;
```
Do NOT just import expo-video without actually using the VideoView component.
### Required Navigation (ALWAYS USE)
- [ ] Use `NativeTabs` from `expo-router/unstable-native-tabs` for tab navigation - NEVER use `@react-navigation/bottom-tabs` or `Tabs` from expo-router
### Required Context Providers (ALWAYS WRAP)
```tsx
import { ThemeProvider } from "@/context/theme-context";
import {
DarkTheme,
DefaultTheme,
ThemeProvider as NavigationThemeProvider,
} from "@react-navigation/native";
<ThemeProvider>
<OnboardingProvider>
<AdsProvider>
<NavigationThemeProvider
value={colorScheme === "dark" ? DarkTheme : DefaultTheme}
>
<Stack />
</NavigationThemeProvider>
</AdsProvider>
</OnboardingProvider>
</ThemeProvider>;
```
### Required Libraries (ALWAYS INSTALL)
Use `npx expo install` to install libraries (NOT npm/yarn/bun install):
```bash
npx expo install react-native-purchases react-native-google-mobile-ads expo-notifications i18next react-i18next expo-localization react-native-reanimated expo-video expo-audio expo-sqlite expo-linear-gradient
```
Libraries:
- `react-native-purchases` (RevenueCat)
- `react-native-google-mobile-ads` (AdMob)
- `expo-notifications`
- `i18next` + `react-i18next` + `expo-localization`
- `react-native-reanimated`
- `expo-video` + `expo-audio`
- `expo-sqlite` (for localStorage)
- `expo-linear-gradient` (for gradient overlays)
### AdMob Configuration (REQUIRED in app.json)
You MUST add this to `app.json` for AdMob to work:
```json
{
"expo": {
"plugins": [
[
"react-native-google-mobile-ads",
{
"androidAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy",
"iosAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"
}
]
]
}
}
```
For development/testing, use test App IDs:
- iOS: `ca-app-pub-3940256099942544~1458002511`
- Android: `ca-app-pub-3940256099942544~3347511713`
Do NOT skip this configuration or the app will crash with `GADInvalidInitializationException`.
### Banner Ad Implementation (REQUIRED)
You MUST implement banner ads in the Tab layout. Use this pattern:
```tsx
import { View, StyleSheet } from 'react-native';
import { NativeTabs } from 'expo-router/unstable-native-tabs';
import { useTranslation } from 'react-i18next';
import { BannerAd, BannerAdSize, TestIds } from 'react-native-google-mobile-ads';
import { useAds } from '@/context/ads-context';
const adUnitId = __DEV__
? TestIds.BANNER
: 'ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyyy';
export default function TabLayout() {
const { t } = useTranslation();
const { shouldShowAds } = useAds();
return (
<View style={styles.container}>
<NativeTabs>
<NativeTabs.Trigger name="index">
<NativeTabs.Trigger.Label>{t('tabs.home')}</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon sf="house.fill" md="home" />
</NativeTabs.Trigger>
<NativeTabs.Trigger name="settings">
<NativeTabs.Trigger.Label>{t('tabs.settings')}</NativeTabs.Trigger.Label>
<NativeTabs.Trigger.Icon sf="gear" md="settings" />
</NativeTabs.Trigger>
</NativeTabs>
{shouldShowAds && (
<View style={styles.adContainer}>
<BannerAd
unitId={adUnitId}
size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER}
requestOptions={{
requestNonPersonalizedAdsOnly: true,
}}
/>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
adContainer: {
alignItems: 'center',
paddingBottom: 10,
},
});
```
- ALWAYS use `TestIds.BANNER` in development
- Banner ad is placed below NativeTabs in the Tab layout
- Use `useAds` context to check `shouldShowAds` (hides for premium users)
### TURKISH LOCALIZATION (IMPORTANT)
When writing `tr.json`, you MUST use correct Turkish characters:
- ı (lowercase dotless i) - NOT i
- İ (uppercase dotted I) - NOT I
- ü, Ü, ö, Ö, ç, Ç, ş, Ş, ğ, Ğ
Example:
- ✅ "Ayarlar", "Giriş", "Çıkış", "Başla", "İleri", "Güncelle"
- ❌ "Ayarlar", "Giris", "Cikis", "Basla", "Ileri", "Guncelle"
### FORBIDDEN (NEVER USE)
- ❌ AsyncStorage - Use `expo-sqlite/localStorage/install` instead
- ❌ lineHeight style - Use padding/margin instead
- ❌ `Tabs` from expo-router - Use `NativeTabs` instead
- ❌ `@react-navigation/bottom-tabs` - Use `NativeTabs` instead
- ❌ `expo-av` - Use `expo-video` for video, `expo-audio` for audio instead
- ❌ `expo-ads-admob` - Use `react-native-google-mobile-ads` instead
- ❌ Any other ads library - ONLY use `react-native-google-mobile-ads`
- ❌ Reanimated hooks inside callbacks - Call at component top level
### Reanimated Usage (IMPORTANT)
NEVER call `useAnimatedStyle`, `useSharedValue`, or other reanimated hooks inside callbacks, loops, or conditions.
❌ WRONG:
```tsx
const renderItem = () => {
const animatedStyle = useAnimatedStyle(() => ({ opacity: 1 })); // ERROR!
return <Animated.View style={animatedStyle} />;
};
```
✅ CORRECT:
```tsx
function MyComponent() {
const animatedStyle = useAnimatedStyle(() => ({ opacity: 1 })); // Top level
return <Animated.View style={animatedStyle} />;
}
```
For lists, create a separate component for each item:
```tsx
function AnimatedItem({ item }) {
const animatedStyle = useAnimatedStyle(() => ({ opacity: 1 }));
return <Animated.View style={animatedStyle}>{item.name}</Animated.View>;
}
// In FlatList:
renderItem={({ item }) => <AnimatedItem item={item} />}
```
### POST-CREATION CLEANUP (ALWAYS DO)
After creating a new Expo project, you MUST:
1. If using `(tabs)` folder, DELETE `src/app/index.tsx` to avoid route conflicts:
```bash
rm src/app/index.tsx
```
2. Check and remove `lineHeight` from these files:
- `src/components/themed-text.tsx` (comes with lineHeight by default - REMOVE IT)
- Any other component using `lineHeight`
Search and remove all `lineHeight` occurrences:
```bash
grep -r "lineHeight" src/
```
Replace with padding or margin instead.
### AFTER COMPLETING CODE (ALWAYS RUN)
When you finish writing/modifying code, you MUST run these commands in order:
```bash
npx expo install --fix
npx expo prebuild --clean
```
1. `install --fix` fixes dependency version mismatches
2. `prebuild --clean` recreates ios and android folders
Do NOT skip these steps.
---
## Project Creation
When user asks to create an app, you MUST:
1. FIRST ask for the bundle ID (e.g., "What is the bundle ID? Example: com.company.appname")
2. Create the project in the CURRENT directory using:
```bash
buRelated in Ads & Marketing
ads
IncludedMulti-platform paid advertising audit and optimization skill. Analyzes Google, Meta, YouTube, LinkedIn, TikTok, Microsoft, and Apple Ads. 250+ checks with scoring, parallel agents, industry templates, and AI creative generation.
banana
IncludedAI image generation Creative Director powered by Google Gemini Nano Banana models. Use this skill for ANY request involving image creation, editing, visual asset production, or creative direction. Triggers on: generate an image, create a photo, edit this picture, design a logo, make a banner, visual for my anything, and all /banana commands. Handles text-to-image, image editing, multi-turn creative sessions, batch workflows, and brand presets.
rpg-migration-analyzer
IncludedAnalyzes legacy RPG (Report Program Generator) programs from AS/400 and IBM i systems for migration to modern Java applications. Extracts business logic from RPG III/IV/ILE source code, identifies data structures (D-specs), file operations (F-specs), program dependencies (CALLB/CALLP), and converts RPG constructs to Java equivalents. Generates migration reports, complexity estimates, and Java implementation strategies with POJO classes, JPA entities, and service methods. Use when modernizing AS/400 or IBM i legacy systems, analyzing RPG source files (.rpg, .rpgle, .RPGLE), converting RPG to Java, mapping data specifications to Java classes, planning legacy system migration, or when user mentions RPG analysis, Report Program Generator, RPG III/IV/ILE, AS/400 modernization, IBM i migration, packed decimal conversion, or mainframe application rewrite.
brand-library-architect
IncludedBuild a complete brand library for a product — visual asset render pipeline, brand documentation set (BRAND, COPY, MANIFESTO, BIOS, FAQ, GLOSSARY, TONE, PRICING), open-source convention files (README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT), and a self-contained press kit. This skill should be used when the user asks to "build a brand library / brand kit / press kit / brand assets" for a product, "set up a brand library workflow," "create a positioning manifesto plus visual identity," or any combination of brand documentation + visual asset pipeline. Apply phase-by-phase or run end-to-end. Templates are product-agnostic and use {{TOKEN}} placeholders the skill prompts the user to fill.
writing-tech-post
IncludedAuthors engineering blog posts end-to-end: launch deep-dives, incident postmortems, architecture migrations, performance case studies, tutorials, AI/agent system writeups, security disclosures, and research-to-product translations. Picks the correct archetype, plans the abstraction ladder, enforces an evidence cadence (diagrams, benchmarks, profiles, traces, code, ablations), tunes voice against publisher house styles (Datadog, Vercel, GitHub, AWS, Meta, Cloudflare, Jane Street), and runs a pre-publish gate for narrative momentum and disclosure ethics. Use when drafting a new engineering post, restructuring a draft that feels flat, deciding which evidence form belongs where, validating that depth and product context are balanced, or preparing a postmortem, migration, or performance narrative for external publication. Do not use for API reference documentation, README authoring, marketing copy, release notes, generic SEO content, ghost-written executive thought leadership, or non-engineering long-form essays.
blog-google
IncludedGoogle API integration for blog performance: PageSpeed Insights, CrUX Core Web Vitals with 25-week history, Search Console performance, URL Inspection, Indexing API, GA4 organic traffic, NLP entity analysis for E-E-A-T, YouTube video search for embedding, and Google Ads Keyword Planner. Progressive feature availability based on credential tier (API key, OAuth/service account, GA4, Ads). Shares config with claude-seo at ~/.config/claude-seo/google-api.json. Use when user says "google data", "page speed", "core web vitals", "search console", "indexation", "GA4", "keyword research", "nlp entities", "blog performance", "youtube search", "google api setup".