react-frontend — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited react-frontend (Agent Skill) and scored it 91/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.
ignore/disregard/forget … previous instructions sentence.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.
ComponentPropsWithoutRef<'button'>, add custom props via intersectionReact.ReactNode for children, React.ReactElement for single element, render prop (data: T) => ReactNode<T> with keyof T for column keys, T extends { id: string } for constraintsReact.MouseEvent<HTMLButtonElement>, FormEvent<HTMLFormElement>, ChangeEvent<HTMLInputElement>as const for custom hook tuple returnsuseRef<HTMLInputElement>(null) for DOM (use ?.), useRef<number>(0) for mutable valuesuseState<User | null>(null) for unions/null{ type: 'set'; payload: number } | { type: 'reset' }useX() hook if context is nullEffects are escape hatches — most logic should NOT use effects.
| Need | Solution |
|---|---|
| Derived value from props/state | Calculate during render (useMemo if expensive) |
| Reset state on prop change | key prop on component |
| Respond to user event | Event handler |
| Notify parent of state change | Call onChange in event handler, or fully controlled component |
| Chain of state updates | Calculate all next state in one event handler |
| Sync with external system | Effect with cleanup |
Effect rules:
setItems(prev => [...prev, item])) to remove state dependenciesuseEffectEvent for non-reactive values (e.g., theme in a connection effect)ignore flag pattern or React QueryLocal UI state → useState, useReducer
Shared client state → Zustand (simple) | Redux Toolkit (complex)
Atomic/granular → Jotai
Server/remote data → React Query (TanStack Query)
URL state → nuqs, router search params
Form state → React Hook FormKey patterns:
create<State>()(devtools(persist((set) => ({...})))) — use slices for scale, selective subscriptions to prevent re-renders['users', 'detail', id] as const), staleTime/gcTime, optimistic updates with onMutate/onError rollbackCritical — eliminate waterfalls:
Promise.all() for independent async operationsawait into branches where actually neededCritical — bundle size:
index.ts re-exports)next/dynamic or React.lazy() for heavy componentsRe-render optimization:
state.items.length > 0 not state.items)setCount(c => c + 1)useState(() => expensiveComputation())useTransition for non-urgent updates (search filtering)useDeferredValue for expensive derived UIcondition ? <A /> : <B />), not && for conditionalsReact.memo only for expensive subtrees with stable propsReact Compiler (React 19): auto-memoizes — write idiomatic React, remove manual useMemo/useCallback/memo. Install babel-plugin-react-compiler, keep components pure.
forwardRef deprecated. Accept ref?: React.Ref<HTMLElement> as regular propuseFormState: const [state, formAction, isPending] = useActionState(action, initialState)const [optimistic, addOptimistic] = useOptimistic(state, mergeFn) for instant UI feedbackconst { pending } = useFormStatus() in child of <form action={...}>'use server' directive. Validate inputs (Zod), revalidateTag/revalidatePath after mutationsFile conventions: page.tsx (route UI), layout.tsx (shared wrapper), loading.tsx (Suspense), error.tsx (error boundary), not-found.tsx (404), route.ts (API endpoint)
Rendering modes: Server Components (default) | Client ('use client') | Static (build) | Dynamic (request) | Streaming (progressive)
Decision: Server Component unless it needs hooks, event handlers, or browser APIs. Split: server parent + client child.
Routing patterns:
(name) — organize without affecting URL@slot — independent loading states in same layout(.) — modal overlays with full-page fallbackCaching:
fetch(url, { cache: 'force-cache' }) — staticfetch(url, { next: { revalidate: 60 } }) — ISRfetch(url, { cache: 'no-store' }) — dynamicfetch(url, { next: { tags: ['products'] } }) then revalidateTag('products')Data fetching: Fetch in Server Components where data is used. Use Suspense boundaries for slow queries. React.cache() for per-request dedup. generateStaticParams for static generation. generateMetadata for dynamic SEO.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.