| name | mobile-native-standards |
| description | Enforces mobile native template principles including no hardcoded colors, proper safe area handling, platform-specific implementations, centralized theming, and TypeScript strict mode. Use when creating components, reviewing code, editing files, or when violations of template standards might occur. |
Mobile Native Standards Enforcer
This skill ensures all code adheres to the mobile native template's core principles. Apply these checks proactively when creating or modifying components, screens, or any UI code.
Before Making Changes
Run this validation checklist mentally or explicitly:
Standards Validation:
- [ ] No hardcoded colors (hex codes or Tailwind color classes)
- [ ] Using theme system via useTheme() hook
- [ ] Safe areas handled with useSafeAreaInsets() or layout components
- [ ] Platform-specific code uses correct patterns
- [ ] TypeScript strict mode compliant (no 'any' types)
- [ ] Animations use Reanimated 4
- [ ] Component is production-grade (if creating new component)
Core Principle Enforcement
1. Zero Hardcoded Colors
Rule: Every color must come from the theme system.
Check for violations:
- Hex codes:
#000000, #FFFFFF, #FF5733, etc.
- RGB/RGBA values:
rgb(0,0,0), rgba(255,255,255,0.5)
- Tailwind color classes:
bg-black, text-blue-500, border-red-600
- Named colors:
backgroundColor: 'red', color: 'white'
Correct pattern:
import { useTheme } from '@/hooks';
const { colors } = useTheme();
<View style={{ backgroundColor: colors.background.primary }} />
<Text style={{ color: colors.text.primary }} />
<View style={{ borderColor: colors.border.default }} />
Available theme colors (check constants/colors.ts for complete list):
colors.background.* - primary, secondary, tertiary, elevated
colors.text.* - primary, secondary, tertiary, inverse
colors.border.* - default, subtle, emphasis
colors.surface.* - primary, secondary, overlay
colors.accent.* - primary, secondary, success, warning, error, info
If you see a violation: Stop and refactor to use theme colors before proceeding.
2. Safe Area Handling
Rule: Never use deprecated SafeAreaView from react-native.
Check for violations:
import { SafeAreaView } from 'react-native';
Correct patterns:
Option A: Use the hook (preferred for animations)
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const insets = useSafeAreaInsets();
<View style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}>
{/* content */}
</View>
Option B: Use layout components
import { ScreenLayout } from '@/components/layouts';
<ScreenLayout>
{/* content - safe areas handled automatically */}
</ScreenLayout>
3. Platform-Specific Code
Rule: Use correct patterns for platform differences.
For full component differences, use file extensions:
Component.ios.tsx // iOS 26 Liquid Glass implementation
Component.android.tsx // Android 16 Material 3 implementation
Component.web.tsx // Web fallback
Component.tsx // Base/shared logic or type exports
For minor differences, use Platform module:
import { Platform } from 'react-native';
const hitSlop = Platform.select({
ios: { top: 10, bottom: 10, left: 10, right: 10 },
android: 20,
default: 10
});
if (Platform.OS === 'ios') {
} else if (Platform.OS === 'android') {
}
4. Animation Standards
Rule: All animations must use Reanimated 4.
Check for violations:
- Using
Animated from react-native (deprecated)
- Using
LayoutAnimation (unreliable)
- CSS transitions on web that don't work on native
Correct pattern:
import Animated, {
FadeIn,
FadeOut,
SlideInRight,
useAnimatedStyle,
withTiming
} from 'react-native-reanimated';
<Animated.View entering={FadeIn} exiting={FadeOut}>
{/* content */}
</Animated.View>
const animatedStyle = useAnimatedStyle(() => ({
opacity: withTiming(isVisible ? 1 : 0)
}));
5. TypeScript Strict Mode
Rule: No any types. Use proper generics and type inference.
Check for violations:
const data: any = fetchData();
function process(item: any) { }
Correct patterns:
interface User {
id: string;
name: string;
}
const data: User[] = fetchData();
function process<T>(item: T): T {
return item;
}
const data: unknown = fetchData();
if (typeof data === 'object' && data !== null) {
}
Production-Grade Component Standards
When creating a new component in components/ui/, it must meet ALL criteria:
Component Checklist
Production Component Requirements:
- [ ] Fully typed with TypeScript strict mode
- [ ] Props interface exported and documented with JSDoc
- [ ] Supports light/dark mode via useTheme()
- [ ] Has variants (size, color, state) as needed
- [ ] Works on iOS, Android, and web
- [ ] Uses Reanimated 4 for animations
- [ ] Handles accessibility (accessibilityLabel, accessibilityRole)
- [ ] No hardcoded colors or spacing
- [ ] Uses centralized spacing from constants/spacing.ts
- [ ] Exported from components/ui/index.ts
Component Template
Use this structure for new components:
import React from 'react';
import { View, Text, Pressable } from 'react-native';
import { useTheme } from '@/hooks';
import { spacing } from '@/constants';
interface YourComponentProps {
children?: React.ReactNode;
variant?: 'primary' | 'secondary' | 'tertiary';
size?: 'small' | 'medium' | 'large';
onPress?: () => void;
}
export function YourComponent({
children,
variant = 'primary',
size = 'medium',
onPress,
}: YourComponentProps) {
const { colors } = useTheme();
const backgroundColor = variant ===
? colors..
: colors..;
paddingSize = size ===
? spacing.
: size ===
? spacing.
: spacing.;
(
);
}
Common Violations and Fixes
Violation: Hardcoded Black Background
<View style={{ backgroundColor: '#000000' }} />
<View className="bg-black" />
const { colors } = useTheme();
<View style={{ backgroundColor: colors.background.primary }} />
Violation: Using SafeAreaView from React Native
import { SafeAreaView } from 'react-native';
<SafeAreaView>
<View>Content</View>
</SafeAreaView>
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const insets = useSafeAreaInsets();
<View style={{ paddingTop: insets.top }}>
<View>Content</View>
</View>
Violation: Any Type Usage
function handleData(data: any) {
console.log(data.name);
}
interface Data {
name: string;
}
function handleData(data: Data) {
console.log(data.name);
}
Violation: Magic Numbers for Spacing
<View style={{ padding: 16, margin: 8 }} />
import { spacing } from '@/constants';
<View style={{ padding: spacing.md, margin: spacing.sm }} />
Violation: Using Animated from react-native
import { Animated } from 'react-native';
const fadeAnim = new Animated.Value(0);
import Animated, { FadeIn } from 'react-native-reanimated';
<Animated.View entering={FadeIn}>
{/* content */}
</Animated.View>
Enforcement Workflow
When creating or modifying code:
- Before writing: Review relevant standards above
- While writing: Use theme system, proper imports, and types
- After writing: Run the validation checklist
- If violations found: Fix immediately before proceeding
Quick Reference
Colors: const { colors } = useTheme();
Safe Areas: const insets = useSafeAreaInsets();
Spacing: import { spacing } from '@/constants';
Platform: import { Platform } from 'react-native';
Animation: import Animated, { FadeIn } from 'react-native-reanimated';
Philosophy Reminder
This template prioritizes:
- Native first: iOS 26 Liquid Glass + Android 16 Material 3 Expressive
- No shortcuts: Three platform implementations if needed
- Design system discipline: Single source of truth for all styles
Enforce these principles in every change.