performance — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited performance (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
| TTI | Rating |
|---|---|
| <2s | Excellent |
| 2--4s | Acceptable |
| >4s | Poor -- must fix |
JS Bundle load target: <500ms. Native init target: <500ms.
| FPS | State |
|---|---|
| 55--60 | Smooth -- target |
| 45--55 | Slight stutter -- investigate |
| 30--45 | Noticeable -- fix before release |
| <30 | Critical |
UI FPS drop = native rendering issue (layout properties animated, heavy views)\ JS FPS drop = JS thread blocked (heavy computation, too many re-renders)
// ❌ ScrollView -- renders ALL items upfront, freezes on long lists
<ScrollView>
{posts.map(p => <PostCard key={p.id} {...p} />)}
</ScrollView>
// ✅ FlashList -- virtualizes, renders only visible items
import { FlashList } from '@shopify/flash-list'
<FlashList
data={posts}
renderItem={({ item }) => <PostCard id={item.id} title={item.title} />}
estimatedItemSize={88}
keyExtractor={item => item.id}
onEndReached={fetchNextPage}
onEndReachedThreshold={0.5}
ListEmptyComponent={<EmptyState />}
ListFooterComponent={isFetchingNextPage ? <ActivityIndicator /> : null}
/>// ❌ Object prop -- breaks memo, re-renders every time
<FlashList renderItem={({ item }) => <PostCard data={item} onPress={handlePress} />} />
// ✅ Primitive props -- shallow comparison works
<FlashList renderItem={({ item }) => (
<PostCard id={item.id} title={item.title} onPress={handlePress} />
)} />
// ✅ Memoized item
const PostCard = memo(({ id, title, onPress }: PostCardProps) => ...)
// ✅ Hoisted callback -- stable reference
const handlePress = useCallback((id: string) => router.push({ pathname: '/(app)/[id]', params: { id } }), [])
// ✅ Memoized data
const filteredPosts = useMemo(() => posts.filter(p => p.active), [posts])type FeedItem = { type: 'post' | 'ad' | 'story' } & (PostItem | AdItem | StoryItem)
<FlashList
data={feed}
getItemType={item => item.type}
estimatedItemSize={88}
renderItem={({ item }) => {
if (item.type === 'post') return <PostCard {...item} />
if (item.type === 'ad') return <AdCard {...item} />
return <StoryCard {...item} />
}}
/>// ❌ Inline object -- new reference every render
<Component style={{ color: 'red' }} options={{ timeout: 1000 }} />
// ✅ Outside component or useMemo
const STYLE = { color: 'red' as const }
const OPTIONS = { timeout: 1000 }
// ❌ Inline function -- new reference every render
<FlatList renderItem={({ item }) => <Item {...item} onPress={() => handlePress(item.id)} />} />
// ✅ useCallback
const renderItem = useCallback(({ item }) => <Item {...item} onPress={handlePress} />, [handlePress])Automatically removes memo, useCallback, useMemo where safe.
# Check if your code is compiler-ready
bunx react-compiler-healthcheck@latestWrite compiler-friendly code:
// ✅ Destructure functions at render top
function Screen({ onPress, onChange }: Props) {
// Compiler can optimize these
const handlePress = () => onPress()
const handleChange = (v: string) => onChange(v)
}
// ❌ Dot-access in JSX
<Pressable onPress={() => props.onPress()} />Enabled by default in Expo SDK 52+. Hermes benefits:
Ensure Hermes is enabled in app.json:
{ "expo": { "jsEngine": "hermes" } }// ❌ Causes layout recalculation
width.value = withSpring(200)
marginTop.value = withTiming(20)
// ✅ GPU only
transform: [{ scale: scaleValue }]
opacity: opacityValue// ❌ Created in render -- expensive
function formatDate(date: Date) {
return new Intl.DateTimeFormat('en-US', { month: 'short' }).format(date)
}
// ✅ Created once at module level
const dateFormatter = new Intl.DateTimeFormat('en-US', { month: 'short' })
function formatDate(date: Date) { return dateFormatter.format(date) }# Expo Atlas (most accurate for Expo)
EXPO_UNSTABLE_ATLAS=true bunx expo export
# Open .expo/atlas.jsonl in Atlas viewer
# Source map explorer
bunx source-map-explorer dist/index.jsCommon bundle issues:
import { x } from 'big-library' loads everything)dayjs instead)bun why <package>)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.