# Gluestack Ui V5:performance

> Performance optimization and cross-platform patterns for gluestack-ui v5 - covers NativeWind v5 / UniWind, TypeScript, memoization, animations, and best practices.

- **Type:** Skill
- **Install:** `agentstack add skill-gluestack-agent-skills-performance`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [gluestack](https://agentstack.voostack.com/s/gluestack)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [gluestack](https://github.com/gluestack)
- **Source:** https://github.com/gluestack/agent-skills/tree/main/.agents/skills/gluestack-ui-v5/performance

## Install

```sh
agentstack add skill-gluestack-agent-skills-performance
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Gluestack UI v5 — Performance & Cross-Platform

This sub-skill focuses on performance optimization, cross-platform compatibility, and React Native best practices for gluestack-ui v5 (NativeWind v5 / UniWind).

## Rule 12: Cross-Platform Rendering (Native & Web)

Gluestack UI v5 components are designed to work seamlessly on both React Native (iOS/Android) and Web platforms. Always use Gluestack wrapper components instead of direct React Native imports to ensure cross-platform compatibility.

### Critical Rule: Always Use Gluestack Wrappers

**NEVER import components directly from `react-native`** when a Gluestack wrapper exists. Gluestack wrappers handle platform-specific differences automatically.

### Platform-Specific Component Mapping

| React Native Import | Gluestack Wrapper | Notes |
|---------------------|-------------------|-------|
| `KeyboardAvoidingView` from `react-native` | `KeyboardAvoidingView` from `@/components/ui/keyboard-avoiding-view` | Required for web compatibility |
| `Platform` from `react-native` | Use only when absolutely necessary | Prefer Gluestack's built-in platform handling |
| `View`, `Text`, etc. | `Box`, `Text` from `@/components/ui/*` | Always use Gluestack components |

### Correct Pattern: Cross-Platform Components

```tsx
// ✅ CORRECT: Using Gluestack KeyboardAvoidingView wrapper
import { KeyboardAvoidingView } from '@/components/ui/keyboard-avoiding-view';
import { Platform } from 'react-native'; // Only when needed for platform-specific logic

  
    {/* Content */}
  

```

### Incorrect Pattern: Direct React Native Imports

```tsx
// ❌ INCORRECT: Direct import from react-native
import { KeyboardAvoidingView, Platform } from 'react-native';

  {/* This may not work correctly on web */}

```

### Web-Specific Considerations

1. **KeyboardAvoidingView**: The Gluestack wrapper handles web gracefully (web doesn't need keyboard avoidance)
2. **SafeAreaView**: Works on both native and web (web treats it as a regular View)
3. **ScrollView**: Works identically on both platforms
4. **Platform.select**: Only use when absolutely necessary; prefer Gluestack's built-in handling

### Testing Cross-Platform Compatibility

Always test components on both platforms:

1. **Native**: Run `npm run ios` or `npm run android`
2. **Web**: Run `npm run web` and verify in browser
3. **Verify**: Check that all components render correctly and interactions work on both platforms

### Platform-Specific Code (When Necessary)

If you must use platform-specific code, use it sparingly and document why:

```tsx
// Acceptable: Platform-specific behavior when Gluestack doesn't cover it
import { Platform } from 'react-native';

const keyboardBehavior = Platform.OS === 'ios' ? 'padding' : 'height';

  {/* Content */}

```

### Common Cross-Platform Issues to Avoid

1. **Direct React Native imports** - Always use Gluestack wrappers
2. **Platform-specific styling without fallbacks** - Ensure web has equivalent styles
3. **Native-only APIs** - Check if web alternatives exist
4. **Missing web polyfills** - Gluestack handles most of these automatically

### Verification Checklist for Cross-Platform

- [ ] All components imported from `@/components/ui/*` wrappers
- [ ] No direct imports from `react-native` for wrapped components
- [ ] KeyboardAvoidingView uses Gluestack wrapper
- [ ] Tested on both native (iOS/Android) and web platforms
- [ ] All interactions work on both platforms
- [ ] Styling renders correctly on both platforms
- [ ] No platform-specific code without documentation

## Rule 13: Performance & Best Practices

Follow these best practices to ensure optimal performance, type safety, and maintainability in React Native/Expo applications.

### Use TypeScript

Define navigation and prop types for type safety. This catches errors at compile time and improves developer experience.

#### Correct Pattern

```tsx
// ✅ CORRECT: Typed component props
interface LoginFormProps {
  readonly onSubmit: (email: string, password: string) => void;
  readonly isLoading?: boolean;
}

const LoginForm = ({ onSubmit, isLoading = false }: LoginFormProps) => {
  // Component implementation
};

// ✅ CORRECT: Typed navigation
import { useRouter } from 'expo-router';

const router = useRouter();
router.push('/login' as any); // Type-safe navigation
```

#### Incorrect Pattern

```tsx
// ❌ INCORRECT: No type definitions
const LoginForm = ({ onSubmit, isLoading }) => {
  // No type safety
};
```

### Memoize Components

Use `React.memo` and `useCallback` to prevent unnecessary rerenders, especially for expensive components or frequently re-rendered parent components.

#### Correct Pattern

```tsx
// ✅ CORRECT: Memoized component
import React, { useCallback, useState } from 'react';

const ExpensiveComponent = React.memo(({ data, onUpdate }: Props) => {
  // Expensive rendering logic
});

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  // Memoized callback prevents child rerenders
  const handleUpdate = useCallback((value: string) => {
    // Update logic
  }, []);

  return (
    <>
       setCount(count + 1)}>
        Count: {count}
      
      
    
  );
};
```

#### When to Memoize

- Components that receive stable props but parent rerenders frequently
- Callbacks passed to child components
- Expensive computations (use `useMemo`)

### Run Animations on UI Thread

Use Reanimated worklets for 60fps animations. This keeps animations smooth by running on the native UI thread instead of the JavaScript thread.

#### Correct Pattern

```tsx
// ✅ CORRECT: Using Reanimated worklets
import { useSharedValue, withTiming } from 'react-native-reanimated';
import Animated from 'react-native-reanimated';

const AnimatedBox = Animated.createAnimatedComponent(Box);

const Component = () => {
  const translateX = useSharedValue(0);

  const handlePress = () => {
    // Animation runs on UI thread
    translateX.value = withTiming(100, { duration: 300 });
  };

  return (
    
      
        Animate
      
    
  );
};
```

#### Incorrect Pattern

```tsx
// ❌ INCORRECT: Using Animated API (runs on JS thread)
import { Animated } from 'react-native';

const Component = () => {
  const translateX = new Animated.Value(0);
  // This runs on JavaScript thread, can cause jank
};
```

### Handle Safe Areas

Use `SafeAreaView` or `useSafeAreaInsets` to handle device notches, status bars, and home indicators properly.

#### Correct Pattern

```tsx
// ✅ CORRECT: Using SafeAreaView
import { SafeAreaView } from '@/components/ui/safe-area-view';

const Screen = () => (
  
    
      {/* Content */}
    
  
);

// ✅ CORRECT: Using useSafeAreaInsets for custom layouts
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const CustomLayout = () => {
  const insets = useSafeAreaInsets();

  return (
    
      {/* Content */}
    
  );
};
```

### Test on Real Devices

Simulator/emulator performance differs from real devices. Always test on physical devices before releasing.

#### Testing Checklist

- [ ] Test on real iOS device (iPhone/iPad)
- [ ] Test on real Android device
- [ ] Test on different screen sizes
- [ ] Test with different OS versions
- [ ] Test performance under load
- [ ] Test with slow network conditions

### Use FlatList for Lists

Never use `ScrollView` with `map` for long lists. `FlatList` provides virtualization, which only renders visible items.

#### Correct Pattern

```tsx
// ✅ CORRECT: Using FlatList
import { FlatList } from '@/components/ui/flat-list';

const ItemList = ({ items }: { items: Item[] }) => (
   (
      
        {item.name}
      
    )}
    keyExtractor={(item) => item.id}
    ListEmptyComponent={No items found}
  />
);
```

#### Incorrect Pattern

```tsx
// ❌ INCORRECT: Using ScrollView with map (no virtualization)
import { ScrollView } from '@/components/ui/scroll-view';

const ItemList = ({ items }: { items: Item[] }) => (
  
    {items.map((item) => (
      
        {item.name}
      
    ))}
  
);
```

**Why this is bad**: All items are rendered at once, causing performance issues with long lists.

### Platform-Specific Code

Use `Platform.select` for iOS/Android differences. This provides a clean, declarative way to handle platform-specific code.

#### Correct Pattern

```tsx
// ✅ CORRECT: Using Platform.select
import { Platform } from 'react-native';

const styles = Platform.select({
  ios: {
    paddingTop: 20,
  },
  android: {
    paddingTop: 0,
  },
  default: {
    paddingTop: 0,
  },
});

  {/* Content */}

// ✅ CORRECT: Platform.select for values
const keyboardBehavior = Platform.select({
  ios: 'padding',
  android: 'height',
  default: 'padding',
});
```

#### Incorrect Pattern

```tsx
// ❌ INCORRECT: Using if/else for platform checks
import { Platform } from 'react-native';

let styles;
if (Platform.OS === 'ios') {
  styles = { paddingTop: 20 };
} else {
  styles = { paddingTop: 0 };
}
```

## Best Practices Summary

| Practice | Why It Matters | When to Use |
|----------|---------------|-------------|
| **TypeScript** | Type safety, catch errors early | Always |
| **React.memo** | Prevent unnecessary rerenders | Components with stable props |
| **useCallback** | Stable function references | Callbacks passed to children |
| **Reanimated worklets** | 60fps animations | All animations |
| **SafeAreaView** | Handle device notches/bars | All screens |
| **FlatList** | Virtualization for performance | Lists with 10+ items |
| **Platform.select** | Clean platform-specific code | iOS/Android differences |
| **Real device testing** | Accurate performance metrics | Before release |

## Performance Optimization Patterns

### Memoized List Item

```tsx
// ✅ CORRECT: Memoized list item component
interface ItemProps {
  readonly item: Item;
  readonly onPress: (id: string) => void;
}

const ListItem = React.memo(({ item, onPress }: ItemProps) => {
  const handlePress = useCallback(() => {
    onPress(item.id);
  }, [item.id, onPress]);

  return (
    
      
        {item.name}
      
    
  );
});

// Parent component
const ItemList = ({ items }: { items: Item[] }) => {
  const handlePress = useCallback((id: string) => {
    // Handle press
  }, []);

  return (
     (
        
      )}
      keyExtractor={(item) => item.id}
    />
  );
};
```

### Animated Component

```tsx
// ✅ CORRECT: Using Reanimated for smooth animations
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

const AnimatedBox = Animated.createAnimatedComponent(Box);

const AnimatedCard = () => {
  const scale = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: scale.value }],
  }));

  const handlePress = () => {
    scale.value = withSpring(1.1);
  };

  return (
    
      
        Press to animate
      
    
  );
};
```

### Safe Area Handling

```tsx
// ✅ CORRECT: Proper safe area handling
import { SafeAreaView } from '@/components/ui/safe-area-view';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const Screen = () => {
  const insets = useSafeAreaInsets();

  return (
    
      
        {/* Header */}
        
          Title
        

        {/* Content */}
        
          {/* Content */}
        

        {/* Footer with safe bottom padding */}
        
          
            Submit
          
        
      
    
  );
};
```

## Performance Checklist

- [ ] TypeScript types defined for all components and props
- [ ] Expensive components wrapped with `React.memo`
- [ ] Callbacks memoized with `useCallback`
- [ ] Animations use Reanimated worklets
- [ ] Safe areas handled with `SafeAreaView` or `useSafeAreaInsets`
- [ ] Long lists use `FlatList` instead of `ScrollView` + `map`
- [ ] Platform-specific code uses `Platform.select`
- [ ] Tested on real devices (not just simulators)
- [ ] Performance profiled and optimized
- [ ] Cross-platform compatibility verified (native + web)

## Common Performance Pitfalls

### ❌ Don't: Use ScrollView for Long Lists

```tsx
// ❌ INCORRECT: No virtualization

  {items.map(item => )}

// ✅ CORRECT: Use FlatList
 }
  keyExtractor={(item) => item.id}
/>
```

### ❌ Don't: Create Callbacks Without useCallback

```tsx
// ❌ INCORRECT: New function on every render
 handlePress(id)}>
  Press

// ✅ CORRECT: Memoized callback
const memoizedPress = useCallback(() => {
  handlePress(id);
}, [id, handlePress]);

  Press

```

### ❌ Don't: Use Animated API for Complex Animations

```tsx
// ❌ INCORRECT: Runs on JavaScript thread
import { Animated } from 'react-native';
const animValue = new Animated.Value(0);

// ✅ CORRECT: Use Reanimated (runs on UI thread)
import { useSharedValue } from 'react-native-reanimated';
const animValue = useSharedValue(0);
```

## v5-Specific Performance Notes

### NativeWind v5

- **Pin `lightningcss` to exactly `1.30.1`** in `package.json` `overrides` and `resolutions`. Mismatched versions cause CSS transformation errors and build failures.
- Tailwind v4 uses **CSS-first configuration** via `global.css` — there is no `tailwind.config.js` overhead.
- `@tailwindcss/postcss` handles CSS processing; keep the `postcss.config.js` file minimal.

### UniWind

- **No PostCSS / lightningcss** — UniWind processes CSS at Metro/Babel time, eliminating the PostCSS build step entirely. This can reduce build times for Expo projects.
- Uses `:where()` selectors for theme scoping, which have zero CSS specificity — no specificity wars between themes.
- Consider UniWind for simpler Expo-only projects where build-step reduction matters.

## Reference

- **Reanimated Documentation**: https://docs.swmansion.com/react-native-reanimated/
- **React Native Performance**: https://reactnative.dev/docs/performance
- **Expo Router**: https://docs.expo.dev/router/introduction/
- **NativeWind v5**: https://www.nativewind.dev/

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [gluestack](https://github.com/gluestack)
- **Source:** [gluestack/agent-skills](https://github.com/gluestack/agent-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-gluestack-agent-skills-performance
- Seller: https://agentstack.voostack.com/s/gluestack
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
