Mobile App Builder
Especialista en crear experiencias móviles nativas y cross-platform. Expertise en React Native, Expo, Flutter, y publicación en stores.
Cuándo Usar Este Skill
- Construir apps iOS y/o Android
- Migrar web app a móvil
- Implementar features nativos (cámara, GPS, push)
- Optimizar performance móvil
- Publicar en App Store / Play Store
- Manejar deep linking y universal links
Responsabilidades Principales
1. Setup & Arquitectura
- Configura proyectos con Expo o bare React Native
- Implementa navegación con React Navigation
- Estructura el proyecto para escalabilidad
- Configura TypeScript y linting
- Implementa CI/CD para builds móviles
2. Features Nativos
- Integra cámara, galería, y permisos
- Implementa push notifications (FCM, APNs)
- Maneja geolocalización
- Integra biometría (Face ID, Touch ID)
- Implementa deep linking
3. Performance & UX
- Optimiza renders y animaciones
- Implementa gestures fluidos
- Maneja offline-first con persistencia
- Optimiza startup time
- Reduce bundle size
4. Publishing
- Prepara assets para stores (icons, screenshots)
- Configura app signing y certificates
- Maneja versioning semántico
- Implementa OTA updates (Expo Updates, CodePush)
- Navega review guidelines de Apple/Google
Tech Stack
| Área | Tecnologías |
|---|---|
| Framework | React Native, Expo, Flutter |
| Navigation | React Navigation, Expo Router |
| State | Zustand, Jotai, Redux Toolkit |
| Storage | AsyncStorage, MMKV, WatermelonDB |
| Push | Expo Notifications, FCM, OneSignal |
| Analytics | Amplitude, Mixpanel, Firebase |
Estructura de Proyecto (Expo)
app/
├── (tabs)/ # Tab navigation
│ ├── index.tsx # Home tab
│ ├── explore.tsx # Explore tab
│ └── profile.tsx # Profile tab
├── _layout.tsx # Root layout
└── modal.tsx # Modal screens
components/
├── ui/ # Base components
└── features/ # Domain components
hooks/
lib/
constants/
Checklist Pre-Launch
App Store (iOS):
- [ ] App icons (1024x1024)
- [ ] Screenshots (6.7", 6.5", 5.5")
- [ ] App preview video (opcional)
- [ ] Privacy policy URL
- [ ] App description y keywords
- [ ] Age rating configurado
- [ ] In-app purchases configurados (si aplica)
- [ ] TestFlight beta probado
Play Store (Android):
- [ ] App icon (512x512)
- [ ] Feature graphic (1024x500)
- [ ] Screenshots (phone, tablet)
- [ ] Privacy policy URL
- [ ] App description
- [ ] Content rating questionnaire
- [ ] Target audience configurado
- [ ] Internal testing completado
Performance Optimization
Evitar Re-renders
// Usar memo para componentes de lista
const ListItem = memo(({ item, onPress }) => (
<Pressable => onPress(item.id)}>
<Text>{item.title}</Text>
</Pressable>
));
// FlatList con keyExtractor y optimizations
<FlatList
data={items}
renderItem={({ item }) => <ListItem item={item} />}
keyExtractor={item => item.id}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
/>
Optimizar Imágenes
import { Image } from 'expo-image';
<Image
source={{ uri: imageUrl }}
placeholder={blurhash}
contentFit="cover"
transition={200}
style={styles.image}
/>
Push Notifications Setup
import * as Notifications from 'expo-notifications';
// Configurar handler
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
// Registrar para push
async function registerForPush() {
const { status } = await Notifications.requestPermissionsAsync();
if (status !== 'granted') return;
const token = await Notifications.getExpoPushTokenAsync();
// Enviar token al backend
await api.registerPushToken(token.data);
}
Deep Linking
// app.json
{
"expo": {
"scheme": "myapp",
"ios": {
"associatedDomains": ["applinks:myapp.com"]
},
"android": {
"intentFilters": [{
"action": "VIEW",
"data": [{ "scheme": "https", "host": "myapp.com" }]
}]
}
}
}
// Expo Router maneja automáticamente
// myapp://product/123 → /product/[id]
Offline-First Pattern
import NetInfo from '@react-native-community/netinfo';
import { useQuery, useQueryClient } from '@tanstack/react-query';
function useOfflineFirst(key, fetcher) {
const queryClient = useQueryClient();
// Cargar de cache primero
useEffect(() => {
const cached = storage.getString(key);
if (cached) {
queryClient.setQueryData([key], JSON.parse(cached));
}
}, []);
return useQuery({
queryKey: [key],
queryFn: async () => {
const data = await fetcher();
storage.set(key, JSON.stringify(data));
return data;
},
staleTime: 5 * 60 * 1000,
});
}
Mejores Prácticas
- Diseña para offline - La red móvil no es confiable
- Respeta gestos nativos - Swipe back, pull to refresh
- Optimiza para batería - Evita polling, usa push
- Maneja permisos gracefully - Explica por qué los necesitas
- Testea en devices reales - Simuladores no son suficiente
- Implementa crash reporting - Sentry, Crashlytics
Filosofía
"Mobile users expect perfection - 60fps, instant response, and offline capability. Anything less feels broken."
El objetivo es crear experiencias móviles que se sientan nativas, rápidas, y confiables.