@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,248 @@
1
+ ---
2
+ name: compositions/compose-query-with-tanstack-router-and-start
3
+ description: >
4
+ Use this when combining TanStack Query with TanStack Router or TanStack Start:
5
+ router context QueryClient, createFileRoute loaders, ensureQueryData,
6
+ @tanstack/react-router-ssr-query, setupRouterSsrQueryIntegration, SSR hydration,
7
+ streaming, redirects, and Start server functions.
8
+ type: composition
9
+ library: TanStack Query
10
+ library_version: "5.101.0"
11
+ requires:
12
+ - lifecycle/setup-query-client-and-providers
13
+ - core/design-query-keys-and-options
14
+ - lifecycle/prefetch-and-remove-request-waterfalls
15
+ sources:
16
+ - TanStack/router:https://tanstack.com/router/latest/docs/integrations/query
17
+ - TanStack/router:https://tanstack.com/router/latest/docs/how-to/setup-ssr
18
+ - TanStack/start:https://tanstack.com/start/latest/docs/framework/react/overview
19
+ - TanStack/query:docs/framework/react/guides/prefetching.md
20
+ - TanStack/query:docs/framework/react/guides/ssr.md
21
+ ---
22
+
23
+ ## Setup
24
+
25
+ ```tsx
26
+ import { QueryClient, QueryClientProvider, useSuspenseQuery } from "@tanstack/react-query";
27
+ import { createFileRoute, createRouter, RouterProvider } from "@tanstack/react-router";
28
+ import { routeTree } from "./routeTree.gen";
29
+
30
+ const queryClient = new QueryClient();
31
+
32
+ const postsQuery = {
33
+ queryKey: ["posts"],
34
+ queryFn: async () => [{ id: 1, title: "Router first" }],
35
+ };
36
+
37
+ export const Route = createFileRoute("/posts")({
38
+ loader: ({ context }) => context.queryClient.ensureQueryData(postsQuery),
39
+ component: PostsPage,
40
+ });
41
+
42
+ function PostsPage() {
43
+ const { data } = useSuspenseQuery(postsQuery);
44
+ return <pre>{JSON.stringify(data)}</pre>;
45
+ }
46
+
47
+ const router = createRouter({ routeTree, context: { queryClient } });
48
+
49
+ export function App() {
50
+ return (
51
+ <QueryClientProvider client={queryClient}>
52
+ <RouterProvider router={router} />
53
+ </QueryClientProvider>
54
+ );
55
+ }
56
+ ```
57
+
58
+ ## Core Integration Patterns
59
+
60
+ ### Put QueryClient in router context
61
+
62
+ ```ts
63
+ import { QueryClient } from "@tanstack/react-query";
64
+ import { createRouter } from "@tanstack/react-router";
65
+ import { routeTree } from "./routeTree.gen";
66
+
67
+ const queryClient = new QueryClient();
68
+
69
+ export const router = createRouter({
70
+ routeTree,
71
+ context: { queryClient },
72
+ defaultPreloadStaleTime: 0,
73
+ });
74
+ ```
75
+
76
+ Set `defaultPreloadStaleTime: 0` when Query owns server-state freshness. Router still preloads and runs loaders, but Query is the cache authority.
77
+
78
+ ### Use loader ensureQueryData for route data
79
+
80
+ ```ts
81
+ import { createFileRoute } from "@tanstack/react-router";
82
+
83
+ const todoQuery = (todoId: string) => ({
84
+ queryKey: ["todo", todoId],
85
+ queryFn: async () => ({ id: todoId, title: "Loaded" }),
86
+ });
87
+
88
+ export const Route = createFileRoute("/todos/$todoId")({
89
+ loader: ({ context, params }) => context.queryClient.ensureQueryData(todoQuery(params.todoId)),
90
+ });
91
+ ```
92
+
93
+ Treat loaders as event handlers that prime the Query cache. Components should still call `useQuery` or `useSuspenseQuery` so the route has an active Query observer.
94
+
95
+ ### Prefer Router SSR Query integration for Router SSR
96
+
97
+ ```ts
98
+ import { QueryClient } from "@tanstack/react-query";
99
+ import { createRouter } from "@tanstack/react-router";
100
+ import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
101
+ import { routeTree } from "./routeTree.gen";
102
+
103
+ const queryClient = new QueryClient();
104
+ const router = createRouter({ routeTree, context: { queryClient } });
105
+
106
+ setupRouterSsrQueryIntegration({ router, queryClient });
107
+ ```
108
+
109
+ ## Common Mistakes
110
+
111
+ ### CRITICAL Component-only Query creates route waterfall
112
+
113
+ Wrong:
114
+
115
+ ```tsx
116
+ import { createFileRoute } from "@tanstack/react-router";
117
+ import { useSuspenseQuery } from "@tanstack/react-query";
118
+
119
+ export const Route = createFileRoute("/posts")({ component: PostsPage });
120
+ function PostsPage() {
121
+ const { data } = useSuspenseQuery({
122
+ queryKey: ["posts"],
123
+ queryFn: async () => [{ id: 1 }],
124
+ });
125
+ return <pre>{JSON.stringify(data)}</pre>;
126
+ }
127
+ ```
128
+
129
+ Correct:
130
+
131
+ ```tsx
132
+ import { createFileRoute } from "@tanstack/react-router";
133
+ import { useSuspenseQuery } from "@tanstack/react-query";
134
+
135
+ const postsQuery = { queryKey: ["posts"], queryFn: async () => [{ id: 1 }] };
136
+ export const Route = createFileRoute("/posts")({
137
+ loader: ({ context }) => context.queryClient.ensureQueryData(postsQuery),
138
+ component: PostsPage,
139
+ });
140
+ function PostsPage() {
141
+ const { data } = useSuspenseQuery(postsQuery);
142
+ return <pre>{JSON.stringify(data)}</pre>;
143
+ }
144
+ ```
145
+
146
+ The router can load route-critical data before component render.
147
+
148
+ Source: TanStack/router:https://tanstack.com/router/latest/docs/integrations/query
149
+
150
+ ### CRITICAL Hand-rolled Router hydration
151
+
152
+ Wrong:
153
+
154
+ ```tsx
155
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
156
+ import { createRouter, RouterProvider } from "@tanstack/react-router";
157
+ import { routeTree } from "./routeTree.gen";
158
+
159
+ const queryClient = new QueryClient();
160
+ const router = createRouter({ routeTree });
161
+ export function App() {
162
+ return (
163
+ <QueryClientProvider client={queryClient}>
164
+ <RouterProvider router={router} />
165
+ </QueryClientProvider>
166
+ );
167
+ }
168
+ ```
169
+
170
+ Correct:
171
+
172
+ ```ts
173
+ import { QueryClient } from "@tanstack/react-query";
174
+ import { createRouter } from "@tanstack/react-router";
175
+ import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
176
+ import { routeTree } from "./routeTree.gen";
177
+
178
+ const queryClient = new QueryClient();
179
+ const router = createRouter({ routeTree, context: { queryClient } });
180
+ setupRouterSsrQueryIntegration({ router, queryClient });
181
+ ```
182
+
183
+ The Router SSR Query integration handles dehydration, hydration, streamed query results, redirects, and provider wrapping.
184
+
185
+ Source: TanStack/router:https://tanstack.com/router/latest/docs/integrations/query
186
+
187
+ ### HIGH Next.js mental model copied into Start
188
+
189
+ Wrong:
190
+
191
+ ```tsx
192
+ export default async function Page() {
193
+ const posts = await Promise.resolve([{ id: 1 }]);
194
+ return <pre>{JSON.stringify(posts)}</pre>;
195
+ }
196
+ ```
197
+
198
+ Correct:
199
+
200
+ ```tsx
201
+ import { createFileRoute } from "@tanstack/react-router";
202
+
203
+ export const Route = createFileRoute("/posts")({
204
+ loader: ({ context }) =>
205
+ context.queryClient.ensureQueryData({
206
+ queryKey: ["posts"],
207
+ queryFn: async () => [{ id: 1 }],
208
+ }),
209
+ component: () => <p>Posts loaded by the route</p>,
210
+ });
211
+ ```
212
+
213
+ Start is powered by TanStack Router; use file routes, loaders, server functions, and Router SSR before Next-specific app/pages APIs.
214
+
215
+ Source: TanStack/start:https://tanstack.com/start/latest/docs/framework/react/overview
216
+
217
+ ### HIGH Reading loader data instead of observing Query
218
+
219
+ Wrong:
220
+
221
+ ```tsx
222
+ import { createFileRoute, useLoaderData } from "@tanstack/react-router";
223
+
224
+ export const Route = createFileRoute("/posts")({
225
+ loader: ({ context }) => context.queryClient.ensureQueryData(postsQuery),
226
+ component: PostsPage,
227
+ });
228
+
229
+ function PostsPage() {
230
+ const posts = useLoaderData({ from: "/posts" });
231
+ return <pre>{JSON.stringify(posts)}</pre>;
232
+ }
233
+ ```
234
+
235
+ Correct:
236
+
237
+ ```tsx
238
+ import { useSuspenseQuery } from "@tanstack/react-query";
239
+
240
+ function PostsPage() {
241
+ const { data } = useSuspenseQuery(postsQuery);
242
+ return <pre>{JSON.stringify(data)}</pre>;
243
+ }
244
+ ```
245
+
246
+ The loader primes the cache. The component still needs an active Query observer for refetch triggers, invalidation, and garbage collection semantics.
247
+
248
+ See also: `lifecycle/ssr-hydration-and-streaming` for framework SSR recipes.
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: compositions/enforce-query-best-practices-with-eslint
3
+ description: >
4
+ Use this when configuring @tanstack/eslint-plugin-query, flat/recommended,
5
+ flat/recommended-strict, exhaustive-deps, no-rest-destructuring,
6
+ no-unstable-deps, no-void-query-fn, stable-query-client, prefer-query-options,
7
+ infinite-query-property-order, and mutation-property-order.
8
+ type: composition
9
+ library: TanStack Query
10
+ library_version: "5.101.0"
11
+ requires:
12
+ - core/design-query-keys-and-options
13
+ - core/fetch-and-observe-queries
14
+ - framework/shape-data-and-render-efficiently
15
+ sources:
16
+ - TanStack/query:docs/eslint/eslint-plugin-query.md
17
+ - TanStack/query:docs/eslint/exhaustive-deps.md
18
+ - TanStack/query:docs/eslint/no-rest-destructuring.md
19
+ - TanStack/query:docs/eslint/no-unstable-deps.md
20
+ - TanStack/query:docs/eslint/no-void-query-fn.md
21
+ - TanStack/query:docs/eslint/prefer-query-options.md
22
+ - TanStack/query:docs/eslint/stable-query-client.md
23
+ - TanStack/query:docs/eslint/infinite-query-property-order.md
24
+ - TanStack/query:docs/eslint/mutation-property-order.md
25
+ ---
26
+
27
+ ## Setup
28
+
29
+ ```js
30
+ import pluginQuery from "@tanstack/eslint-plugin-query";
31
+
32
+ export default [...pluginQuery.configs["flat/recommended"]];
33
+ ```
34
+
35
+ ## Core Integration Patterns
36
+
37
+ ### Use strict when generating Query-heavy code
38
+
39
+ ```js
40
+ import pluginQuery from "@tanstack/eslint-plugin-query";
41
+
42
+ export default [...pluginQuery.configs["flat/recommended-strict"]];
43
+ ```
44
+
45
+ ### Prefer option factories
46
+
47
+ ```ts
48
+ import { queryOptions, useQuery } from "@tanstack/react-query";
49
+
50
+ const todosOptions = queryOptions({
51
+ queryKey: ["todos"],
52
+ queryFn: async () => [{ id: 1 }],
53
+ });
54
+
55
+ export function useTodos() {
56
+ return useQuery(todosOptions);
57
+ }
58
+ ```
59
+
60
+ ### Keep inference-sensitive property order
61
+
62
+ ```ts
63
+ import { useInfiniteQuery } from "@tanstack/react-query";
64
+
65
+ export function useFeed() {
66
+ return useInfiniteQuery({
67
+ queryKey: ["feed"],
68
+ queryFn: async ({ pageParam }) => ({ nextCursor: pageParam + 1 }),
69
+ initialPageParam: 0,
70
+ getNextPageParam: (page) => page.nextCursor,
71
+ });
72
+ }
73
+ ```
74
+
75
+ ## Common Mistakes
76
+
77
+ ### MEDIUM Strict rule not enabled
78
+
79
+ Wrong:
80
+
81
+ ```js
82
+ import pluginQuery from "@tanstack/eslint-plugin-query";
83
+
84
+ export default [...pluginQuery.configs["flat/recommended"]];
85
+ ```
86
+
87
+ Correct:
88
+
89
+ ```js
90
+ import pluginQuery from "@tanstack/eslint-plugin-query";
91
+
92
+ export default [...pluginQuery.configs["flat/recommended-strict"]];
93
+ ```
94
+
95
+ Strict mode catches option-factory and inference patterns that agents commonly miss.
96
+
97
+ Source: TanStack/query:docs/eslint/eslint-plugin-query.md
98
+
99
+ ### MEDIUM Infinite option property order
100
+
101
+ Wrong:
102
+
103
+ ```ts
104
+ import { useInfiniteQuery } from "@tanstack/react-query";
105
+
106
+ export function useFeed() {
107
+ return useInfiniteQuery({
108
+ queryFn: async () => ({ nextCursor: 1 }),
109
+ queryKey: ["feed"],
110
+ getNextPageParam: (page) => page.nextCursor,
111
+ initialPageParam: 0,
112
+ });
113
+ }
114
+ ```
115
+
116
+ Correct:
117
+
118
+ ```ts
119
+ import { useInfiniteQuery } from "@tanstack/react-query";
120
+
121
+ export function useFeed() {
122
+ return useInfiniteQuery({
123
+ queryKey: ["feed"],
124
+ queryFn: async ({ pageParam }) => ({ nextCursor: pageParam + 1 }),
125
+ initialPageParam: 0,
126
+ getNextPageParam: (page) => page.nextCursor,
127
+ });
128
+ }
129
+ ```
130
+
131
+ Some infinite-query inference depends on stable option ordering.
132
+
133
+ Source: TanStack/query:docs/eslint/infinite-query-property-order.md
134
+
135
+ ### MEDIUM Mutation option property order
136
+
137
+ Wrong:
138
+
139
+ ```ts
140
+ import { useMutation } from "@tanstack/react-query";
141
+
142
+ export function useSave() {
143
+ return useMutation({
144
+ onSuccess: () => console.log("saved"),
145
+ mutationFn: async (title: string) => title,
146
+ });
147
+ }
148
+ ```
149
+
150
+ Correct:
151
+
152
+ ```ts
153
+ import { useMutation } from "@tanstack/react-query";
154
+
155
+ export function useSave() {
156
+ return useMutation({
157
+ mutationFn: async (title: string) => title,
158
+ onSuccess: () => console.log("saved"),
159
+ });
160
+ }
161
+ ```
162
+
163
+ The mutation property order rule preserves inference for mutation options.
164
+
165
+ Source: TanStack/query:docs/eslint/mutation-property-order.md
166
+
167
+ See also: `core/design-query-keys-and-options` for the patterns these rules protect.
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: compositions/persist-offline-and-restore-caches
3
+ description: >
4
+ Use this when using persistQueryClient, PersistQueryClientProvider,
5
+ createSyncStoragePersister, createAsyncStoragePersister, experimental
6
+ fine-grained persisters, offline mutations, resumePausedMutations, maxAge,
7
+ gcTime, and restore races.
8
+ type: composition
9
+ library: TanStack Query
10
+ library_version: "5.101.0"
11
+ requires:
12
+ - lifecycle/setup-query-client-and-providers
13
+ - core/tune-defaults-freshness-retries-and-refetching
14
+ - core/write-mutations-and-invalidate-related-queries
15
+ sources:
16
+ - TanStack/query:docs/framework/react/plugins/persistQueryClient.md
17
+ - TanStack/query:docs/framework/react/plugins/createSyncStoragePersister.md
18
+ - TanStack/query:docs/framework/react/plugins/createAsyncStoragePersister.md
19
+ - TanStack/query:docs/framework/react/plugins/createPersister.md
20
+ - TanStack/query:docs/framework/react/guides/network-mode.md
21
+ ---
22
+
23
+ ## Setup
24
+
25
+ ```tsx
26
+ import * as React from "react";
27
+ import { QueryClient } from "@tanstack/react-query";
28
+ import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client";
29
+ import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister";
30
+
31
+ const queryClient = new QueryClient({
32
+ defaultOptions: { queries: { gcTime: 24 * 60 * 60 * 1000 } },
33
+ });
34
+
35
+ const persister = createSyncStoragePersister({
36
+ storage: window.localStorage,
37
+ });
38
+
39
+ export function AppProviders(props: { children: React.ReactNode }) {
40
+ return (
41
+ <PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
42
+ {props.children}
43
+ </PersistQueryClientProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ## Core Integration Patterns
49
+
50
+ ### Resume paused mutations after restore
51
+
52
+ ```ts
53
+ import { QueryClient } from "@tanstack/react-query";
54
+
55
+ export const queryClient = new QueryClient();
56
+
57
+ queryClient.setMutationDefaults(["todos"], {
58
+ mutationFn: async (todo: { id: number; title: string }) => todo,
59
+ });
60
+
61
+ export function resumeMutations() {
62
+ return queryClient.resumePausedMutations();
63
+ }
64
+ ```
65
+
66
+ ### Align cache lifetime with persistence
67
+
68
+ ```ts
69
+ import { QueryClient } from "@tanstack/react-query";
70
+
71
+ export const queryClient = new QueryClient({
72
+ defaultOptions: {
73
+ queries: { gcTime: 7 * 24 * 60 * 60 * 1000 },
74
+ },
75
+ });
76
+ ```
77
+
78
+ ### Use networkMode for offline-first writes
79
+
80
+ ```ts
81
+ import { useMutation } from "@tanstack/react-query";
82
+
83
+ export function useSaveDraft() {
84
+ return useMutation({
85
+ mutationKey: ["saveDraft"],
86
+ mutationFn: async (draft: { body: string }) => draft,
87
+ networkMode: "offlineFirst",
88
+ });
89
+ }
90
+ ```
91
+
92
+ ## Common Mistakes
93
+
94
+ ### HIGH gcTime shorter than maxAge
95
+
96
+ Wrong:
97
+
98
+ ```ts
99
+ import { QueryClient } from "@tanstack/react-query";
100
+
101
+ export const queryClient = new QueryClient({
102
+ defaultOptions: { queries: { gcTime: 5 * 60 * 1000 } },
103
+ });
104
+ ```
105
+
106
+ Correct:
107
+
108
+ ```ts
109
+ import { QueryClient } from "@tanstack/react-query";
110
+
111
+ export const queryClient = new QueryClient({
112
+ defaultOptions: { queries: { gcTime: 24 * 60 * 60 * 1000 } },
113
+ });
114
+ ```
115
+
116
+ Persisted data can be garbage-collected before the persister maxAge can restore it.
117
+
118
+ Source: TanStack/query:docs/framework/react/plugins/persistQueryClient.md
119
+
120
+ ### CRITICAL Rendering before restore
121
+
122
+ Wrong:
123
+
124
+ ```tsx
125
+ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
126
+
127
+ const queryClient = new QueryClient();
128
+ export function App(props: { children: React.ReactNode }) {
129
+ return <QueryClientProvider client={queryClient}>{props.children}</QueryClientProvider>;
130
+ }
131
+ ```
132
+
133
+ Correct:
134
+
135
+ ```tsx
136
+ import { QueryClient } from "@tanstack/react-query";
137
+ import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client";
138
+ import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister";
139
+
140
+ const queryClient = new QueryClient();
141
+ const persister = createSyncStoragePersister({ storage: window.localStorage });
142
+
143
+ export function App(props: { children: React.ReactNode }) {
144
+ return (
145
+ <PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
146
+ {props.children}
147
+ </PersistQueryClientProvider>
148
+ );
149
+ }
150
+ ```
151
+
152
+ The persistence provider prevents query fetching while restore is in progress.
153
+
154
+ Source: TanStack/query:docs/framework/react/plugins/persistQueryClient.md
155
+
156
+ ### CRITICAL Missing default mutationFn
157
+
158
+ Wrong:
159
+
160
+ ```ts
161
+ import { QueryClient } from "@tanstack/react-query";
162
+
163
+ export const queryClient = new QueryClient();
164
+ ```
165
+
166
+ Correct:
167
+
168
+ ```ts
169
+ import { QueryClient } from "@tanstack/react-query";
170
+
171
+ export const queryClient = new QueryClient();
172
+ queryClient.setMutationDefaults(["saveDraft"], {
173
+ mutationFn: async (draft: { body: string }) => draft,
174
+ });
175
+ ```
176
+
177
+ Paused persisted mutations cannot resume without a serializable mutation key mapped to a default mutationFn.
178
+
179
+ Source: TanStack/query:docs/framework/react/plugins/persistQueryClient.md
180
+
181
+ See also: `core/tune-defaults-freshness-retries-and-refetching` for gcTime and networkMode.