
React Native
Apply React Native folder layout, typed functional components, and screen-hook patterns while editing mobile app code.
Overview
React Native is an agent skill for the Build phase that enforces React Native project structure, typed functional components, and screen-level hook patterns when editing mobile app code.
Install
npx skills add https://github.com/alinaqi/claude-bootstrap --skill react-nativeWhat is this skill?
- Opinionated src layout: core business logic, components, screens, navigation, hooks, and store
- Barrel exports and per-screen folders with dedicated hooks (e.g. useHome.ts)
- Functional components only with explicit TypeScript props interfaces
- Path triggers for **/*.tsx, **/*.jsx, ios/**, android/**, and app.json
- Separates pure core/services from React UI layers for testability
Adoption & trust: 455 installs on skills.sh; 691 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
Your React Native repo mixes screens, logic, and navigation ad hoc, so every agent session reinvents folder layout and component style.
Who is it for?
Solo builders actively editing an existing React Native codebase who want agents to mirror one structural convention across ios/, android/, and TSX screens.
Skip if: Greenfield mobile projects that still need stack choice (Expo vs bare), CI, or store listing work—use validate/ship skills first; skip if you already enforce a different architecture in CLAUDE.md.
When should I use this skill?
When working on React Native mobile app code (paths: **/*.tsx, **/*.jsx, ios/**, android/**, app.json).
What do I get? / Deliverables
After the skill runs, new and touched files follow a consistent src/core–components–screens layout with typed functional components and screen hooks aligned to your paths.
- Consistent src/core, components, screens, and navigation layout in touched files
- Typed functional components and screen-level hooks
Recommended Skills
Journey fit
The skill auto-triggers on TSX/JSX and native project paths during hands-on product implementation, which maps cleanly to the Build phase shelf. Most guidance targets screens, reusable UI, navigation, and hooks—core frontend mobile work rather than backend or shipping gates.
How it compares
Use as procedural layout guardrails during coding, not as a UI kit or navigation library replacement.
Common Questions / FAQ
Who is react-native for?
Indie and solo developers shipping React Native apps who want their coding agent to follow one folder and component convention across TypeScript UI and native project files.
When should I use react-native?
Use it during Build when you change screens, shared components, navigation, or platform configs—the skill matches when-to-use: working on React Native mobile app code under tsx, jsx, ios, android, or app.json paths.
Is react-native safe to install?
Treat it as local procedural guidance in your agent context; review the Security Audits panel on this Prism page before trusting any third-party skill package in your repo.
SKILL.md
READMESKILL.md - React Native
# React Native Skill --- ## Project Structure ``` project/ ├── src/ │ ├── core/ # Pure business logic (no React) │ │ ├── types.ts │ │ └── services/ │ ├── components/ # Reusable UI components │ │ ├── Button/ │ │ │ ├── Button.tsx │ │ │ ├── Button.test.tsx │ │ │ └── index.ts │ │ └── index.ts # Barrel export │ ├── screens/ # Screen components │ │ ├── Home/ │ │ │ ├── HomeScreen.tsx │ │ │ ├── useHome.ts # Screen-specific hook │ │ │ └── index.ts │ │ └── index.ts │ ├── navigation/ # Navigation configuration │ ├── hooks/ # Shared custom hooks │ ├── store/ # State management │ └── utils/ # Utilities ├── __tests__/ ├── android/ ├── ios/ └── CLAUDE.md ``` --- ## Component Patterns ### Functional Components Only ```typescript // Good - simple, testable interface ButtonProps { label: string; onPress: () => void; disabled?: boolean; } export function Button({ label, onPress, disabled = false }: ButtonProps): JSX.Element { return ( <Pressable onPress={onPress} disabled={disabled}> <Text>{label}</Text> </Pressable> ); } ``` ### Extract Logic to Hooks ```typescript // useHome.ts - all logic here export function useHome() { const [items, setItems] = useState<Item[]>([]); const [loading, setLoading] = useState(false); const refresh = useCallback(async () => { setLoading(true); const data = await fetchItems(); setItems(data); setLoading(false); }, []); return { items, loading, refresh }; } // HomeScreen.tsx - pure presentation export function HomeScreen(): JSX.Element { const { items, loading, refresh } = useHome(); return ( <ItemList items={items} loading={loading} onRefresh={refresh} /> ); } ``` ### Props Interface Always Explicit ```typescript // Always define props interface, even if simple interface ItemCardProps { item: Item; onPress: (id: string) => void; } export function ItemCard({ item, onPress }: ItemCardProps): JSX.Element { ... } ``` --- ## State Management ### Local State First ```typescript // Start with useState, escalate only when needed const [value, setValue] = useState(''); ``` ### Zustand for Global State (if needed) ```typescript // store/useAppStore.ts import { create } from 'zustand'; interface AppState { user: User | null; setUser: (user: User | null) => void; } export const useAppStore = create<AppState>((set) => ({ user: null, setUser: (user) => set({ user }), })); ``` ### React Query for Server State ```typescript // hooks/useItems.ts import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; export function useItems() { return useQuery({ queryKey: ['items'], queryFn: fetchItems, }); } export function useCreateItem() { const queryClient = useQueryClient(); return useMutation({ mutationFn: createItem, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['items'] }); }, }); } ``` --- ## Testing ### Component Testing with React Native Testing Library ```typescript import { render, fireEvent } from '@testing-library/react-native'; import { Button } from './Button'; describe('Button', () => { it('calls onPress when pressed', () => { const onPress = jest.fn(); const { getByText } = render(<Button label="Click me" onPress={onPress} />); fireEvent.press(getByText('Click me')); expect(onPress).toHaveBeenCalledTimes(1); }); it('does not call onPress when disabled', () => { const onPress = jest.fn(); const { getByText } = render(<Button label="Click me" onPress={onPress} disa