plugins/smedjen/skills/expo-native-ui/SKILL.md
Native UI patterns in Expo — platform-specific components, gestures, animations, and design system integration.
npx skillsauth add hjemmesidekongen/ai expo-native-uiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Native UI in Expo is React Native with a curated layer on top. No DOM, no CSS — layout is Yoga flexbox and platform behavior diverges in ways that matter.
Platform.select for inline divergence. .ios.tsx / .android.tsx file extensions when implementations differ substantially — don't bury large platform branches in a single file.
Always use SafeAreaView from react-native-safe-area-context (not core RN). For programmatic insets use useSafeAreaInsets. Never hardcode top/bottom padding to compensate for notches.
expo-router uses file-based routing on top of React Navigation. Screens live in app/. Layouts in _layout.tsx. Use useRouter and useLocalSearchParams — avoid direct React Navigation APIs unless expo-router doesn't expose what you need.
react-native-gesture-handler for all touch interactions beyond TouchableOpacity. Wrap the app root in GestureHandlerRootView. Compose conflicting gestures with Gesture.Simultaneous / Gesture.Exclusive.
Reanimated for smooth 60fps animations on the UI thread — useSharedValue, useAnimatedStyle, withSpring / withTiming. Avoid JS-driven animations for anything continuous. LayoutAnimation works for simple one-off transitions; Reanimated's Layout prop is better.
StyleSheet.create is not optional — it registers styles natively and avoids object allocation on re-renders. Use useWindowDimensions (not Dimensions.get) for responsive sizing — it's reactive to orientation changes.
Keep a tokens.ts exporting spacing, color, typography, radius. No CSS variables in RN — import directly. Use expo-vector-icons for icons and expo-image over core Image — better caching, blurhash placeholder support.
FlashList (@shopify/flash-list) over FlatList for any unbounded or large list. Set estimatedItemSize accurately — wrong estimates degrade performance. For modals, use @gorhom/bottom-sheet over Modal for bottom sheets — integrates with gesture handler and Reanimated. Modal is fine for simple confirmations. Always wrap form modals in KeyboardAvoidingView.
See references/process.md for platform split patterns, navigation setup, gesture composition, animation recipes, list configuration, and anti-patterns.
development
Creates a brand from scratch through market research and interactive sparring. Runs competitive research via Perplexity, then guides the user through positioning, audience, voice, values, and content pillars. Produces the full brand guideline set at .ai/brand/{name}/. Use when building a new brand, defining brand strategy for a product, or when /våbenskjold:create is invoked.
testing
Loads brand guidelines from .ai/brand/{name}/ and makes them available to the current context. Progressive disclosure: L1 confirms brand exists, L2 loads summary, L3 loads specific files on demand. Use when a downstream skill or user needs brand context, or when /våbenskjold:apply is invoked.
documentation
Guided reinvention of an existing brand guideline. Loads current brand from .ai/brand/{name}/, identifies what to keep vs change, and walks the user through targeted evolution. Preserves brand equity while updating positioning, voice, or values. Use when refreshing a brand or when /våbenskjold:evolve is invoked.
development
Codifies an existing brand from materials, samples, and references. Analyzes provided content to extract voice patterns, values, and positioning. Produces the same guideline format as brand-strategy. Use when a brand already exists but isn't documented, or when /våbenskjold:audit is invoked.