From bee-dev-team
Gate 6 of the React Native frontend development cycle - ensures JS bundle size within budget, Hermes engine enabled, FlatList/FlashList correctly used, image optimization applied, and no unnecessary re-renders detected. Covers React Native-specific optimizations including memo, useCallback, useMemo, and FlashList for performant list rendering.
npx claudepluginhub luanrodrigues/ia-frmwrk --plugin bee-dev-teamThis skill uses the workspace's default tool permissions.
Ensure all React Native frontend screens and components meet **mobile performance budgets**: JS bundle within budget, Hermes engine enabled, FlashList used for long lists, images optimized, and UI thread not blocked by unnecessary re-renders.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Ensure all React Native frontend screens and components meet mobile performance budgets: JS bundle within budget, Hermes engine enabled, FlashList used for long lists, images optimized, and UI thread not blocked by unnecessary re-renders.
Core principle: Performance on mobile is non-negotiable. Low-end Android devices have 1-2GB RAM. Slow UI thread kills the user experience. Performance budgets are enforced, not suggested.
<block_condition>
This skill ORCHESTRATES. React Native Frontend QA Analyst Agent (performance mode) EXECUTES.
| Who | Responsibility |
|---|---|
| This Skill | Gather requirements, dispatch agent, track iterations |
| QA Analyst Frontend React Native Agent | Run bundle analysis, audit components, check Hermes, detect re-renders |
MANDATORY: Load testing-performance-rn.md standards via WebFetch.
<fetch_required> https://raw.githubusercontent.com/luanrodrigues/ia-frmwrk/master/dev-team/docs/standards/frontend-react-native/testing-performance.md </fetch_required>
REQUIRED INPUT:
- unit_id: [task/subtask being tested]
- implementation_files: [files from Gate 0]
OPTIONAL INPUT:
- performance_baseline: [previous metrics for comparison]
- gate5_handoff: [full Gate 5 output]
if any REQUIRED input is missing:
→ STOP and report: "Missing required input: [field]"
Task tool:
subagent_type: "bee:qa-analyst-frontend-react-native"
model: "opus"
prompt: |
**MODE:** PERFORMANCE TESTING (Gate 6)
**Standards:** Load testing-performance.md (frontend-react-native)
**Input:**
- Unit ID: {unit_id}
- Implementation Files: {implementation_files}
- Baseline: {performance_baseline or "N/A"}
- Framework: React Native (Expo or bare)
**Requirements:**
1. Analyze JS bundle size change vs baseline (use react-native-bundle-visualizer or metro bundle output)
2. Verify Hermes engine is enabled (app.json jsEngine: "hermes" or build.gradle setting)
3. Audit all list components: FlatList with > 10 items MUST be replaced with FlashList
4. Audit image components: remote URLs MUST use react-native-fast-image or Expo Image
5. Detect unnecessary re-renders using React.memo, useCallback, useMemo audit
6. Verify UI thread is not blocked: no heavy computation in render path
7. Check Reanimated usage for animations (not Animated API for performance-critical animations)
8. Detect InteractionManager usage for deferred post-animation work
**React Native-Specific Performance Checks:**
- FlashList from @shopify/flash-list used for ALL lists with > 10 items (never FlatList)
- FlashList has correct estimatedItemSize prop set
- FlatList keyExtractor returns stable unique string keys (not index)
- React.memo applied to list item components that receive complex props
- useCallback applied to event handlers passed as props (prevent child re-renders)
- useMemo applied to expensive computations in render
- Image components for remote URLs use react-native-fast-image or expo-image (not bare <Image>)
- Image components have defined width/height to prevent layout shifts
- InteractionManager.runAfterInteractions() used for heavy work after navigation transitions
- No synchronous heavy computation in render (move to useMemo or background thread)
- setNativeDriver: true used for all Animated animations that don't modify layout
- Reanimated 2/3 used for gesture-driven animations (not Animated for 60fps requirements)
- No anonymous functions as direct props to pure components
- Zustand selectors are granular (avoid selecting entire store, select only needed slice)
- No Redux useSelector selecting entire state object
- Navigation screen options are stable (not inline object literals causing re-renders)
**Output Sections Required:**
- ## Performance Testing Summary
- ## Bundle Analysis
- ## Handoff to Next Gate
Parse agent output:
if "Status: PASS" in output:
→ Gate 6 PASSED
→ Return success with metrics
if "Status: FAIL" in output:
→ Dispatch fix to implementation agent (bee:frontend-engineer-react-native)
→ Re-run performance tests (max 3 iterations)
→ If still failing: ESCALATE to user
## Performance Testing Summary
**Status:** {PASS|FAIL}
**Bundle Change:** {+X%} (< 10%)
**Hermes:** {Enabled|DISABLED - FAIL}
**FlashList Violations:** {count}
**Unnecessary Re-renders:** {count}
**Image Optimization Violations:** {count}
## Bundle Analysis
| Metric | Current | Baseline | Change | Status |
|--------|---------|----------|--------|--------|
| JS Bundle (gzipped) | {size} | {size} | {change}% | {PASS|FAIL} |
| Total Assets | {size} | {size} | {change}% | {PASS|FAIL} |
## List Component Audit
| Screen/Component | List Type | Item Count | Status |
|-----------------|-----------|------------|--------|
| {name} | {FlatList|FlashList} | {count} | {PASS|FAIL} |
## Image Optimization Audit
| Component | Image Type | Library Used | Status |
|-----------|------------|--------------|--------|
| {name} | {remote|local} | {FastImage|ExpoImage|bare Image} | {PASS|FAIL} |
## Re-render Analysis
| Component | Re-render Cause | Fix Applied | Status |
|-----------|-----------------|-------------|--------|
| {name} | {reason} | {memo/useCallback/useMemo} | {PASS|FAIL} |
## Anti-Pattern Detection
| Pattern | Occurrences | Status |
|---------|-------------|--------|
| FlatList with > 10 items (not FlashList) | {count} | {PASS|FAIL} |
| Remote image without FastImage/ExpoImage | {count} | {PASS|FAIL} |
| Animated without setNativeDriver: true | {count} | {PASS|FAIL} |
| Anonymous function as prop to pure component | {count} | {PASS|FAIL} |
| Heavy computation in render (not memoized) | {count} | {PASS|FAIL} |
| Hermes disabled | {Yes|No} | {PASS|FAIL} |
## Handoff to Next Gate
- Ready for Gate 7 (Code Review): {YES|NO}
- Iterations: {count}
See shared-patterns/shared-anti-rationalization.md for universal anti-rationalizations. Gate-specific:
| Rationalization | Why It's WRONG | Required Action |
|---|---|---|
| "Works fine on simulator" | Simulators don't reflect low-end Android performance. | Measure on representative device |
| "We'll optimize later" | Performance debt compounds. Fix during development. | Meet thresholds now |
| "FlatList is fine for 20 items" | FlashList is always faster. 10+ items = FlashList. | Replace FlatList with FlashList |
| "Hermes doesn't matter for dev builds" | Hermes is production default. Disable it = production regression. | Ensure Hermes enabled |
| "FastImage is complex to set up" | FastImage gives free caching + performance. Always use it for remote URLs. | Use FastImage or Expo Image |
| "React.memo is premature optimization" | Without memo, parent re-renders force child re-renders in RN. Apply it. | Apply React.memo to list items |
| "useCallback everywhere is verbose" | Without useCallback, handlers cause child re-renders on every render. | Apply useCallback to stable handlers |
| "Bundle size doesn't matter" | Large bundles increase launch time, especially on cold start. | Stay within 10% budget |
| "Animated API is fine for animations" | Animated runs on JS thread. Reanimated runs on UI thread. Use Reanimated for smooth 60fps. | Use Reanimated for performance-critical animations |