← VercelCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
changed
Update to Vercel
Snapshot Sep 30, 2026 · 23:18 UTC · version 0.21.4
Collection source: not recorded for this historical snapshot. These snapshots do not have a confirmed matching collection source. Differences in file lists alone do not establish changes to the package.
Supporting file metadata differs
Newly listed paths: agents/openai.yaml. This compares saved file lists, not package contents; a different collection source can change the list.
Observed in package metadata. These changes alone do not establish a new customer-facing feature.
Supporting files
Before
[]
After
[{"relative_path":"agents/openai.yaml","size_in_bytes":90}]
Compare saved observations
Download comparison JSONFull technical diff · 1 changed fields
changed /included_files
BEFORE
[]
AFTER
[
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 90
}
]Full snapshot data
{
"name": "swr",
"description": "SWR data-fetching expert guidance. Use when building React apps with client-side data fetching, caching, revalidation, mutations, optimistic UI, pagination, or infinite loading using the SWR library.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 90
}
],
"skill_md_contents": "---\nname: swr\ndescription: SWR data-fetching expert guidance. Use when building React apps with client-side data fetching, caching, revalidation, mutations, optimistic UI, pagination, or infinite loading using the SWR library.\nmetadata:\n priority: 4\n docs:\n - \"https://swr.vercel.app/docs\"\n sitemap: \"https://swr.vercel.app/sitemap.xml\"\n pathPatterns:\n - 'lib/fetcher.*'\n - 'src/lib/fetcher.*'\n - 'utils/fetcher.*'\n - 'src/utils/fetcher.*'\n - 'hooks/use*SWR*'\n - 'src/hooks/use*SWR*'\n - 'hooks/useFetch*'\n - 'src/hooks/useFetch*'\n importPatterns:\n - 'swr'\n - 'swr/*'\n bashPatterns:\n - '\\bnpm\\s+(install|i|add)\\s+[^\\n]*\\bswr\\b'\n - '\\bpnpm\\s+(install|i|add)\\s+[^\\n]*\\bswr\\b'\n - '\\bbun\\s+(install|i|add)\\s+[^\\n]*\\bswr\\b'\n - '\\byarn\\s+add\\s+[^\\n]*\\bswr\\b'\n promptSignals:\n phrases:\n - \"swr\"\n - \"useswr\"\n - \"stale-while-revalidate\"\n allOf:\n - [data fetching, client]\n - [cache, revalidat]\n anyOf:\n - \"mutation\"\n - \"optimistic\"\n - \"infinite loading\"\n - \"pagination\"\n noneOf: []\n minScore: 6\n---\n\n# SWR — React Hooks for Data Fetching\n\nYou are an expert in SWR v2 (latest: 2.4.1), the React Hooks library for data fetching by Vercel. SWR implements the stale-while-revalidate HTTP cache invalidation strategy — serve from cache first, then revalidate in the background.\n\n## Installation\n\n```bash\nnpm install swr\n```\n\n## Core API\n\n### `useSWR`\n\n```tsx\nimport useSWR from 'swr'\n\nconst fetcher = (url: string) => fetch(url).then(res => res.json())\n\nfunction Profile() {\n const { data, error, isLoading, mutate } = useSWR('/api/user', fetcher)\n\n if (isLoading) return <div>Loading...</div>\n if (error) return <div>Error loading data</div>\n return <div>Hello, {data.name}</div>\n}\n```\n\n**Key parameters:**\n- `key` — unique string, array, or function identifying the resource (often a URL)\n- `fetcher` — async function that receives the key and returns data\n- `options` — optional config object\n\n**Return values:** `data`, `error`, `isLoading`, `isValidating`, `mutate`\n\n### `useSWRMutation` — Remote Mutations\n\n```tsx\nimport useSWRMutation from 'swr/mutation'\n\nasync function updateUser(url: string, { arg }: { arg: { name: string } }) {\n return fetch(url, { method: 'POST', body: JSON.stringify(arg) }).then(res => res.json())\n}\n\nfunction Profile() {\n const { trigger, isMutating } = useSWRMutation('/api/user', updateUser)\n\n return (\n <button disabled={isMutating} onClick={() => trigger({ name: 'New Name' })}>\n Update\n </button>\n )\n}\n```\n\n### `useSWRInfinite` — Pagination & Infinite Loading\n\n```tsx\nimport useSWRInfinite from 'swr/infinite'\n\nconst getKey = (pageIndex: number, previousPageData: any[]) => {\n if (previousPageData && !previousPageData.length) return null\n return `/api/items?page=${pageIndex}`\n}\n\nfunction Items() {\n const { data, size, setSize, isLoading } = useSWRInfinite(getKey, fetcher)\n const items = data ? data.flat() : []\n\n return (\n <>\n {items.map(item => <div key={item.id}>{item.name}</div>)}\n <button onClick={() => setSize(size + 1)}>Load More</button>\n </>\n )\n}\n```\n\n## Global Configuration\n\nWrap your app (or a subtree) with `SWRConfig` to set defaults:\n\n```tsx\nimport { SWRConfig } from 'swr'\n\nfunction App() {\n return (\n <SWRConfig value={{\n fetcher: (url: string) => fetch(url).then(res => res.json()),\n revalidateOnFocus: false,\n dedupingInterval: 5000,\n }}>\n <Dashboard />\n </SWRConfig>\n )\n}\n```\n\n## Revalidation Strategies\n\n| Strategy | Option | Default |\n|---|---|---|\n| On window focus | `revalidateOnFocus` | `true` |\n| On network recovery | `revalidateOnReconnect` | `true` |\n| On mount if stale | `revalidateIfStale` | `true` |\n| Polling | `refreshInterval` | `0` (disabled) |\n| Manual | Call `mutate()` | — |\n\n## Optimistic Updates\n\n```tsx\nconst { trigger } = useSWRMutation('/api/user', updateUser, {\n optimisticData: (current) => ({ ...current, name: 'New Name' }),\n rollbackOnError: true,\n populateCache: true,\n revalidate: false,\n})\n```\n\n## Conditional Fetching\n\nPass `null` or a falsy key to skip fetching:\n\n```tsx\nconst { data } = useSWR(userId ? `/api/user/${userId}` : null, fetcher)\n```\n\n## Error Retry\n\nSWR retries on error by default with exponential backoff. Customize with:\n\n```tsx\nuseSWR(key, fetcher, {\n onErrorRetry: (error, key, config, revalidate, { retryCount }) => {\n if (error.status === 404) return // Don't retry on 404\n if (retryCount >= 3) return // Max 3 retries\n setTimeout(() => revalidate({ retryCount }), 5000)\n },\n})\n```\n\n## `useSWRSubscription` — Real-Time Data Sources\n\nSubscribe to real-time data (WebSockets, SSE, etc.) with automatic deduplication:\n\n```tsx\nimport useSWRSubscription from 'swr/subscription'\n\nfunction LivePrice({ symbol }: { symbol: string }) {\n const { data } = useSWRSubscription(\n `wss://stream.example.com/${symbol}`,\n (key, { next }) => {\n const ws = new WebSocket(key)\n ws.onmessage = (event) => next(null, JSON.parse(event.data))\n ws.onerror = (event) => next(event)\n return () => ws.close()\n }\n )\n\n return <span>{data?.price}</span>\n}\n```\n\nThe `subscribe` function receives a `next(error, data)` callback and must return a cleanup function. Multiple components using the same key share a single subscription.\n\n## Key Rules\n\n- **Keys must be unique** — two `useSWR` calls with the same key share cache and deduplicate requests\n- **Fetcher is optional** when set via `SWRConfig`\n- **`mutate(key)`** globally revalidates any hook matching that key\n- **Array keys** like `useSWR(['/api/user', id], fetcher)` — the fetcher receives the full array\n- **Never call hooks conditionally** — use conditional keys (`null`) instead\n"
}SHA-256: bd3b4e4b9632d3ef38c41c4425cbc4abb0583b8287c9b7151f3b8552e2251026