[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-tanstack-ai-coreclient-persistence":3,"mdc-yjvzyf-key":53,"related-repo-tanstack-ai-coreclient-persistence":1258,"related-org-tanstack-ai-coreclient-persistence":1353},{"slug":4,"name":5,"fn":6,"description":7,"org":8,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":48,"sourceUrl":51,"mdContent":52},"ai-coreclient-persistence","ai-core\u002Fclient-persistence","implement browser chat persistence for TanStack AI","Browser chat persistence on useChat \u002F ChatClient: localStoragePersistence, sessionStoragePersistence, indexedDBPersistence. Client-authoritative (adapter, full transcript) vs server-authoritative (persistence: true, no client cache). Reload restore, pending interrupts, mid-stream rejoin with delivery durability. Use for SPA reload durability — NOT server history alone. No extra package: the adapters ship in the framework packages.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},"tanstack","TanStack","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Ftanstack.png",[13,17,20,21],{"name":14,"slug":15,"type":16},"AI","ai","tag",{"name":18,"slug":19,"type":16},"Persistence","persistence",{"name":10,"slug":9,"type":16},{"name":22,"slug":23,"type":16},"Frontend","frontend",2884,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Fai","2026-07-30T05:53:35.503176",null,269,[15,30,31,32,33,34,35,36,37,38,39,40,41,42,43,9,44,45,46,47],"ai-agents","ai-sdk","anthropic","chatbot","function-calling","gemini","generative-ai","llm","multimodal","openai","react","solidjs","streaming","svelte","tool-calling","typescript","typescript-sdk","vue",{"repoUrl":25,"stars":24,"forks":28,"topics":49,"description":50},[15,30,31,32,33,34,35,36,37,38,39,40,41,42,43,9,44,45,46,47],"🤖 Type-safe, provider-agnostic TypeScript AI SDK for streaming chat, tool calling, agents, and multimodal apps across OpenAI, Anthropic, Gemini, React, Vue, Svelte, and Solid.","https:\u002F\u002Fgithub.com\u002FTanStack\u002Fai\u002Ftree\u002FHEAD\u002Fpackages\u002Fai\u002Fskills\u002Fai-core\u002Fclient-persistence","---\nname: ai-core\u002Fclient-persistence\ndescription: >\n  Browser chat persistence on useChat \u002F ChatClient: localStoragePersistence,\n  sessionStoragePersistence, indexedDBPersistence. Client-authoritative\n  (adapter, full transcript) vs server-authoritative (persistence: true, no\n  client cache).\n  Reload restore, pending interrupts, mid-stream rejoin with delivery\n  durability. Use for SPA reload durability — NOT server history alone.\n  No extra package: the adapters ship in the framework packages.\ntype: sub-skill\nlibrary: tanstack-ai\nlibrary_version: '0.10.0'\nsources:\n  - 'TanStack\u002Fai:docs\u002Fpersistence\u002Fclient-persistence.md'\n  - 'TanStack\u002Fai:docs\u002Fpersistence\u002Foverview.md'\n---\n\n# Client Persistence\n\n> Builds on ai-core, and on `ai-core\u002Fchat-experience` for `useChat` itself.\n>\n> **No extra package.** The adapters below ship in the **framework** packages\n> (`@tanstack\u002Fai-react` and friends, re-exported from `@tanstack\u002Fai-client`),\n> so browser persistence needs nothing installed beyond what a chat UI already\n> has. The **server** half is a separate package — see\n> `@tanstack\u002Fai-persistence` and its `ai-persistence\u002Fserver` skill.\n\nA `ChatClient` \u002F `useChat` keeps messages in memory. The `persistence` option\nstores one record per `threadId` so a reload can repaint the transcript,\nrestore a pending interrupt, and rejoin an in-flight run.\n\nImport adapters from the **framework package** (not `@tanstack\u002Fai-client`\nunless vanilla JS):\n\n```tsx\nimport {\n  useChat,\n  fetchServerSentEvents,\n  localStoragePersistence,\n  sessionStoragePersistence,\n  indexedDBPersistence,\n} from '@tanstack\u002Fai-react'\n```\n\n## Adapters\n\n| Adapter                       | Survives                   | Notes                                                           |\n| ----------------------------- | -------------------------- | --------------------------------------------------------------- |\n| `localStoragePersistence()`   | Reloads + browser restarts | Sync hydrate; quota-bound; JSON codec default                   |\n| `sessionStoragePersistence()` | Reloads in the same tab    | Cleared when tab\u002Fsession ends                                   |\n| `indexedDBPersistence()`      | Reloads + restarts         | Async open (first paint may be empty briefly); structured clone |\n\nAll default to the chat persisted-state shape — no type argument or codec\nrequired for normal use.\n\n## Mode A — cache everything (client-authoritative)\n\n```tsx\nfunction Chat() {\n  const { messages, sendMessage } = useChat({\n    threadId: 'support-chat', \u002F\u002F stable — required\n    connection: fetchServerSentEvents('\u002Fapi\u002Fchat'),\n    persistence: localStoragePersistence(),\n  })\n  \u002F\u002F ...\n}\n```\n\nBare adapter ≡ full transcript + resume pointer. Browser owns history; server\n(if any) mirrors when you post non-empty `messages`.\n\nBest for: SPA, offline-first, single device, moderate conversation size.\n\n## Mode B — server-authoritative (`persistence: true`)\n\n```tsx\nfunction Chat({ threadId }: { threadId: string }) {\n  const { messages, sendMessage } = useChat({\n    threadId,\n    connection: fetchServerSentEvents('\u002Fapi\u002Fchat'),\n    persistence: true,\n  })\n  \u002F\u002F ...\n}\n```\n\nNothing is cached client-side: no transcript, no resume pointer.\n\nOn mount, `useChat` hydrates the thread from the **server** by `threadId`\n(paint + tail active run). Same path for another device. Pair with server\n`withPersistence` + a hydrate route (`reconstructChat` or equivalent).\n\nBest for: large transcripts, multi-device, compliance (no message bodies in\nbrowser storage).\n\n## What a reload restores\n\n1. **Finished run** — transcript from the adapter (mode A) or server (mode B).\n2. **Paused on interrupt** — approval UI restored (from the adapter in mode A,\n   the server hydrate in mode B).\n3. **Still streaming** — needs **delivery durability** on the route\n   (`toServerSentEventsResponse(stream, { durability: … })`) so the client can\n   `joinRun` and finish the reply. Persistence alone is not enough.\n\n## Stable `threadId` is the identity\n\nPersistence keys on `threadId`. The hooks have **no separate `id` option** — a\nchat's identity _is_ its `threadId`. Without a stable one, each load is a new\nchat. Generate it server-side or from a route param the user owns; do not\nrandomize per mount.\n\n## Common mistakes\n\n### HIGH: No `threadId`\n\nRecord cannot be found after reload.\n\n### HIGH: Passing `id` to `useChat`\n\nRemoved — `threadId` is the identity. (`ChatClient` still accepts `id` directly\nas a lower-level escape hatch for keying storage separately from the wire\nthread; the framework hooks do not.)\n\n### HIGH: `persistence: true` without server history\n\nEmpty chat after reload unless the server can reconstruct by `threadId`.\n\n### MEDIUM: Huge transcripts in `localStorage`\n\nQuota and main-thread cost. Prefer `persistence: true` + server store, or\nIndexedDB with care.\n\n### MEDIUM: Expecting multi-device sync from client storage alone\n\n`localStorage` is per-browser. Use server persistence for multi-device.\n\n## Cross-references\n\n- **ai-persistence\u002Fserver** (`@tanstack\u002Fai-persistence`) — authoritative server half\n- **ai-core\u002Fchat-experience** — `useChat`, resumable connections\n- Resumable streams docs — mid-stream rejoin\n",{"data":54,"body":61},{"name":5,"description":7,"type":55,"library":56,"library_version":57,"sources":58},"sub-skill","tanstack-ai","0.10.0",[59,60],"TanStack\u002Fai:docs\u002Fpersistence\u002Fclient-persistence.md","TanStack\u002Fai:docs\u002Fpersistence\u002Foverview.md",{"type":62,"children":63},"root",[64,73,157,192,211,336,343,442,447,453,673,686,691,704,904,909,950,955,961,1019,1032,1074,1080,1092,1097,1115,1141,1154,1165,1177,1189,1195,1205,1211,1252],{"type":65,"tag":66,"props":67,"children":69},"element","h1",{"id":68},"client-persistence",[70],{"type":71,"value":72},"text","Client Persistence",{"type":65,"tag":74,"props":75,"children":76},"blockquote",{},[77,100],{"type":65,"tag":78,"props":79,"children":80},"p",{},[81,83,90,92,98],{"type":71,"value":82},"Builds on ai-core, and on ",{"type":65,"tag":84,"props":85,"children":87},"code",{"className":86},[],[88],{"type":71,"value":89},"ai-core\u002Fchat-experience",{"type":71,"value":91}," for ",{"type":65,"tag":84,"props":93,"children":95},{"className":94},[],[96],{"type":71,"value":97},"useChat",{"type":71,"value":99}," itself.",{"type":65,"tag":78,"props":101,"children":102},{},[103,109,111,116,118,124,126,132,134,139,141,147,149,155],{"type":65,"tag":104,"props":105,"children":106},"strong",{},[107],{"type":71,"value":108},"No extra package.",{"type":71,"value":110}," The adapters below ship in the ",{"type":65,"tag":104,"props":112,"children":113},{},[114],{"type":71,"value":115},"framework",{"type":71,"value":117}," packages\n(",{"type":65,"tag":84,"props":119,"children":121},{"className":120},[],[122],{"type":71,"value":123},"@tanstack\u002Fai-react",{"type":71,"value":125}," and friends, re-exported from ",{"type":65,"tag":84,"props":127,"children":129},{"className":128},[],[130],{"type":71,"value":131},"@tanstack\u002Fai-client",{"type":71,"value":133},"),\nso browser persistence needs nothing installed beyond what a chat UI already\nhas. The ",{"type":65,"tag":104,"props":135,"children":136},{},[137],{"type":71,"value":138},"server",{"type":71,"value":140}," half is a separate package — see\n",{"type":65,"tag":84,"props":142,"children":144},{"className":143},[],[145],{"type":71,"value":146},"@tanstack\u002Fai-persistence",{"type":71,"value":148}," and its ",{"type":65,"tag":84,"props":150,"children":152},{"className":151},[],[153],{"type":71,"value":154},"ai-persistence\u002Fserver",{"type":71,"value":156}," skill.",{"type":65,"tag":78,"props":158,"children":159},{},[160,162,168,170,175,177,182,184,190],{"type":71,"value":161},"A ",{"type":65,"tag":84,"props":163,"children":165},{"className":164},[],[166],{"type":71,"value":167},"ChatClient",{"type":71,"value":169}," \u002F ",{"type":65,"tag":84,"props":171,"children":173},{"className":172},[],[174],{"type":71,"value":97},{"type":71,"value":176}," keeps messages in memory. The ",{"type":65,"tag":84,"props":178,"children":180},{"className":179},[],[181],{"type":71,"value":19},{"type":71,"value":183}," option\nstores one record per ",{"type":65,"tag":84,"props":185,"children":187},{"className":186},[],[188],{"type":71,"value":189},"threadId",{"type":71,"value":191}," so a reload can repaint the transcript,\nrestore a pending interrupt, and rejoin an in-flight run.",{"type":65,"tag":78,"props":193,"children":194},{},[195,197,202,204,209],{"type":71,"value":196},"Import adapters from the ",{"type":65,"tag":104,"props":198,"children":199},{},[200],{"type":71,"value":201},"framework package",{"type":71,"value":203}," (not ",{"type":65,"tag":84,"props":205,"children":207},{"className":206},[],[208],{"type":71,"value":131},{"type":71,"value":210},"\nunless vanilla JS):",{"type":65,"tag":212,"props":213,"children":218},"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-tsx shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import {\n  useChat,\n  fetchServerSentEvents,\n  localStoragePersistence,\n  sessionStoragePersistence,\n  indexedDBPersistence,\n} from '@tanstack\u002Fai-react'\n","tsx","",[219],{"type":65,"tag":84,"props":220,"children":221},{"__ignoreMap":217},[222,240,255,268,281,294,307],{"type":65,"tag":223,"props":224,"children":227},"span",{"class":225,"line":226},"line",1,[228,234],{"type":65,"tag":223,"props":229,"children":231},{"style":230},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[232],{"type":71,"value":233},"import",{"type":65,"tag":223,"props":235,"children":237},{"style":236},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[238],{"type":71,"value":239}," {\n",{"type":65,"tag":223,"props":241,"children":243},{"class":225,"line":242},2,[244,250],{"type":65,"tag":223,"props":245,"children":247},{"style":246},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[248],{"type":71,"value":249},"  useChat",{"type":65,"tag":223,"props":251,"children":252},{"style":236},[253],{"type":71,"value":254},",\n",{"type":65,"tag":223,"props":256,"children":258},{"class":225,"line":257},3,[259,264],{"type":65,"tag":223,"props":260,"children":261},{"style":246},[262],{"type":71,"value":263},"  fetchServerSentEvents",{"type":65,"tag":223,"props":265,"children":266},{"style":236},[267],{"type":71,"value":254},{"type":65,"tag":223,"props":269,"children":271},{"class":225,"line":270},4,[272,277],{"type":65,"tag":223,"props":273,"children":274},{"style":246},[275],{"type":71,"value":276},"  localStoragePersistence",{"type":65,"tag":223,"props":278,"children":279},{"style":236},[280],{"type":71,"value":254},{"type":65,"tag":223,"props":282,"children":284},{"class":225,"line":283},5,[285,290],{"type":65,"tag":223,"props":286,"children":287},{"style":246},[288],{"type":71,"value":289},"  sessionStoragePersistence",{"type":65,"tag":223,"props":291,"children":292},{"style":236},[293],{"type":71,"value":254},{"type":65,"tag":223,"props":295,"children":297},{"class":225,"line":296},6,[298,303],{"type":65,"tag":223,"props":299,"children":300},{"style":246},[301],{"type":71,"value":302},"  indexedDBPersistence",{"type":65,"tag":223,"props":304,"children":305},{"style":236},[306],{"type":71,"value":254},{"type":65,"tag":223,"props":308,"children":310},{"class":225,"line":309},7,[311,316,321,326,331],{"type":65,"tag":223,"props":312,"children":313},{"style":236},[314],{"type":71,"value":315},"}",{"type":65,"tag":223,"props":317,"children":318},{"style":230},[319],{"type":71,"value":320}," from",{"type":65,"tag":223,"props":322,"children":323},{"style":236},[324],{"type":71,"value":325}," '",{"type":65,"tag":223,"props":327,"children":329},{"style":328},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[330],{"type":71,"value":123},{"type":65,"tag":223,"props":332,"children":333},{"style":236},[334],{"type":71,"value":335},"'\n",{"type":65,"tag":337,"props":338,"children":340},"h2",{"id":339},"adapters",[341],{"type":71,"value":342},"Adapters",{"type":65,"tag":344,"props":345,"children":346},"table",{},[347,371],{"type":65,"tag":348,"props":349,"children":350},"thead",{},[351],{"type":65,"tag":352,"props":353,"children":354},"tr",{},[355,361,366],{"type":65,"tag":356,"props":357,"children":358},"th",{},[359],{"type":71,"value":360},"Adapter",{"type":65,"tag":356,"props":362,"children":363},{},[364],{"type":71,"value":365},"Survives",{"type":65,"tag":356,"props":367,"children":368},{},[369],{"type":71,"value":370},"Notes",{"type":65,"tag":372,"props":373,"children":374},"tbody",{},[375,398,420],{"type":65,"tag":352,"props":376,"children":377},{},[378,388,393],{"type":65,"tag":379,"props":380,"children":381},"td",{},[382],{"type":65,"tag":84,"props":383,"children":385},{"className":384},[],[386],{"type":71,"value":387},"localStoragePersistence()",{"type":65,"tag":379,"props":389,"children":390},{},[391],{"type":71,"value":392},"Reloads + browser restarts",{"type":65,"tag":379,"props":394,"children":395},{},[396],{"type":71,"value":397},"Sync hydrate; quota-bound; JSON codec default",{"type":65,"tag":352,"props":399,"children":400},{},[401,410,415],{"type":65,"tag":379,"props":402,"children":403},{},[404],{"type":65,"tag":84,"props":405,"children":407},{"className":406},[],[408],{"type":71,"value":409},"sessionStoragePersistence()",{"type":65,"tag":379,"props":411,"children":412},{},[413],{"type":71,"value":414},"Reloads in the same tab",{"type":65,"tag":379,"props":416,"children":417},{},[418],{"type":71,"value":419},"Cleared when tab\u002Fsession ends",{"type":65,"tag":352,"props":421,"children":422},{},[423,432,437],{"type":65,"tag":379,"props":424,"children":425},{},[426],{"type":65,"tag":84,"props":427,"children":429},{"className":428},[],[430],{"type":71,"value":431},"indexedDBPersistence()",{"type":65,"tag":379,"props":433,"children":434},{},[435],{"type":71,"value":436},"Reloads + restarts",{"type":65,"tag":379,"props":438,"children":439},{},[440],{"type":71,"value":441},"Async open (first paint may be empty briefly); structured clone",{"type":65,"tag":78,"props":443,"children":444},{},[445],{"type":71,"value":446},"All default to the chat persisted-state shape — no type argument or codec\nrequired for normal use.",{"type":65,"tag":337,"props":448,"children":450},{"id":449},"mode-a-cache-everything-client-authoritative",[451],{"type":71,"value":452},"Mode A — cache everything (client-authoritative)",{"type":65,"tag":212,"props":454,"children":456},{"className":214,"code":455,"language":216,"meta":217,"style":217},"function Chat() {\n  const { messages, sendMessage } = useChat({\n    threadId: 'support-chat', \u002F\u002F stable — required\n    connection: fetchServerSentEvents('\u002Fapi\u002Fchat'),\n    persistence: localStoragePersistence(),\n  })\n  \u002F\u002F ...\n}\n",[457],{"type":65,"tag":84,"props":458,"children":459},{"__ignoreMap":217},[460,484,538,575,618,643,656,664],{"type":65,"tag":223,"props":461,"children":462},{"class":225,"line":226},[463,469,475,480],{"type":65,"tag":223,"props":464,"children":466},{"style":465},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[467],{"type":71,"value":468},"function",{"type":65,"tag":223,"props":470,"children":472},{"style":471},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[473],{"type":71,"value":474}," Chat",{"type":65,"tag":223,"props":476,"children":477},{"style":236},[478],{"type":71,"value":479},"()",{"type":65,"tag":223,"props":481,"children":482},{"style":236},[483],{"type":71,"value":239},{"type":65,"tag":223,"props":485,"children":486},{"class":225,"line":242},[487,492,497,502,507,512,517,522,527,533],{"type":65,"tag":223,"props":488,"children":489},{"style":465},[490],{"type":71,"value":491},"  const",{"type":65,"tag":223,"props":493,"children":494},{"style":236},[495],{"type":71,"value":496}," {",{"type":65,"tag":223,"props":498,"children":499},{"style":246},[500],{"type":71,"value":501}," messages",{"type":65,"tag":223,"props":503,"children":504},{"style":236},[505],{"type":71,"value":506},",",{"type":65,"tag":223,"props":508,"children":509},{"style":246},[510],{"type":71,"value":511}," sendMessage",{"type":65,"tag":223,"props":513,"children":514},{"style":236},[515],{"type":71,"value":516}," }",{"type":65,"tag":223,"props":518,"children":519},{"style":236},[520],{"type":71,"value":521}," =",{"type":65,"tag":223,"props":523,"children":524},{"style":471},[525],{"type":71,"value":526}," useChat",{"type":65,"tag":223,"props":528,"children":530},{"style":529},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[531],{"type":71,"value":532},"(",{"type":65,"tag":223,"props":534,"children":535},{"style":236},[536],{"type":71,"value":537},"{\n",{"type":65,"tag":223,"props":539,"children":540},{"class":225,"line":257},[541,546,551,555,560,565,569],{"type":65,"tag":223,"props":542,"children":543},{"style":529},[544],{"type":71,"value":545},"    threadId",{"type":65,"tag":223,"props":547,"children":548},{"style":236},[549],{"type":71,"value":550},":",{"type":65,"tag":223,"props":552,"children":553},{"style":236},[554],{"type":71,"value":325},{"type":65,"tag":223,"props":556,"children":557},{"style":328},[558],{"type":71,"value":559},"support-chat",{"type":65,"tag":223,"props":561,"children":562},{"style":236},[563],{"type":71,"value":564},"'",{"type":65,"tag":223,"props":566,"children":567},{"style":236},[568],{"type":71,"value":506},{"type":65,"tag":223,"props":570,"children":572},{"style":571},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[573],{"type":71,"value":574}," \u002F\u002F stable — required\n",{"type":65,"tag":223,"props":576,"children":577},{"class":225,"line":270},[578,583,587,592,596,600,605,609,614],{"type":65,"tag":223,"props":579,"children":580},{"style":529},[581],{"type":71,"value":582},"    connection",{"type":65,"tag":223,"props":584,"children":585},{"style":236},[586],{"type":71,"value":550},{"type":65,"tag":223,"props":588,"children":589},{"style":471},[590],{"type":71,"value":591}," fetchServerSentEvents",{"type":65,"tag":223,"props":593,"children":594},{"style":529},[595],{"type":71,"value":532},{"type":65,"tag":223,"props":597,"children":598},{"style":236},[599],{"type":71,"value":564},{"type":65,"tag":223,"props":601,"children":602},{"style":328},[603],{"type":71,"value":604},"\u002Fapi\u002Fchat",{"type":65,"tag":223,"props":606,"children":607},{"style":236},[608],{"type":71,"value":564},{"type":65,"tag":223,"props":610,"children":611},{"style":529},[612],{"type":71,"value":613},")",{"type":65,"tag":223,"props":615,"children":616},{"style":236},[617],{"type":71,"value":254},{"type":65,"tag":223,"props":619,"children":620},{"class":225,"line":283},[621,626,630,635,639],{"type":65,"tag":223,"props":622,"children":623},{"style":529},[624],{"type":71,"value":625},"    persistence",{"type":65,"tag":223,"props":627,"children":628},{"style":236},[629],{"type":71,"value":550},{"type":65,"tag":223,"props":631,"children":632},{"style":471},[633],{"type":71,"value":634}," localStoragePersistence",{"type":65,"tag":223,"props":636,"children":637},{"style":529},[638],{"type":71,"value":479},{"type":65,"tag":223,"props":640,"children":641},{"style":236},[642],{"type":71,"value":254},{"type":65,"tag":223,"props":644,"children":645},{"class":225,"line":296},[646,651],{"type":65,"tag":223,"props":647,"children":648},{"style":236},[649],{"type":71,"value":650},"  }",{"type":65,"tag":223,"props":652,"children":653},{"style":529},[654],{"type":71,"value":655},")\n",{"type":65,"tag":223,"props":657,"children":658},{"class":225,"line":309},[659],{"type":65,"tag":223,"props":660,"children":661},{"style":571},[662],{"type":71,"value":663},"  \u002F\u002F ...\n",{"type":65,"tag":223,"props":665,"children":667},{"class":225,"line":666},8,[668],{"type":65,"tag":223,"props":669,"children":670},{"style":236},[671],{"type":71,"value":672},"}\n",{"type":65,"tag":78,"props":674,"children":675},{},[676,678,684],{"type":71,"value":677},"Bare adapter ≡ full transcript + resume pointer. Browser owns history; server\n(if any) mirrors when you post non-empty ",{"type":65,"tag":84,"props":679,"children":681},{"className":680},[],[682],{"type":71,"value":683},"messages",{"type":71,"value":685},".",{"type":65,"tag":78,"props":687,"children":688},{},[689],{"type":71,"value":690},"Best for: SPA, offline-first, single device, moderate conversation size.",{"type":65,"tag":337,"props":692,"children":694},{"id":693},"mode-b-server-authoritative-persistence-true",[695,697,703],{"type":71,"value":696},"Mode B — server-authoritative (",{"type":65,"tag":84,"props":698,"children":700},{"className":699},[],[701],{"type":71,"value":702},"persistence: true",{"type":71,"value":613},{"type":65,"tag":212,"props":705,"children":707},{"className":214,"code":706,"language":216,"meta":217,"style":217},"function Chat({ threadId }: { threadId: string }) {\n  const { messages, sendMessage } = useChat({\n    threadId,\n    connection: fetchServerSentEvents('\u002Fapi\u002Fchat'),\n    persistence: true,\n  })\n  \u002F\u002F ...\n}\n",[708],{"type":65,"tag":84,"props":709,"children":710},{"__ignoreMap":217},[711,765,808,819,858,879,890,897],{"type":65,"tag":223,"props":712,"children":713},{"class":225,"line":226},[714,718,722,727,733,738,742,746,750,756,761],{"type":65,"tag":223,"props":715,"children":716},{"style":465},[717],{"type":71,"value":468},{"type":65,"tag":223,"props":719,"children":720},{"style":471},[721],{"type":71,"value":474},{"type":65,"tag":223,"props":723,"children":724},{"style":236},[725],{"type":71,"value":726},"({",{"type":65,"tag":223,"props":728,"children":730},{"style":729},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[731],{"type":71,"value":732}," threadId",{"type":65,"tag":223,"props":734,"children":735},{"style":236},[736],{"type":71,"value":737}," }:",{"type":65,"tag":223,"props":739,"children":740},{"style":236},[741],{"type":71,"value":496},{"type":65,"tag":223,"props":743,"children":744},{"style":529},[745],{"type":71,"value":732},{"type":65,"tag":223,"props":747,"children":748},{"style":236},[749],{"type":71,"value":550},{"type":65,"tag":223,"props":751,"children":753},{"style":752},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[754],{"type":71,"value":755}," string",{"type":65,"tag":223,"props":757,"children":758},{"style":236},[759],{"type":71,"value":760}," })",{"type":65,"tag":223,"props":762,"children":763},{"style":236},[764],{"type":71,"value":239},{"type":65,"tag":223,"props":766,"children":767},{"class":225,"line":242},[768,772,776,780,784,788,792,796,800,804],{"type":65,"tag":223,"props":769,"children":770},{"style":465},[771],{"type":71,"value":491},{"type":65,"tag":223,"props":773,"children":774},{"style":236},[775],{"type":71,"value":496},{"type":65,"tag":223,"props":777,"children":778},{"style":246},[779],{"type":71,"value":501},{"type":65,"tag":223,"props":781,"children":782},{"style":236},[783],{"type":71,"value":506},{"type":65,"tag":223,"props":785,"children":786},{"style":246},[787],{"type":71,"value":511},{"type":65,"tag":223,"props":789,"children":790},{"style":236},[791],{"type":71,"value":516},{"type":65,"tag":223,"props":793,"children":794},{"style":236},[795],{"type":71,"value":521},{"type":65,"tag":223,"props":797,"children":798},{"style":471},[799],{"type":71,"value":526},{"type":65,"tag":223,"props":801,"children":802},{"style":529},[803],{"type":71,"value":532},{"type":65,"tag":223,"props":805,"children":806},{"style":236},[807],{"type":71,"value":537},{"type":65,"tag":223,"props":809,"children":810},{"class":225,"line":257},[811,815],{"type":65,"tag":223,"props":812,"children":813},{"style":246},[814],{"type":71,"value":545},{"type":65,"tag":223,"props":816,"children":817},{"style":236},[818],{"type":71,"value":254},{"type":65,"tag":223,"props":820,"children":821},{"class":225,"line":270},[822,826,830,834,838,842,846,850,854],{"type":65,"tag":223,"props":823,"children":824},{"style":529},[825],{"type":71,"value":582},{"type":65,"tag":223,"props":827,"children":828},{"style":236},[829],{"type":71,"value":550},{"type":65,"tag":223,"props":831,"children":832},{"style":471},[833],{"type":71,"value":591},{"type":65,"tag":223,"props":835,"children":836},{"style":529},[837],{"type":71,"value":532},{"type":65,"tag":223,"props":839,"children":840},{"style":236},[841],{"type":71,"value":564},{"type":65,"tag":223,"props":843,"children":844},{"style":328},[845],{"type":71,"value":604},{"type":65,"tag":223,"props":847,"children":848},{"style":236},[849],{"type":71,"value":564},{"type":65,"tag":223,"props":851,"children":852},{"style":529},[853],{"type":71,"value":613},{"type":65,"tag":223,"props":855,"children":856},{"style":236},[857],{"type":71,"value":254},{"type":65,"tag":223,"props":859,"children":860},{"class":225,"line":283},[861,865,869,875],{"type":65,"tag":223,"props":862,"children":863},{"style":529},[864],{"type":71,"value":625},{"type":65,"tag":223,"props":866,"children":867},{"style":236},[868],{"type":71,"value":550},{"type":65,"tag":223,"props":870,"children":872},{"style":871},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[873],{"type":71,"value":874}," true",{"type":65,"tag":223,"props":876,"children":877},{"style":236},[878],{"type":71,"value":254},{"type":65,"tag":223,"props":880,"children":881},{"class":225,"line":296},[882,886],{"type":65,"tag":223,"props":883,"children":884},{"style":236},[885],{"type":71,"value":650},{"type":65,"tag":223,"props":887,"children":888},{"style":529},[889],{"type":71,"value":655},{"type":65,"tag":223,"props":891,"children":892},{"class":225,"line":309},[893],{"type":65,"tag":223,"props":894,"children":895},{"style":571},[896],{"type":71,"value":663},{"type":65,"tag":223,"props":898,"children":899},{"class":225,"line":666},[900],{"type":65,"tag":223,"props":901,"children":902},{"style":236},[903],{"type":71,"value":672},{"type":65,"tag":78,"props":905,"children":906},{},[907],{"type":71,"value":908},"Nothing is cached client-side: no transcript, no resume pointer.",{"type":65,"tag":78,"props":910,"children":911},{},[912,914,919,921,925,927,932,934,940,942,948],{"type":71,"value":913},"On mount, ",{"type":65,"tag":84,"props":915,"children":917},{"className":916},[],[918],{"type":71,"value":97},{"type":71,"value":920}," hydrates the thread from the ",{"type":65,"tag":104,"props":922,"children":923},{},[924],{"type":71,"value":138},{"type":71,"value":926}," by ",{"type":65,"tag":84,"props":928,"children":930},{"className":929},[],[931],{"type":71,"value":189},{"type":71,"value":933},"\n(paint + tail active run). Same path for another device. Pair with server\n",{"type":65,"tag":84,"props":935,"children":937},{"className":936},[],[938],{"type":71,"value":939},"withPersistence",{"type":71,"value":941}," + a hydrate route (",{"type":65,"tag":84,"props":943,"children":945},{"className":944},[],[946],{"type":71,"value":947},"reconstructChat",{"type":71,"value":949}," or equivalent).",{"type":65,"tag":78,"props":951,"children":952},{},[953],{"type":71,"value":954},"Best for: large transcripts, multi-device, compliance (no message bodies in\nbrowser storage).",{"type":65,"tag":337,"props":956,"children":958},{"id":957},"what-a-reload-restores",[959],{"type":71,"value":960},"What a reload restores",{"type":65,"tag":962,"props":963,"children":964},"ol",{},[965,976,986],{"type":65,"tag":966,"props":967,"children":968},"li",{},[969,974],{"type":65,"tag":104,"props":970,"children":971},{},[972],{"type":71,"value":973},"Finished run",{"type":71,"value":975}," — transcript from the adapter (mode A) or server (mode B).",{"type":65,"tag":966,"props":977,"children":978},{},[979,984],{"type":65,"tag":104,"props":980,"children":981},{},[982],{"type":71,"value":983},"Paused on interrupt",{"type":71,"value":985}," — approval UI restored (from the adapter in mode A,\nthe server hydrate in mode B).",{"type":65,"tag":966,"props":987,"children":988},{},[989,994,996,1001,1003,1009,1011,1017],{"type":65,"tag":104,"props":990,"children":991},{},[992],{"type":71,"value":993},"Still streaming",{"type":71,"value":995}," — needs ",{"type":65,"tag":104,"props":997,"children":998},{},[999],{"type":71,"value":1000},"delivery durability",{"type":71,"value":1002}," on the route\n(",{"type":65,"tag":84,"props":1004,"children":1006},{"className":1005},[],[1007],{"type":71,"value":1008},"toServerSentEventsResponse(stream, { durability: … })",{"type":71,"value":1010},") so the client can\n",{"type":65,"tag":84,"props":1012,"children":1014},{"className":1013},[],[1015],{"type":71,"value":1016},"joinRun",{"type":71,"value":1018}," and finish the reply. Persistence alone is not enough.",{"type":65,"tag":337,"props":1020,"children":1022},{"id":1021},"stable-threadid-is-the-identity",[1023,1025,1030],{"type":71,"value":1024},"Stable ",{"type":65,"tag":84,"props":1026,"children":1028},{"className":1027},[],[1029],{"type":71,"value":189},{"type":71,"value":1031}," is the identity",{"type":65,"tag":78,"props":1033,"children":1034},{},[1035,1037,1042,1044,1057,1059,1065,1067,1072],{"type":71,"value":1036},"Persistence keys on ",{"type":65,"tag":84,"props":1038,"children":1040},{"className":1039},[],[1041],{"type":71,"value":189},{"type":71,"value":1043},". The hooks have ",{"type":65,"tag":104,"props":1045,"children":1046},{},[1047,1049,1055],{"type":71,"value":1048},"no separate ",{"type":65,"tag":84,"props":1050,"children":1052},{"className":1051},[],[1053],{"type":71,"value":1054},"id",{"type":71,"value":1056}," option",{"type":71,"value":1058}," — a\nchat's identity ",{"type":65,"tag":1060,"props":1061,"children":1062},"em",{},[1063],{"type":71,"value":1064},"is",{"type":71,"value":1066}," its ",{"type":65,"tag":84,"props":1068,"children":1070},{"className":1069},[],[1071],{"type":71,"value":189},{"type":71,"value":1073},". Without a stable one, each load is a new\nchat. Generate it server-side or from a route param the user owns; do not\nrandomize per mount.",{"type":65,"tag":337,"props":1075,"children":1077},{"id":1076},"common-mistakes",[1078],{"type":71,"value":1079},"Common mistakes",{"type":65,"tag":1081,"props":1082,"children":1084},"h3",{"id":1083},"high-no-threadid",[1085,1087],{"type":71,"value":1086},"HIGH: No ",{"type":65,"tag":84,"props":1088,"children":1090},{"className":1089},[],[1091],{"type":71,"value":189},{"type":65,"tag":78,"props":1093,"children":1094},{},[1095],{"type":71,"value":1096},"Record cannot be found after reload.",{"type":65,"tag":1081,"props":1098,"children":1100},{"id":1099},"high-passing-id-to-usechat",[1101,1103,1108,1110],{"type":71,"value":1102},"HIGH: Passing ",{"type":65,"tag":84,"props":1104,"children":1106},{"className":1105},[],[1107],{"type":71,"value":1054},{"type":71,"value":1109}," to ",{"type":65,"tag":84,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":71,"value":97},{"type":65,"tag":78,"props":1116,"children":1117},{},[1118,1120,1125,1127,1132,1134,1139],{"type":71,"value":1119},"Removed — ",{"type":65,"tag":84,"props":1121,"children":1123},{"className":1122},[],[1124],{"type":71,"value":189},{"type":71,"value":1126}," is the identity. (",{"type":65,"tag":84,"props":1128,"children":1130},{"className":1129},[],[1131],{"type":71,"value":167},{"type":71,"value":1133}," still accepts ",{"type":65,"tag":84,"props":1135,"children":1137},{"className":1136},[],[1138],{"type":71,"value":1054},{"type":71,"value":1140}," directly\nas a lower-level escape hatch for keying storage separately from the wire\nthread; the framework hooks do not.)",{"type":65,"tag":1081,"props":1142,"children":1144},{"id":1143},"high-persistence-true-without-server-history",[1145,1147,1152],{"type":71,"value":1146},"HIGH: ",{"type":65,"tag":84,"props":1148,"children":1150},{"className":1149},[],[1151],{"type":71,"value":702},{"type":71,"value":1153}," without server history",{"type":65,"tag":78,"props":1155,"children":1156},{},[1157,1159,1164],{"type":71,"value":1158},"Empty chat after reload unless the server can reconstruct by ",{"type":65,"tag":84,"props":1160,"children":1162},{"className":1161},[],[1163],{"type":71,"value":189},{"type":71,"value":685},{"type":65,"tag":1081,"props":1166,"children":1168},{"id":1167},"medium-huge-transcripts-in-localstorage",[1169,1171],{"type":71,"value":1170},"MEDIUM: Huge transcripts in ",{"type":65,"tag":84,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":71,"value":1176},"localStorage",{"type":65,"tag":78,"props":1178,"children":1179},{},[1180,1182,1187],{"type":71,"value":1181},"Quota and main-thread cost. Prefer ",{"type":65,"tag":84,"props":1183,"children":1185},{"className":1184},[],[1186],{"type":71,"value":702},{"type":71,"value":1188}," + server store, or\nIndexedDB with care.",{"type":65,"tag":1081,"props":1190,"children":1192},{"id":1191},"medium-expecting-multi-device-sync-from-client-storage-alone",[1193],{"type":71,"value":1194},"MEDIUM: Expecting multi-device sync from client storage alone",{"type":65,"tag":78,"props":1196,"children":1197},{},[1198,1203],{"type":65,"tag":84,"props":1199,"children":1201},{"className":1200},[],[1202],{"type":71,"value":1176},{"type":71,"value":1204}," is per-browser. Use server persistence for multi-device.",{"type":65,"tag":337,"props":1206,"children":1208},{"id":1207},"cross-references",[1209],{"type":71,"value":1210},"Cross-references",{"type":65,"tag":1212,"props":1213,"children":1214},"ul",{},[1215,1231,1247],{"type":65,"tag":966,"props":1216,"children":1217},{},[1218,1222,1224,1229],{"type":65,"tag":104,"props":1219,"children":1220},{},[1221],{"type":71,"value":154},{"type":71,"value":1223}," (",{"type":65,"tag":84,"props":1225,"children":1227},{"className":1226},[],[1228],{"type":71,"value":146},{"type":71,"value":1230},") — authoritative server half",{"type":65,"tag":966,"props":1232,"children":1233},{},[1234,1238,1240,1245],{"type":65,"tag":104,"props":1235,"children":1236},{},[1237],{"type":71,"value":89},{"type":71,"value":1239}," — ",{"type":65,"tag":84,"props":1241,"children":1243},{"className":1242},[],[1244],{"type":71,"value":97},{"type":71,"value":1246},", resumable connections",{"type":65,"tag":966,"props":1248,"children":1249},{},[1250],{"type":71,"value":1251},"Resumable streams docs — mid-stream rejoin",{"type":65,"tag":1253,"props":1254,"children":1255},"style",{},[1256],{"type":71,"value":1257},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1259,"total":1352},[1260,1278,1292,1307,1320,1331,1338],{"slug":1261,"name":1261,"fn":1262,"description":1263,"org":1264,"tags":1265,"stars":24,"repoUrl":25,"updatedAt":1277},"ai-code-mode","execute sandboxed TypeScript code with LLMs","LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createCloudflareIsolateDriver), codeModeWithSkills() for persistent skill libraries, trust strategies, skill storage (FileSystem, LocalStorage, InMemory, Mongo), client-side execution progress via code_mode:* custom events in useChat.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1266,1268,1271,1274,1275],{"name":1267,"slug":31,"type":16},"AI SDK",{"name":1269,"slug":1270,"type":16},"Code Execution","code-execution",{"name":1272,"slug":1273,"type":16},"Sandboxing","sandboxing",{"name":10,"slug":9,"type":16},{"name":1276,"slug":45,"type":16},"TypeScript","2026-07-16T06:04:13.597905",{"slug":1279,"name":1279,"fn":1280,"description":1281,"org":1282,"tags":1283,"stars":24,"repoUrl":25,"updatedAt":1291},"ai-core","configure TanStack AI agent features","Entry point for TanStack AI skills. Routes to chat-experience, tool-calling, media-generation, structured-outputs, adapter-configuration, ag-ui-protocol, middleware, locks, custom-backend-integration, and debug-logging, plus the skills shipped by companion packages (@tanstack\u002Fai-persistence, @tanstack\u002Fai-code-mode). Use chat() not streamText(), openaiText() not createOpenAI(), toServerSentEventsResponse() not manual SSE, middleware hooks not onEnd callbacks.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1284,1287,1288],{"name":1285,"slug":1286,"type":16},"Agents","agents",{"name":14,"slug":15,"type":16},{"name":1289,"slug":1290,"type":16},"Middleware","middleware","2026-07-30T05:26:10.404565",{"slug":1293,"name":1294,"fn":1295,"description":1296,"org":1297,"tags":1298,"stars":24,"repoUrl":25,"updatedAt":1306},"ai-coreadapter-configuration","ai-core\u002Fadapter-configuration","configure AI provider adapters","Provider adapter selection and configuration: openaiText, anthropicText, geminiText, ollamaText, grokText, groqText, openRouterText, bedrockText, openaiCompatible. Per-model type safety with modelOptions, reasoning\u002Fthinking configuration, runtime adapter switching, extendAdapter() for custom models, createModel(). Generic OpenAI-compatible providers (DeepSeek, Together, Fireworks, etc.) via openaiCompatible({ baseURL, apiKey, models }) from @tanstack\u002Fai-openai\u002Fcompatible. API key env vars: OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY\u002FGEMINI_API_KEY, XAI_API_KEY, GROQ_API_KEY, OPENROUTER_API_KEY, OLLAMA_HOST, BEDROCK_API_KEY (or AWS_BEARER_TOKEN_BEDROCK).\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1299,1300,1303,1305],{"name":1267,"slug":31,"type":16},{"name":1301,"slug":1302,"type":16},"Configuration","configuration",{"name":1304,"slug":37,"type":16},"LLM",{"name":10,"slug":9,"type":16},"2026-07-16T06:04:17.82075",{"slug":1308,"name":1309,"fn":1310,"description":1311,"org":1312,"tags":1313,"stars":24,"repoUrl":25,"updatedAt":1319},"ai-coreag-ui-protocol","ai-core\u002Fag-ui-protocol","implement TanStack AI streaming protocol","Server-side AG-UI streaming protocol implementation: StreamChunk event types (RUN_STARTED, TEXT_MESSAGE_START\u002FCONTENT\u002FEND, TOOL_CALL_START\u002FARGS\u002FEND, RUN_FINISHED, RUN_ERROR, STEP_STARTED\u002FSTEP_FINISHED, STATE_SNAPSHOT\u002FDELTA, CUSTOM), toServerSentEventsStream() for SSE format, toHttpStream() for NDJSON format. For backends serving AG-UI events without client packages.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1314,1317,1318],{"name":1315,"slug":1316,"type":16},"API Development","api-development",{"name":1304,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-16T06:04:10.093367",{"slug":1321,"name":89,"fn":1322,"description":1323,"org":1324,"tags":1325,"stars":24,"repoUrl":25,"updatedAt":1330},"ai-corechat-experience","implement chat experiences with TanStack AI","End-to-end chat implementation: server endpoint with chat() and toServerSentEventsResponse(), client-side useChat hook with fetchServerSentEvents(), message rendering with UIMessage parts, multimodal content, thinking\u002Freasoning display. Covers streaming states, connection adapters, and message format conversions. NOT Vercel AI SDK — uses chat() not streamText().\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1326,1327,1328,1329],{"name":1315,"slug":1316,"type":16},{"name":22,"slug":23,"type":16},{"name":1304,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:11.505241",{"slug":4,"name":5,"fn":6,"description":7,"org":1332,"tags":1333,"stars":24,"repoUrl":25,"updatedAt":26},{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1334,1335,1336,1337],{"name":14,"slug":15,"type":16},{"name":22,"slug":23,"type":16},{"name":18,"slug":19,"type":16},{"name":10,"slug":9,"type":16},{"slug":1339,"name":1340,"fn":1341,"description":1342,"org":1343,"tags":1344,"stars":24,"repoUrl":25,"updatedAt":1351},"ai-corecustom-backend-integration","ai-core\u002Fcustom-backend-integration","integrate custom backends with TanStack AI","Connect useChat to a non-TanStack-AI backend through custom connection adapters. ConnectConnectionAdapter (single async iterable) vs SubscribeConnectionAdapter (separate subscribe\u002Fsend). Customize fetchServerSentEvents() and fetchHttpStream() with auth headers, custom URLs, and request options. Import from framework package, not @tanstack\u002Fai-client.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1345,1346,1347,1350],{"name":14,"slug":15,"type":16},{"name":1315,"slug":1316,"type":16},{"name":1348,"slug":1349,"type":16},"Backend","backend",{"name":10,"slug":9,"type":16},"2026-07-17T06:06:39.855351",27,{"items":1354,"total":1494},[1355,1369,1381,1393,1408,1420,1430,1440,1453,1463,1474,1484],{"slug":1356,"name":1356,"fn":1357,"description":1358,"org":1359,"tags":1360,"stars":1366,"repoUrl":1367,"updatedAt":1368},"aggregation","perform data aggregation in TanStack Table","Aggregate TanStack Table columns independently of grouping, including grand totals, caller-selected row totals, multiple keyed aggregations, custom context-based definitions, grouped merges, manual values, and worker constraints.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1361,1364,1365],{"name":1362,"slug":1363,"type":16},"Data Analysis","data-analysis",{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},28175,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Ftable","2026-07-30T05:25:59.429787",{"slug":1370,"name":1370,"fn":1371,"description":1372,"org":1373,"tags":1374,"stars":1366,"repoUrl":1367,"updatedAt":1380},"api-not-found","diagnose TanStack Table API errors","Diagnose missing TanStack Table v9 exports, options, state slices, and instance methods. Load before inventing an API when code sees a type error, undefined feature method, absent object key, adapter mismatch, or v8-shaped example.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1375,1378,1379],{"name":1376,"slug":1377,"type":16},"Debugging","debugging",{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:05.418735",{"slug":1382,"name":1382,"fn":1383,"description":1384,"org":1385,"tags":1386,"stars":1366,"repoUrl":1367,"updatedAt":1392},"cell-selection","select rectangular cell ranges in tables","Select rectangular cell ranges with cellSelectionFeature: two-corner range state keyed by row and column id, mousedown\u002Fmouseenter handlers, selection edges, render-order resolution under pinning, and autoResetCellSelection. Load when ranges widen unexpectedly after sorting or column reordering, when a drag re-renders the whole table, or when building copy-to-clipboard from a selection.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1387,1388,1389],{"name":1362,"slug":1363,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"UI Components","ui-components","2026-07-30T05:25:38.403427",{"slug":1394,"name":1394,"fn":1395,"description":1396,"org":1397,"tags":1398,"stars":1366,"repoUrl":1367,"updatedAt":1407},"client-vs-server","manage TanStack Table data pipelines","Choose client or server ownership for filtering, grouping, sorting, expanding, and pagination in TanStack Table v9. Load for manual* flags, mixed pipelines, server counts, or deciding which dataset each row-model stage receives.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1399,1402,1403,1406],{"name":1400,"slug":1401,"type":16},"Data Pipeline","data-pipeline",{"name":22,"slug":23,"type":16},{"name":1404,"slug":1405,"type":16},"Performance","performance",{"name":10,"slug":9,"type":16},"2026-07-30T05:25:45.400104",{"slug":1409,"name":1409,"fn":1410,"description":1411,"org":1412,"tags":1413,"stars":1366,"repoUrl":1367,"updatedAt":1419},"column-faceting","build faceted filter UIs","Build faceted filter UIs with columnFacetingFeature, facetedRowModel, facetedUniqueValues, and facetedMinMaxValues. Load for facet counts, numeric ranges, own-filter exclusion, or server-page facet completeness.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1414,1417,1418],{"name":1415,"slug":1416,"type":16},"Data Visualization","data-visualization",{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:41.397257",{"slug":1421,"name":1421,"fn":1422,"description":1423,"org":1424,"tags":1425,"stars":1366,"repoUrl":1367,"updatedAt":1429},"column-filtering","implement column filtering in TanStack Table","Filter columns with columnFilteringFeature, filteredRowModel, filterFns, filterMeta, nested-row direction, and manualFiltering. Load for accessor compatibility, controlled filter updaters, fuzzy metadata, or client\u002Fserver ownership.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1426,1427,1428],{"name":1362,"slug":1363,"type":16},{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:53.391632",{"slug":1431,"name":1431,"fn":1432,"description":1433,"org":1434,"tags":1435,"stars":1366,"repoUrl":1367,"updatedAt":1439},"column-ordering","manage TanStack Table column ordering","Control TanStack Table v9 leaf columnOrder with stable IDs while accounting for pinning regions, visibility, and groupedColumnMode precedence. Load for drag-and-drop columns or rendered order that differs from state.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1436,1437,1438],{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:26:03.37801",{"slug":1441,"name":1441,"fn":1442,"description":1443,"org":1444,"tags":1445,"stars":1366,"repoUrl":1367,"updatedAt":1452},"column-pinning","configure column pinning in TanStack Table","Pin columns into logical start, center, and end regions with columnPinningFeature and renderer-owned sticky CSS. Load for RTL offsets, z-index, backgrounds, overflow, widths, gaps, or overlaps.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1446,1449,1450,1451],{"name":1447,"slug":1448,"type":16},"CSS","css",{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:25:55.377366",{"slug":1454,"name":1454,"fn":1455,"description":1456,"org":1457,"tags":1458,"stars":1366,"repoUrl":1367,"updatedAt":1462},"column-resizing","implement column resizing in TanStack Table","Wire columnResizingFeature, header.getResizeHandler, resize mode and direction, pointer or touch events, and performant CSS-variable updates. Load when resize state changes but widths do not, or large tables resize slowly.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1459,1460,1461],{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:25:51.400011",{"slug":1464,"name":1464,"fn":1465,"description":1466,"org":1467,"tags":1468,"stars":1366,"repoUrl":1367,"updatedAt":1473},"column-sizing","configure column sizing in TanStack Table","Use columnSizingFeature numeric size, minSize, maxSize, getSize, getStart, getAfter, and total-size APIs in table, grid, or flex CSS. Load for auto or percentage misconceptions and sizing\u002Fpinning layout mismatch.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1469,1470,1471,1472],{"name":1447,"slug":1448,"type":16},{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:25:48.703799",{"slug":1475,"name":1475,"fn":1476,"description":1477,"org":1478,"tags":1479,"stars":1366,"repoUrl":1367,"updatedAt":1483},"column-visibility","manage column visibility in TanStack Table","Hide columns with columnVisibilityFeature while rendering visibility-aware header, column, and cell collections. Load when hidden columns remain in the DOM, false-versus-absent state is confused, or enableHiding is misunderstood.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1480,1481,1482],{"name":22,"slug":23,"type":16},{"name":10,"slug":9,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:25:47.367943",{"slug":1485,"name":1485,"fn":1486,"description":1487,"org":1488,"tags":1489,"stars":1366,"repoUrl":1367,"updatedAt":1493},"core","build data grids with TanStack Table","Use TanStack Table v9 as a headless data-grid state and row-processing engine. Load for first-table architecture, stable data and columns, row numbering with getDisplayIndex, semantic rendering, framework adapter choice, or deciding what Table owns versus the renderer.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[1490,1491,1492],{"name":1362,"slug":1363,"type":16},{"name":22,"slug":23,"type":16},{"name":1390,"slug":1391,"type":16},"2026-07-30T05:25:52.366295",125]