Install
$ agentstack add skill-gluestack-agent-skills-validation ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Gluestack UI v5 — Validation & Anti-Patterns
This sub-skill focuses on validating implementations, identifying anti-patterns, and ensuring code quality for gluestack-ui v5 (Tailwind CSS v4, NativeWind v5 / UniWind).
Validation Checklist
When reviewing code, check for:
Component Usage
- [ ] Component usage verified against official v5 docs at
https://gluestack.io/ui/docs/components/${componentName}/ - [ ] All React Native primitives replaced with Gluestack components
- [ ] Components imported from local
@/components/ui/directory - [ ] GluestackUIProvider wraps the app
Component Props vs className
- [ ] Component props used instead of className when available:
- [ ] VStack/HStack use
spaceprop instead ofgap-*className - [ ] Button uses
variantandsizeprops instead of className - [ ] Heading/Text use
sizeprop instead oftext-*className - [ ] Heading/Text use
boldprop instead offont-boldclassName - [ ] Other component props used where applicable
Styling
- [ ] CRITICAL: All colors use ONLY semantic tokens - NO exceptions:
- [ ] No
typography-*tokens (usetext-foreground,text-muted-foreground) - [ ] No
neutral-*tokens (use semantic equivalents) - [ ] No
gray-*orslate-*tokens (use semantic equivalents) - [ ] No numbered colors:
red-500,blue-600,green-400 - [ ] No arbitrary values:
[#3b82f6],[#DC2626] - [ ] No opacity utilities (use alpha values:
/70,/90) - [ ] All spacing values use the standard scale (no arbitrary values)
- [ ] No inline styles where className can be used
- [ ] Dark mode support using
dark:prefix (semantic tokens ensure compatibility) - [ ] Variants defined using
tvawhen needed - [ ] className properly merged in custom components
Compound Components
- [ ] Compound components used correctly:
- [ ] InputIcon always wrapped in InputSlot (CRITICAL)
- [ ] ButtonText used for all button text content
- [ ] FormControl sub-components used (FormControlLabel, FormControlError, etc.)
- [ ] Card sub-components used (CardHeader, CardBody, CardFooter)
- [ ] Checkbox sub-components used (CheckboxIndicator, CheckboxIcon, CheckboxLabel)
- [ ] All other component sub-components as per official docs
Icons
- [ ] Icons follow priority: pre-built icons → Lucide Icons → createIcon for custom icons
- [ ] Icons imported from
@/components/ui/icon
Cross-Platform Compatibility
- [ ] Cross-platform compatibility verified:
- [ ] All components use Gluestack wrappers (no direct react-native imports)
- [ ] KeyboardAvoidingView uses Gluestack wrapper
- [ ] Tested on both native and web platforms
- [ ] All interactions work on both platforms
Performance & Best Practices
- [ ] Performance & best practices:
- [ ] TypeScript types defined for components and props
- [ ] Expensive components memoized with React.memo
- [ ] Callbacks memoized with useCallback when needed
- [ ] Animations use Reanimated worklets (not Animated API)
- [ ] Safe areas handled with SafeAreaView or useSafeAreaInsets
- [ ] Long lists use FlatList (not ScrollView + map)
- [ ] Platform-specific code uses Platform.select
- [ ] Tested on real devices (not just simulators)
Anti-Patterns to Avoid
❌ Don't: Mix React Native and Gluestack Components
// ❌ INCORRECT: Mixing React Native and Gluestack components
import { View, Text } from "react-native";
import { Button } from "@/components/ui/button";
Mixed usage
Click
Why it's bad: Loses theming, accessibility, and cross-platform consistency.
Correct approach:
// ✅ CORRECT: Use Gluestack components consistently
import { Box } from "@/components/ui/box";
import { Text } from "@/components/ui/text";
import { Button, ButtonText } from "@/components/ui/button";
Consistent usage
Click
❌ Don't: Use Non-Semantic Color Tokens
STRICTLY PROHIBITED - You MUST use ONLY semantic tokens for ALL colors.
// ❌ PROHIBITED: Generic typography tokens
Heading
Body
Muted
// ❌ PROHIBITED: Neutral color tokens
Card
Text
Border
// ❌ PROHIBITED: Gray/Slate color scales
Background
Content
Border
// ❌ PROHIBITED: Numbered color tokens
Primary
Error
Success
// ❌ PROHIBITED: Arbitrary color values
Arbitrary
Error
// ❌ PROHIBITED: Inline color styles
White
Error
// ❌ PROHIBITED: Opacity utilities
Muted
Transparent
Why it's bad:
- ❌ Breaks theming and dark mode
- ❌ Creates maintenance debt
- ❌ Violates design system
- ❌ Inconsistent colors across app
Correct approach:
// ✅ CORRECT: Use ONLY semantic tokens
Heading
Body
Muted
Card
Text
Border
Background
Content
Border
Primary
Error
Success
// ✅ CORRECT: Alpha values instead of opacity
Muted
Transparent
❌ Don't: Skip Sub-Components
// ❌ INCORRECT: ButtonText is required
Click Me
// ❌ INCORRECT: InputIcon not wrapped in InputSlot
// ❌ INCORRECT: Missing FormControl sub-components
Email
Why it's bad: Components won't render correctly, breaks styling and accessibility.
Correct approach:
// ✅ CORRECT: Proper sub-component usage
Click Me
// ✅ CORRECT: InputIcon wrapped in InputSlot
// ✅ CORRECT: FormControl with proper sub-components
Email
❌ Don't: Use Inline Styles When className Works
// ❌ INCORRECT: Inline styles for static values
Why it's bad: Bypasses optimization, breaks theming, harder to maintain.
Correct approach:
// ✅ CORRECT: Use className
❌ Don't: Use Arbitrary Spacing Values
// ❌ INCORRECT: Arbitrary spacing values
Why it's bad: Creates maintenance burden, inconsistent spacing across app.
Correct approach:
// ✅ CORRECT: Use spacing scale
❌ Don't: Use className for Component Props
// ❌ INCORRECT: Using className instead of props
Item
Click
Title
Why it's bad: Loses type safety, harder to maintain, bypasses design system.
Correct approach:
// ✅ CORRECT: Use component props
Item
Click
Title
❌ Don't: Import from react-native for Wrapped Components
// ❌ INCORRECT: Direct React Native imports
import { KeyboardAvoidingView, View, Text } from 'react-native';
Content
Why it's bad: Breaks cross-platform compatibility, loses theming and accessibility.
Correct approach:
// ✅ CORRECT: Use Gluestack wrappers
import { KeyboardAvoidingView } from '@/components/ui/keyboard-avoiding-view';
import { Box } from '@/components/ui/box';
import { Text } from '@/components/ui/text';
Content
❌ Don't: Use ScrollView for Long Lists
// ❌ INCORRECT: ScrollView with map for long lists
{items.map((item) => (
{item.name}
))}
Why it's bad: No virtualization, all items rendered at once, poor performance.
Correct approach:
// ✅ CORRECT: Use FlatList for long lists
(
{item.name}
)}
keyExtractor={(item) => item.id}
/>
❌ Don't: Use Animated API for Animations
// ❌ INCORRECT: Animated API (runs on JS thread)
import { Animated } from 'react-native';
const animValue = new Animated.Value(0);
Animated.timing(animValue, {
toValue: 100,
duration: 300,
}).start();
Why it's bad: Runs on JavaScript thread, can cause jank and dropped frames.
Correct approach:
// ✅ CORRECT: Use Reanimated (runs on UI thread)
import { useSharedValue, withTiming } from 'react-native-reanimated';
const animValue = useSharedValue(0);
animValue.value = withTiming(100, { duration: 300 });
Common Mistakes Summary
| Mistake | Impact | Correct Approach | |---------|--------|-----------------| | Using React Native primitives | Loses theming, accessibility, cross-platform support | Use Gluestack components | | Using typography-*, neutral-*, gray-* tokens | Breaks theming and dark mode | Use ONLY semantic tokens | | Using numbered colors (red-500, blue-600) | Breaks theming and dark mode | Use semantic tokens | | Using opacity utilities (opacity-70) | Inconsistent transparency | Use alpha values (/70, /90) | | Raw color values | Breaks theming and dark mode | Use semantic tokens | | Skipping sub-components | Components won't render correctly | Use proper compound components | | Inline styles for static values | Bypasses optimization, harder to maintain | Use className | | Arbitrary spacing values | Creates maintenance burden | Use spacing scale | | className instead of props | Loses type safety | Use component props when available | | Direct react-native imports | Breaks cross-platform compatibility | Use Gluestack wrappers | | ScrollView for long lists | Poor performance | Use FlatList | | Animated API | Janky animations | Use Reanimated worklets | | Still using tailwind.config.js in v5 | Tailwind v4 is CSS-first; config ignored | Delete it, use global.css @theme inline | | Missing lightningcss pin (NativeWind v5) | Build errors, CSS mismatch | Pin lightningcss@1.30.1 in overrides/resolutions | | Using @tailwind base/components/utilities | Tailwind v4 uses @import syntax | Use @import "tailwindcss/..." | | Missing postcss.config.js (NativeWind v5) | CSS not processed | Create with @tailwindcss/postcss plugin |
Critical Issues (Must Fix Immediately)
🔴 Critical: InputIcon Not Wrapped in InputSlot
// ❌ CRITICAL ERROR: Will break rendering
// ✅ MUST FIX: Wrap InputIcon in InputSlot
🔴 Critical: Missing ButtonText
// ❌ CRITICAL ERROR: Button won't render correctly
Submit
// ✅ MUST FIX: Use ButtonText
Submit
🔴 Critical: Using React Native Instead of Gluestack
// ❌ CRITICAL ERROR: Breaks cross-platform support
import { View, Text } from 'react-native';
// ✅ MUST FIX: Use Gluestack components
import { Box } from '@/components/ui/box';
import { Text } from '@/components/ui/text';
🔴 Critical: Using Non-Semantic Color Tokens
// ❌ CRITICAL ERROR: Using prohibited tokens
Heading
Card
Content
Primary
// ✅ MUST FIX: Use ONLY semantic tokens
Heading
Card
Content
Primary
Code Review Guidelines
High Priority (Must Have)
- Component consistency - All components use Gluestack wrappers
- Compound components - All sub-components used correctly
- CRITICAL: Semantic tokens ONLY - Zero tolerance for:
typography-*,neutral-*,gray-*,slate-*tokens- Numbered colors:
red-500,blue-600,green-400 - Arbitrary values:
[#3b82f6],[#DC2626] - Opacity utilities:
opacity-70,bg-opacity-90 - Must use ONLY:
text-foreground,bg-primary,border-border, etc.
- Component props - Props used instead of className when available
Medium Priority (Should Have)
- TypeScript types - All props and components typed
- Spacing scale - No arbitrary spacing values
- Performance - FlatList for long lists, memoization for expensive components
- Dark mode - Proper dark mode support
Low Priority (Nice to Have)
- Animations - Using Reanimated instead of Animated API
- Code organization - Logical component structure
- Documentation - Comments for complex logic
Escalation Guidance
When a design request cannot be satisfied with existing patterns:
Step 1: Push Back Early
Explain the implications:
- Performance impact
- Maintenance burden
- Breaks theming/dark mode
- Inconsistent with design system
Example: > "Using arbitrary spacing values like p-[13px] creates maintenance issues and breaks consistency. Can we use p-3 (12px) or p-4 (16px) from our spacing scale instead?"
Step 2: Propose Alternatives
Map to existing tokens:
// Request: "Make it slightly lighter red"
// ❌ Don't use: bg-red-400
// ✅ Propose: bg-destructive/80 (with alpha)
Suggest new semantic tokens:
// Request: "I need a success color"
// ✅ Propose: Add success token to design system
// Then use: text-success, bg-success
Step 3: Add to Design System
If truly needed, add the CSS custom property to global.css @layer theme and map it in @theme inline, then update gluestack-ui-provider/config.ts:
// 1. Add to global.css @layer theme
// --success: 34 197 94;
// --success-foreground: 255 255 255;
// 2. Map in global.css @theme inline
// --color-success: rgb(var(--success));
// --color-success-foreground: rgb(var(--success-foreground));
// 3. Update provider config
export const config = {
tokens: {
colors: {
success: '34 197 94',
'success-foreground': '255 255 255',
},
},
};
Step 4: Document Exception
If inline style is unavoidable, document why:
/**
* Using inline style for dynamic safe area padding
* Cannot use className as value comes from hook
*/
{/* Content */}
Quick Validation Script
Use this mental checklist when reviewing code:
- ✅ Gluestack components? (not React Native)
- ✅ Compound components correct? (ButtonText, InputSlot, etc.)
- ✅ CRITICAL: Semantic tokens ONLY?
- ❌ No
typography-*,neutral-*,gray-*,slate-* - ❌ No numbered colors:
red-500,blue-600 - ❌ No arbitrary values:
[#3b82f6] - ❌ No opacity utilities:
opacity-70 - ✅ Only semantic:
text-foreground,bg-primary,border-border
- ✅ Component props? (space, size, variant)
- ✅ Spacing scale? (no arbitrary values)
- ✅ TypeScript types? (all props typed)
- ✅ Performance? (FlatList, memoization)
- ✅ Cross-platform? (Gluestack wrappers)
Reference
- Official Documentation: https://gluestack.io/ui/docs
- Component Verification:
https://gluestack.io/ui/docs/components/${componentName}/
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: gluestack
- Source: gluestack/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.