# AGENTS.md — TanStack Query (v5) Conventions for `@tanstack/react-query` v5. Grounded in the official docs. - Use the v5 object syntax: `useQuery({ queryKey, queryFn })`, `useMutation({ mutationFn })`. - A query = a unique key + a function returning a promise that resolves data or **throws** on error. - `fetch` doesn't throw on HTTP errors — check `res.ok` and throw, or the query won't enter the error state. - Query keys are **arrays**, `JSON.stringify`-serializable, and unique to the data: `['todos']`, `['todo', 5, { preview: true }]`. - Put **every variable the `queryFn` uses** in the key; changing it refetches automatically. The key is the dependency array. - Object key props are hashed order-independently; **array item order matters**. - `status` (`pending`/`error`/`success`) is about data; `fetchStatus` (`fetching`/`paused`/`idle`) is about the running function. Use both. - Default `staleTime` is `0` (stale immediately); stale queries refetch on mount, window focus, and reconnect. Tune `staleTime` instead of disabling refetch flags. - Default `gcTime` is 5 minutes for inactive queries. Freshness (`staleTime`) and retention (`gcTime`) are independent. - Failed queries retry **3 times with exponential backoff** by default — don't disable retries blindly. - Results are structurally shared (stable references for unchanged data); don't re-memoize `data`. - Use `useMutation` for create/update/delete; trigger with `mutate(variables)`. - After a successful mutation, `queryClient.invalidateQueries({ queryKey })` (in `onSuccess`/`onSettled`) or `setQueryData`. - Callback order: `onMutate` → `onSuccess`/`onError` → `onSettled`. Use `mutateAsync` only when you need to await at the call site. - Don't use TanStack Query for non-server state (form/UI/derived values) — that belongs in `useState` or derived on render.