@hitch42/applet 0.1.1-beta.7 → 0.1.1-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/_internal/client.js +120 -11
  2. package/dist/_internal/log-context.d.ts +34 -0
  3. package/dist/_internal/log-context.js +2 -0
  4. package/dist/_internal/server.d.ts +14 -1
  5. package/dist/_internal/server.js +122 -118
  6. package/dist/applet.js +22 -11
  7. package/dist/build-Bh_S5BUv.js +2 -0
  8. package/dist/{build-DauirTcY.js → build-CEfFoIZZ.js} +1 -1
  9. package/dist/{ci-gPrwo6C0.js → ci-BKw14X2h.js} +14 -13
  10. package/dist/client.d.ts +3 -3
  11. package/dist/{contract-DB9QQhD9.d.ts → contract-CsUpTBe0.d.ts} +1 -1
  12. package/dist/{deploy-CqrtNJ1x.js → deploy-wGYjwXrx.js} +139 -88
  13. package/dist/email-DBTVhNB_.js +62 -0
  14. package/dist/{generate-BIifT6PK.js → generate-BEIYs17x.js} +70 -32
  15. package/dist/generate-Dox-OYt6.js +2 -0
  16. package/dist/headers-DkNr9MLJ.js +17 -0
  17. package/dist/index.d.ts +122 -10
  18. package/dist/index.js +142 -26
  19. package/dist/{init-Wu6XmyVc.js → init-6oGPM46R.js} +15 -17
  20. package/dist/{load-config-BknBkdRs.js → load-config-xEdTXs0y.js} +2 -2
  21. package/dist/log-context-zu8U9Sjm.js +73 -0
  22. package/dist/{login-iT9MRuaw.js → login-CUx3TmFQ.js} +1 -1
  23. package/dist/{logs-B-qZGXSK.js → logs-DSjuEN0Q.js} +20 -22
  24. package/dist/{manifest-C489nYUy.d.ts → manifest-C6_F4bL8.d.ts} +7 -0
  25. package/dist/{manifest-Bd04cWhu.js → manifest-CJSL9GuC.js} +22 -3
  26. package/dist/me-BW7Paary.js +32 -0
  27. package/dist/{project-C_rtpjp8.js → project-BRZGd6xq.js} +202 -20
  28. package/dist/prompt-ChS-grYO.js +29 -0
  29. package/dist/query-cache-CXmAyLv3.js +82 -0
  30. package/dist/react.d.ts +3 -2
  31. package/dist/react.js +98 -80
  32. package/dist/schedules-C8_Svr4h.js +42 -0
  33. package/dist/server.d.ts +9 -4
  34. package/dist/server.js +29 -8
  35. package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
  36. package/dist/telephony.d.ts +97 -0
  37. package/dist/telephony.js +726 -0
  38. package/dist/{upload-YbRKEqR6.d.ts → upload-DKZzz5kW.d.ts} +6 -6
  39. package/dist/{variables-DcwMeIau.js → variables-DT5RyHdH.js} +14 -39
  40. package/dist/vite.d.ts +3 -60
  41. package/dist/vite.js +497 -27
  42. package/dist/workflow-engine-BOTzURKM.js +111 -0
  43. package/dist/{workspace-B6lenAS5.js → workspace-D0dnnlxL.js} +37 -39
  44. package/package.json +18 -5
  45. package/scaffold/.agents/skills/hitch-applets/SKILL.md +50 -18
  46. package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
  47. package/scaffold/.agents/skills/hitch-applets/references/files.md +3 -3
  48. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +12 -2
  49. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
  50. package/scaffold/.agents/skills/hitch-applets/references/performance.md +1 -1
  51. package/scaffold/.agents/skills/hitch-applets/references/records.md +27 -4
  52. package/scaffold/.agents/skills/hitch-applets/references/schedules.md +7 -2
  53. package/scaffold/.agents/skills/hitch-applets/references/server.md +0 -3
  54. package/scaffold/.agents/skills/hitch-applets/references/workflows.md +11 -3
  55. package/scaffold/.agents/skills/hitch-cli/SKILL.md +20 -20
  56. package/scaffold/.agents/skills/hitch-data/SKILL.md +3 -2
  57. package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
  58. package/scaffold/.agents/skills/hitch-data/references/limits.md +23 -23
  59. package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
  60. package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
  61. package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  62. package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  63. package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  64. package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  65. package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  66. package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
  67. package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
  68. package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
  69. package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
  70. package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
  71. package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
  72. package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
  73. package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
  74. package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
  75. package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  76. package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  77. package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  78. package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  79. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
  80. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  81. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
  82. package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  83. package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  84. package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  85. package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  86. package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  87. package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  88. package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  89. package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  90. package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  91. package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  92. package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  93. package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  94. package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  95. package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  96. package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  97. package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
  98. package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
  99. package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  100. package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
  101. package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  102. package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  103. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  104. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  105. package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  106. package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  107. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  108. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  109. package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  110. package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  111. package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  112. package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  113. package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  114. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  115. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  116. package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
  117. package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
  118. package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
  119. package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
  120. package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
  121. package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
  122. package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
  123. package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
  124. package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
  125. package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
  126. package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
  127. package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
  128. package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
  129. package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
  130. package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
  131. package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
  132. package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
  133. package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
  134. package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
  135. package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
  136. package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
  137. package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
  138. package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
  139. package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
  140. package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
  141. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
  142. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
  143. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
  144. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
  145. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
  146. package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
  147. package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
  148. package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
  149. package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
  150. package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
  151. package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
  152. package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
  153. package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
  154. package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
  155. package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
  156. package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
  157. package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
  158. package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
  159. package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
  160. package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
  161. package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
  162. package/scaffold/.github/workflows/hitch.yml +1 -1
  163. package/scaffold/AGENTS.md +2 -2
  164. package/scaffold/applet/src/client/components/ui/alert.tsx +1 -1
  165. package/scaffold/applet/src/client/components/ui/button.tsx +1 -1
  166. package/scaffold/applet/src/client/components/ui/checkbox.tsx +1 -1
  167. package/scaffold/applet/src/client/components/ui/dialog.tsx +2 -2
  168. package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +2 -2
  169. package/scaffold/applet/src/client/components/ui/input-group.tsx +2 -2
  170. package/scaffold/applet/src/client/components/ui/select.tsx +2 -2
  171. package/scaffold/applet/src/client/components/ui/sheet.tsx +2 -2
  172. package/scaffold/applet/src/client/components/ui/spinner.tsx +2 -1
  173. package/scaffold/applet/src/client/components/ui/tabs.tsx +1 -1
  174. package/scaffold/applet/src/client/lib/utils.ts +1 -6
  175. package/scaffold/applet/src/client/styles/globals.css +2 -0
  176. package/dist/build-DhNDp7ji.js +0 -2
  177. package/dist/generate-DSk8ihsC.js +0 -2
@@ -0,0 +1,412 @@
1
+ ---
2
+ name: router-query
3
+ description: >-
4
+ Integrating TanStack Router with TanStack Query: queryClient
5
+ in router context, ensureQueryData/prefetchQuery in loaders,
6
+ useSuspenseQuery in components, defaultPreloadStaleTime: 0,
7
+ setupRouterSsrQueryIntegration for SSR dehydration/hydration
8
+ and streaming, per-request QueryClient isolation.
9
+ metadata:
10
+ type: composition
11
+ library: tanstack-router
12
+ library_version: "1.166.2"
13
+ requires:
14
+ - router-core
15
+ - router-core/data-loading
16
+ - react-router
17
+ sources:
18
+ - TanStack/router:docs/router/guide/external-data-loading.md
19
+ - TanStack/router:docs/router/integrations/query.md
20
+ ---
21
+
22
+ # TanStack Router + TanStack Query Integration
23
+
24
+ This skill requires familiarity with both TanStack Router and TanStack Query. Read [router-core](../router-core/index.md) and [react-router](../react-router.md) first.
25
+
26
+ This skill covers coordinating TanStack Query as an external data cache with TanStack Router's loader system. The router acts as a **coordinator** — it triggers data fetching during navigation, while Query manages caching, background refetching, and data lifecycle.
27
+
28
+ > **CRITICAL**: Set `defaultPreloadStaleTime: 0` when using TanStack Query. Without this, Router's built-in preload cache (30s default) prevents Query from controlling data freshness.
29
+
30
+ > **CRITICAL**: For SSR, create `QueryClient` inside the `createRouter` factory function. A module-level singleton leaks data between server requests.
31
+
32
+ ## Setup: QueryClient in Router Context
33
+
34
+ ### Basic (Client-Only)
35
+
36
+ ```tsx
37
+ // src/main.tsx
38
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
39
+ import { RouterProvider, createRouter, createRootRouteWithContext } from "@tanstack/react-router";
40
+ import { routeTree } from "./routeTree.gen";
41
+
42
+ // Root route declares that router context includes queryClient
43
+ // (root route file creates it with createRootRouteWithContext — see below)
44
+
45
+ const queryClient = new QueryClient();
46
+
47
+ const router = createRouter({
48
+ routeTree,
49
+ defaultPreloadStaleTime: 0, // Let Query manage caching
50
+ context: { queryClient },
51
+ Wrap: ({ children }) => (
52
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
53
+ ),
54
+ });
55
+
56
+ declare module "@tanstack/react-router" {
57
+ interface Register {
58
+ router: typeof router;
59
+ }
60
+ }
61
+
62
+ function App() {
63
+ return <RouterProvider router={router} />;
64
+ }
65
+ ```
66
+
67
+ ### Root Route with Context
68
+
69
+ ```tsx
70
+ // src/routes/__root.tsx
71
+ import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";
72
+ import type { QueryClient } from "@tanstack/react-query";
73
+
74
+ // Double parentheses: factory pattern
75
+ export const Route = createRootRouteWithContext<{
76
+ queryClient: QueryClient;
77
+ }>()({
78
+ component: () => <Outlet />,
79
+ });
80
+ ```
81
+
82
+ ### SSR-Safe Setup
83
+
84
+ ```tsx
85
+ // src/router.tsx
86
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
87
+ import { createRouter } from "@tanstack/react-router";
88
+ import { routeTree } from "./routeTree.gen";
89
+
90
+ export function createAppRouter() {
91
+ // Fresh QueryClient per request — prevents data leaking between SSR requests
92
+ const queryClient = new QueryClient();
93
+
94
+ return createRouter({
95
+ routeTree,
96
+ defaultPreloadStaleTime: 0,
97
+ context: { queryClient },
98
+ Wrap: ({ children }) => (
99
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
100
+ ),
101
+ });
102
+ }
103
+
104
+ declare module "@tanstack/react-router" {
105
+ interface Register {
106
+ router: ReturnType<typeof createAppRouter>;
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### SSR with `setupRouterSsrQueryIntegration`
112
+
113
+ For automatic SSR dehydration/hydration and streaming:
114
+
115
+ ```bash
116
+ npm install @tanstack/react-router-ssr-query
117
+ ```
118
+
119
+ ```tsx
120
+ // src/router.tsx
121
+ import { QueryClient } from "@tanstack/react-query";
122
+ import { createRouter } from "@tanstack/react-router";
123
+ import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
124
+ import { routeTree } from "./routeTree.gen";
125
+
126
+ export function createAppRouter() {
127
+ const queryClient = new QueryClient();
128
+
129
+ const router = createRouter({
130
+ routeTree,
131
+ defaultPreloadStaleTime: 0,
132
+ context: { queryClient },
133
+ });
134
+
135
+ setupRouterSsrQueryIntegration({
136
+ router,
137
+ queryClient,
138
+ // wrapQueryClient: true (default — wraps with QueryClientProvider)
139
+ // handleRedirects: true (default — handles redirect() from queries)
140
+ });
141
+
142
+ return router;
143
+ }
144
+ ```
145
+
146
+ The integration:
147
+
148
+ - Dehydrates query state on the server and hydrates on the client automatically
149
+ - Streams queries that resolve during server render to the client
150
+ - Handles `redirect()` thrown from queries/mutations
151
+
152
+ ### Manual SSR Dehydration/Hydration (Without SSR Query Package)
153
+
154
+ ```tsx
155
+ // src/router.tsx
156
+ import { QueryClient, dehydrate, hydrate } from "@tanstack/react-query";
157
+ import { QueryClientProvider } from "@tanstack/react-query";
158
+ import { createRouter } from "@tanstack/react-router";
159
+ import { routeTree } from "./routeTree.gen";
160
+
161
+ export function createAppRouter() {
162
+ const queryClient = new QueryClient();
163
+
164
+ return createRouter({
165
+ routeTree,
166
+ defaultPreloadStaleTime: 0,
167
+ context: { queryClient },
168
+ dehydrate: () => ({
169
+ queryClientState: dehydrate(queryClient),
170
+ }),
171
+ hydrate: (dehydrated) => {
172
+ hydrate(queryClient, dehydrated.queryClientState);
173
+ },
174
+ Wrap: ({ children }) => (
175
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
176
+ ),
177
+ });
178
+ }
179
+ ```
180
+
181
+ ## Core Pattern: `ensureQueryData` in Loader + `useSuspenseQuery` in Component
182
+
183
+ This is the recommended pattern. The loader ensures data is in the cache before render (no loading flash). The component subscribes to the cache for updates.
184
+
185
+ ```tsx
186
+ // src/routes/posts.tsx
187
+ import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
188
+ import { createFileRoute } from "@tanstack/react-router";
189
+
190
+ interface Post {
191
+ id: string;
192
+ title: string;
193
+ }
194
+
195
+ const postsQueryOptions = queryOptions({
196
+ queryKey: ["posts"],
197
+ queryFn: (): Promise<Array<Post>> => fetch("/api/posts").then((r) => r.json()),
198
+ });
199
+
200
+ export const Route = createFileRoute("/posts")({
201
+ loader: ({ context }) => {
202
+ // ensureQueryData returns cached data if available, fetches if not in cache
203
+ // To also refetch stale data, pass revalidateIfStale: true
204
+ return context.queryClient.ensureQueryData(postsQueryOptions);
205
+ },
206
+ component: PostsPage,
207
+ });
208
+
209
+ function PostsPage() {
210
+ // useSuspenseQuery subscribes to cache — gets background updates
211
+ const { data: posts } = useSuspenseQuery(postsQueryOptions);
212
+
213
+ return (
214
+ <ul>
215
+ {posts.map((post) => (
216
+ <li key={post.id}>{post.title}</li>
217
+ ))}
218
+ </ul>
219
+ );
220
+ }
221
+ ```
222
+
223
+ ### With Dynamic Params
224
+
225
+ ```tsx
226
+ // src/routes/posts/$postId.tsx
227
+ import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
228
+ import { createFileRoute } from "@tanstack/react-router";
229
+
230
+ interface Post {
231
+ id: string;
232
+ title: string;
233
+ content: string;
234
+ }
235
+
236
+ const postQueryOptions = (postId: string) =>
237
+ queryOptions({
238
+ queryKey: ["posts", postId],
239
+ queryFn: () => fetch(`/api/posts/${postId}`).then((r) => r.json()),
240
+ });
241
+
242
+ export const Route = createFileRoute("/posts/$postId")({
243
+ loader: ({ context, params }) => {
244
+ return context.queryClient.ensureQueryData(postQueryOptions(params.postId));
245
+ },
246
+ component: PostPage,
247
+ });
248
+
249
+ function PostPage() {
250
+ const { postId } = Route.useParams();
251
+ const { data: post } = useSuspenseQuery(postQueryOptions(postId));
252
+
253
+ return <article>{post.title}</article>;
254
+ }
255
+ ```
256
+
257
+ ## Streaming Pattern: `prefetchQuery` (Not Awaited)
258
+
259
+ For non-critical data, start the fetch without blocking navigation:
260
+
261
+ ```tsx
262
+ import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
263
+
264
+ export const Route = createFileRoute("/dashboard")({
265
+ loader: ({ context }) => {
266
+ // Await critical data
267
+ const user = context.queryClient.ensureQueryData(userQueryOptions);
268
+
269
+ // Start non-critical fetch without awaiting — streams during SSR
270
+ context.queryClient.prefetchQuery(analyticsQueryOptions);
271
+
272
+ return user;
273
+ },
274
+ component: Dashboard,
275
+ });
276
+
277
+ function Dashboard() {
278
+ // Critical: suspense (data ready immediately)
279
+ const { data: user } = useSuspenseQuery(userQueryOptions);
280
+
281
+ // Non-critical: regular query (shows loading state)
282
+ const { data: analytics, isLoading } = useQuery(analyticsQueryOptions);
283
+
284
+ return (
285
+ <div>
286
+ <h1>Welcome {user.name}</h1>
287
+ {isLoading ? <Skeleton /> : <AnalyticsChart data={analytics} />}
288
+ </div>
289
+ );
290
+ }
291
+ ```
292
+
293
+ ## Error Handling with `useQueryErrorResetBoundary`
294
+
295
+ ```tsx
296
+ import { useEffect } from "react";
297
+ import { useQueryErrorResetBoundary } from "@tanstack/react-query";
298
+ import { useRouter } from "@tanstack/react-router";
299
+
300
+ export const Route = createFileRoute("/posts")({
301
+ loader: ({ context }) => context.queryClient.ensureQueryData(postsQueryOptions),
302
+ errorComponent: PostsErrorComponent,
303
+ component: PostsPage,
304
+ });
305
+
306
+ function PostsErrorComponent({ error, reset }: { error: unknown; reset: () => void }) {
307
+ const router = useRouter();
308
+ const queryErrorResetBoundary = useQueryErrorResetBoundary();
309
+
310
+ useEffect(() => {
311
+ queryErrorResetBoundary.reset();
312
+ }, [queryErrorResetBoundary]);
313
+
314
+ return (
315
+ <div>
316
+ <p>{error instanceof Error ? error.message : String(error)}</p>
317
+ <button onClick={() => router.invalidate()}>Retry</button>
318
+ </div>
319
+ );
320
+ }
321
+ ```
322
+
323
+ ## Common Mistakes
324
+
325
+ ### 1. HIGH: Not setting `defaultPreloadStaleTime` to 0
326
+
327
+ Router has a built-in preload cache (default `staleTime` for preloads is 30s). This prevents Query from controlling data freshness during preloading.
328
+
329
+ ```tsx
330
+ // WRONG — Router's preload cache serves stale data, Query never refetches
331
+ const router = createRouter({ routeTree });
332
+
333
+ // CORRECT — disable Router's preload cache, let Query manage freshness
334
+ const router = createRouter({
335
+ routeTree,
336
+ defaultPreloadStaleTime: 0,
337
+ });
338
+ ```
339
+
340
+ ### 2. HIGH: Creating QueryClient outside `createRouter` for SSR
341
+
342
+ A module-level singleton `QueryClient` is shared across all server requests, leaking user data between requests.
343
+
344
+ ```tsx
345
+ // WRONG — shared across SSR requests
346
+ const queryClient = new QueryClient();
347
+ export function createAppRouter() {
348
+ return createRouter({
349
+ routeTree,
350
+ context: { queryClient },
351
+ });
352
+ }
353
+
354
+ // CORRECT — new QueryClient per createAppRouter call
355
+ export function createAppRouter() {
356
+ const queryClient = new QueryClient();
357
+ return createRouter({
358
+ routeTree,
359
+ context: { queryClient },
360
+ });
361
+ }
362
+ ```
363
+
364
+ ### 3. MEDIUM: Awaiting `prefetchQuery` in loader blocks rendering
365
+
366
+ `prefetchQuery` is designed to fire-and-forget. Awaiting it blocks the navigation transition until the data resolves, defeating the purpose of streaming.
367
+
368
+ ```tsx
369
+ // WRONG — blocks navigation, no streaming benefit
370
+ loader: async ({ context }) => {
371
+ await context.queryClient.prefetchQuery(analyticsQueryOptions);
372
+ };
373
+
374
+ // CORRECT — fire and forget for streaming
375
+ loader: ({ context }) => {
376
+ context.queryClient.prefetchQuery(analyticsQueryOptions);
377
+ };
378
+
379
+ // If you need to block (critical data), use ensureQueryData instead:
380
+ loader: ({ context }) => {
381
+ return context.queryClient.ensureQueryData(criticalQueryOptions);
382
+ };
383
+ ```
384
+
385
+ ### 4. HIGH: Missing double parentheses on `createRootRouteWithContext`
386
+
387
+ `createRootRouteWithContext<Type>()` is a factory — it returns a function. The second call passes route options.
388
+
389
+ ```tsx
390
+ // WRONG — passing options to the factory, not the returned function
391
+ const rootRoute = createRootRouteWithContext<{ queryClient: QueryClient }>({
392
+ component: RootComponent,
393
+ });
394
+
395
+ // CORRECT — double call: factory()({options})
396
+ const rootRoute = createRootRouteWithContext<{ queryClient: QueryClient }>()({
397
+ component: RootComponent,
398
+ });
399
+ ```
400
+
401
+ ## Tension: Built-In SWR Cache vs External Cache
402
+
403
+ TanStack Router has its own SWR cache (`staleTime`, `gcTime`, `defaultPreloadStaleTime`). When using Query as an external cache:
404
+
405
+ - Set `defaultPreloadStaleTime: 0` to prevent Router's cache from short-circuiting Query's freshness logic
406
+ - Router's `staleTime`/`gcTime` still apply to the loader return value. For pure Query patterns, return nothing from the loader (just `ensureQueryData` for the side effect) and read data exclusively from `useSuspenseQuery`
407
+ - `router.invalidate()` re-runs loaders (which call `ensureQueryData`), but Query decides whether to actually refetch based on its own `staleTime`
408
+
409
+ ## Cross-References
410
+
411
+ - [router-core/data-loading](../router-core/data-loading.md) — built-in loader caching fundamentals
412
+ - [router-core/ssr](../router-core/ssr.md) — SSR setup for dehydration/hydration