> react-native-expo
You are an expert in React Native with Expo, the modern framework for building native iOS and Android apps with React. You help developers create mobile applications using Expo Router (file-based navigation), Expo SDK modules (camera, notifications, auth, maps), EAS Build/Submit for cloud builds, over-the-air updates, and the full Expo development workflow — from `npx create-expo-app` to App Store submission.
curl "https://skillshub.wtf/TerminalSkills/skills/react-native-expo?format=md"React Native with Expo — Modern Mobile Development
You are an expert in React Native with Expo, the modern framework for building native iOS and Android apps with React. You help developers create mobile applications using Expo Router (file-based navigation), Expo SDK modules (camera, notifications, auth, maps), EAS Build/Submit for cloud builds, over-the-air updates, and the full Expo development workflow — from npx create-expo-app to App Store submission.
Core Capabilities
File-Based Navigation (Expo Router)
// app/_layout.tsx — Root layout with tab navigation
import { Tabs } from "expo-router";
import { Ionicons } from "@expo/vector-icons";
export default function Layout() {
return (
<Tabs screenOptions={{ tabBarActiveTintColor: "#007AFF" }}>
<Tabs.Screen name="index" options={{
title: "Home",
tabBarIcon: ({ color, size }) => <Ionicons name="home" color={color} size={size} />,
}} />
<Tabs.Screen name="explore" options={{
title: "Explore",
tabBarIcon: ({ color, size }) => <Ionicons name="compass" color={color} size={size} />,
}} />
<Tabs.Screen name="profile" options={{
title: "Profile",
tabBarIcon: ({ color, size }) => <Ionicons name="person" color={color} size={size} />,
}} />
</Tabs>
);
}
// app/index.tsx — Home screen
import { View, Text, FlatList, Pressable } from "react-native";
import { Link } from "expo-router";
export default function Home() {
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 24, fontWeight: "bold" }}>Welcome</Text>
<Link href="/explore" asChild>
<Pressable style={{ padding: 12, backgroundColor: "#007AFF", borderRadius: 8, marginTop: 16 }}>
<Text style={{ color: "white", textAlign: "center" }}>Explore</Text>
</Pressable>
</Link>
</View>
);
}
// app/post/[id].tsx — Dynamic route
import { useLocalSearchParams } from "expo-router";
export default function Post() {
const { id } = useLocalSearchParams<{ id: string }>();
return <Text>Post #{id}</Text>;
}
Expo SDK Modules
// Camera
import { CameraView, useCameraPermissions } from "expo-camera";
function CameraScreen() {
const [permission, requestPermission] = useCameraPermissions();
const cameraRef = useRef<CameraView>(null);
if (!permission?.granted) {
return <Button title="Grant Camera Access" onPress={requestPermission} />;
}
const takePicture = async () => {
const photo = await cameraRef.current?.takePictureAsync();
console.log(photo?.uri);
};
return <CameraView ref={cameraRef} style={{ flex: 1 }} facing="back" />;
}
// Push Notifications
import * as Notifications from "expo-notifications";
async function registerForPush() {
const { status } = await Notifications.requestPermissionsAsync();
if (status !== "granted") return;
const token = await Notifications.getExpoPushTokenAsync({ projectId: "your-project-id" });
return token.data; // Send to your backend
}
// Local notifications
await Notifications.scheduleNotificationAsync({
content: { title: "Reminder", body: "Don't forget your task!" },
trigger: { seconds: 3600 }, // 1 hour from now
});
// Secure Storage
import * as SecureStore from "expo-secure-store";
await SecureStore.setItemAsync("token", "jwt-abc123");
const token = await SecureStore.getItemAsync("token");
EAS Build and Submit
# Install EAS CLI
npm install -g eas-cli
# Configure build
eas build:configure
# Build for iOS and Android
eas build --platform ios # Cloud build → .ipa
eas build --platform android # Cloud build → .aab
# Submit to stores
eas submit --platform ios # App Store Connect
eas submit --platform android # Google Play Console
# Over-the-air updates (no store review needed)
eas update --branch production --message "Bug fix for login screen"
Installation
npx create-expo-app@latest my-app
cd my-app
npx expo start # Dev server with QR code
# Scan QR with Expo Go app (iOS/Android) for instant preview
Best Practices
- Expo Router — File-based navigation;
app/directory maps to screens,[param]for dynamic routes - Expo Go for dev — Scan QR code to preview on real device; no Xcode/Android Studio needed for development
- EAS Build — Cloud builds for iOS without a Mac; handles signing, provisioning, and certificates
- OTA updates — Push JS updates instantly via
eas update; skip App Store review for non-native changes - Expo SDK modules — Camera, notifications, maps, auth, haptics; native APIs with JS interface
- Secure storage — Use
expo-secure-storefor tokens/secrets; encrypted Keychain (iOS) / Keystore (Android) - Config plugins — Customize native code without ejecting;
app.config.tsfor dynamic configuration - Prebuild — Run
npx expo prebuildto generate native projects when you need custom native modules
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.