@hitch42/applet 0.1.0-beta.9 → 0.1.1-beta.10

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 (164) 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.js +112 -57
  5. package/dist/applet.js +12 -12
  6. package/dist/build-Bh_S5BUv.js +2 -0
  7. package/dist/{build-CAb26kMY.js → build-CEfFoIZZ.js} +1 -1
  8. package/dist/{ci-5qWl7lT3.js → ci-BKw14X2h.js} +14 -13
  9. package/dist/client.d.ts +2 -2
  10. package/dist/{contract-rP_eV9PK.d.ts → contract-CsUpTBe0.d.ts} +1 -1
  11. package/dist/{deploy-D_OFJ6-Q.js → deploy-wGYjwXrx.js} +139 -88
  12. package/dist/{generate-CBPnHoqX.js → generate-BEIYs17x.js} +54 -22
  13. package/dist/generate-Dox-OYt6.js +2 -0
  14. package/dist/headers-DkNr9MLJ.js +17 -0
  15. package/dist/index.d.ts +3 -2
  16. package/dist/index.js +2 -1
  17. package/dist/{init-tfzwuYnk.js → init-6oGPM46R.js} +10 -15
  18. package/dist/{load-config-BYSxDVAl.js → load-config-xEdTXs0y.js} +2 -2
  19. package/dist/log-context-zu8U9Sjm.js +73 -0
  20. package/dist/{login-C7RKmmTe.js → login-CUx3TmFQ.js} +1 -1
  21. package/dist/{logs-DgjgAxj2.js → logs-DSjuEN0Q.js} +20 -22
  22. package/dist/{manifest-DD_SGkS6.d.ts → manifest-C6_F4bL8.d.ts} +5 -1
  23. package/dist/{manifest-Bp87Uz0a.js → manifest-CJSL9GuC.js} +20 -4
  24. package/dist/{project-D6XHllmC.js → project-BRZGd6xq.js} +197 -16
  25. package/dist/query-cache-CXmAyLv3.js +82 -0
  26. package/dist/react.d.ts +2 -1
  27. package/dist/react.js +59 -39
  28. package/dist/{schedules-dhU1yyFr.js → schedules-C8_Svr4h.js} +1 -1
  29. package/dist/server.d.ts +8 -3
  30. package/dist/server.js +29 -8
  31. package/dist/telephony.d.ts +24 -4
  32. package/dist/telephony.js +135 -16
  33. package/dist/{variables-Bwnr7oxf.js → variables-DT5RyHdH.js} +13 -13
  34. package/dist/vite.d.ts +3 -60
  35. package/dist/vite.js +50 -15
  36. package/dist/{workflow-engine-MogejNfF.js → workflow-engine-BOTzURKM.js} +1 -7
  37. package/dist/{workspace-XVtM12ZC.js → workspace-D0dnnlxL.js} +33 -38
  38. package/package.json +13 -6
  39. package/scaffold/.agents/skills/hitch-applets/SKILL.md +29 -3
  40. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +8 -0
  41. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +2 -0
  42. package/scaffold/.agents/skills/hitch-applets/references/records.md +2 -0
  43. package/scaffold/.agents/skills/hitch-data/SKILL.md +2 -1
  44. package/scaffold/.agents/skills/hitch-data/references/attributes.md +7 -1
  45. package/scaffold/.agents/skills/hitch-data/references/limits.md +13 -13
  46. package/scaffold/.agents/skills/hitch-theory/SKILL.md +3 -2
  47. package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
  48. package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  49. package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  50. package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  51. package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  52. package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  53. package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
  54. package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
  55. package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
  56. package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
  57. package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
  58. package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
  59. package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
  60. package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
  61. package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
  62. package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  63. package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  64. package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  65. package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  66. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
  67. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  68. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
  69. package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  70. package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  71. package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  72. package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  73. package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  74. package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  75. package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  76. package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  77. package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  78. package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  79. package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  80. package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  81. package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  82. package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  83. package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  84. package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
  85. package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
  86. package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  87. package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
  88. package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  89. package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  90. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  91. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  92. package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  93. package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  94. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  95. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  96. package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  97. package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  98. package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  99. package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  100. package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  101. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  102. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  103. package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
  104. package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
  105. package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
  106. package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
  107. package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
  108. package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
  109. package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
  110. package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
  111. package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
  112. package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
  113. package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
  114. package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
  115. package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
  116. package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
  117. package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
  118. package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
  119. package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
  120. package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
  121. package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
  122. package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
  123. package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
  124. package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
  125. package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
  126. package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
  127. package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
  128. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
  129. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
  130. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
  131. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
  132. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
  133. package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
  134. package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
  135. package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
  136. package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
  137. package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
  138. package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
  139. package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
  140. package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
  141. package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
  142. package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
  143. package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
  144. package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
  145. package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
  146. package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
  147. package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
  148. package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
  149. package/scaffold/.github/workflows/hitch.yml +1 -1
  150. package/scaffold/AGENTS.md +2 -2
  151. package/scaffold/applet/src/client/components/ui/alert.tsx +1 -1
  152. package/scaffold/applet/src/client/components/ui/button.tsx +1 -1
  153. package/scaffold/applet/src/client/components/ui/checkbox.tsx +1 -1
  154. package/scaffold/applet/src/client/components/ui/dialog.tsx +2 -2
  155. package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +2 -2
  156. package/scaffold/applet/src/client/components/ui/input-group.tsx +2 -2
  157. package/scaffold/applet/src/client/components/ui/select.tsx +2 -2
  158. package/scaffold/applet/src/client/components/ui/sheet.tsx +2 -2
  159. package/scaffold/applet/src/client/components/ui/spinner.tsx +2 -1
  160. package/scaffold/applet/src/client/components/ui/tabs.tsx +1 -1
  161. package/scaffold/applet/src/client/lib/utils.ts +1 -6
  162. package/scaffold/applet/src/client/styles/globals.css +2 -0
  163. package/dist/build-BfbTbt_r.js +0 -2
  164. package/dist/generate-BgepN4-b.js +0 -2
@@ -0,0 +1,433 @@
1
+ ---
2
+ name: navigation
3
+ description: >-
4
+ Link component, useNavigate, Navigate component, router.navigate,
5
+ ToOptions/NavigateOptions/LinkOptions, from/to relative navigation,
6
+ activeOptions/activeProps, preloading (intent/viewport/render),
7
+ preloadDelay, navigation blocking (useBlocker, Block), createLink,
8
+ linkOptions helper, scroll restoration, MatchRoute.
9
+ metadata:
10
+ type: sub-skill
11
+ library: tanstack-router
12
+ library_version: "1.171.15"
13
+ requires:
14
+ - router-core
15
+ sources:
16
+ - TanStack/router:docs/router/guide/navigation.md
17
+ - TanStack/router:docs/router/guide/preloading.md
18
+ - TanStack/router:docs/router/guide/navigation-blocking.md
19
+ - TanStack/router:docs/router/guide/link-options.md
20
+ - TanStack/router:docs/router/guide/custom-link.md
21
+ - TanStack/router:docs/router/guide/scroll-restoration.md
22
+ ---
23
+
24
+ # Navigation
25
+
26
+ ## Setup
27
+
28
+ Basic type-safe `Link` with `to` and `params`:
29
+
30
+ ```tsx
31
+ import { Link } from "@tanstack/react-router";
32
+
33
+ function PostLink({ postId }: { postId: string }) {
34
+ return (
35
+ <Link to="/posts/$postId" params={{ postId }}>
36
+ View Post
37
+ </Link>
38
+ );
39
+ }
40
+ ```
41
+
42
+ ## Core Patterns
43
+
44
+ ### Link with Active States
45
+
46
+ ```tsx
47
+ import { Link } from "@tanstack/react-router";
48
+
49
+ function NavLink() {
50
+ return (
51
+ <Link
52
+ to="/posts"
53
+ activeProps={{ className: "font-bold" }}
54
+ inactiveProps={{ className: "text-gray-500" }}
55
+ activeOptions={{ exact: true }}
56
+ >
57
+ Posts
58
+ </Link>
59
+ );
60
+ }
61
+ ```
62
+
63
+ The `data-status` attribute is also set to `"active"` on active links for CSS-based styling.
64
+
65
+ `activeOptions` controls matching behavior:
66
+
67
+ - `exact` (default `false`) — when `true`, only matches the exact path (not children)
68
+ - `includeHash` (default `false`) — include hash in active matching
69
+ - `includeSearch` (default `true`) — include search params in active matching
70
+
71
+ Children can receive `isActive` as a render function:
72
+
73
+ ```tsx
74
+ <Link to="/posts">
75
+ {({ isActive }) => <span className={isActive ? "font-bold" : ""}>Posts</span>}
76
+ </Link>
77
+ ```
78
+
79
+ ### Relative Navigation with `from`
80
+
81
+ Without `from`, navigation resolves from root `/`. To use relative paths like `..`, provide `from`:
82
+
83
+ ```tsx
84
+ import { createFileRoute, Link } from "@tanstack/react-router";
85
+
86
+ export const Route = createFileRoute("/posts/$postId")({
87
+ component: PostComponent,
88
+ });
89
+
90
+ function PostComponent() {
91
+ return (
92
+ <div>
93
+ {/* Relative to current route */}
94
+ <Link from={Route.fullPath} to="..">
95
+ Back to Posts
96
+ </Link>
97
+
98
+ {/* "." reloads the current route */}
99
+ <Link from={Route.fullPath} to=".">
100
+ Reload
101
+ </Link>
102
+ </div>
103
+ );
104
+ }
105
+ ```
106
+
107
+ ### useNavigate for Programmatic Navigation
108
+
109
+ Use `useNavigate` only for side-effect-driven navigation (e.g., after a form submission). For anything the user clicks, prefer `Link`.
110
+
111
+ ```tsx
112
+ import { useNavigate } from "@tanstack/react-router";
113
+
114
+ function CreatePostForm() {
115
+ const navigate = useNavigate({ from: "/posts" });
116
+
117
+ const handleSubmit = async (e: React.FormEvent) => {
118
+ e.preventDefault();
119
+ const response = await fetch("/api/posts", { method: "POST", body: "..." });
120
+ const { id: postId } = await response.json();
121
+
122
+ if (response.ok) {
123
+ navigate({ to: "/posts/$postId", params: { postId } });
124
+ }
125
+ };
126
+
127
+ return <form onSubmit={handleSubmit}>{/* ... */}</form>;
128
+ }
129
+ ```
130
+
131
+ The `Navigate` component performs an immediate client-side navigation on mount:
132
+
133
+ ```tsx
134
+ import { Navigate } from "@tanstack/react-router";
135
+
136
+ function LegacyRedirect() {
137
+ return <Navigate to="/posts/$postId" params={{ postId: "my-first-post" }} />;
138
+ }
139
+ ```
140
+
141
+ `router.navigate` is available anywhere you have the router instance, including outside of React.
142
+
143
+ ### Preloading
144
+
145
+ Strategies: `intent` (hover/touchstart), `viewport` (intersection observer), `render` (on mount).
146
+
147
+ Set globally:
148
+
149
+ ```tsx
150
+ import { createRouter } from "@tanstack/react-router";
151
+
152
+ const router = createRouter({
153
+ routeTree,
154
+ defaultPreload: "intent",
155
+ defaultPreloadDelay: 50, // ms, default is 50
156
+ });
157
+ ```
158
+
159
+ Or per-link:
160
+
161
+ ```tsx
162
+ <Link to="/posts/$postId" params={{ postId }} preload="intent" preloadDelay={100}>
163
+ View Post
164
+ </Link>
165
+ ```
166
+
167
+ Preloaded data stays fresh for 30 seconds by default (`defaultPreloadStaleTime: 30_000`). During that window it won't be refetched. When using an external cache like TanStack Query, set `defaultPreloadStaleTime: 0` to let the external library control freshness.
168
+
169
+ Manual preloading via the router instance:
170
+
171
+ ```tsx
172
+ import { useRouter } from "@tanstack/react-router";
173
+
174
+ function Component() {
175
+ const router = useRouter();
176
+
177
+ useEffect(() => {
178
+ router.preloadRoute({ to: "/posts/$postId", params: { postId: "1" } });
179
+ }, [router]);
180
+
181
+ return <div />;
182
+ }
183
+ ```
184
+
185
+ ### Navigation Blocking
186
+
187
+ Use `useBlocker` to prevent navigation when a form has unsaved changes:
188
+
189
+ ```tsx
190
+ import { useBlocker } from "@tanstack/react-router";
191
+ import { useState } from "react";
192
+
193
+ function EditForm() {
194
+ const [formIsDirty, setFormIsDirty] = useState(false);
195
+
196
+ useBlocker({
197
+ shouldBlockFn: () => {
198
+ if (!formIsDirty) return false;
199
+ const shouldLeave = confirm("Are you sure you want to leave?");
200
+ return !shouldLeave;
201
+ },
202
+ });
203
+
204
+ return <form>{/* ... */}</form>;
205
+ }
206
+ ```
207
+
208
+ With custom UI using `withResolver`:
209
+
210
+ ```tsx
211
+ import { useBlocker } from "@tanstack/react-router";
212
+ import { useState } from "react";
213
+
214
+ function EditForm() {
215
+ const [formIsDirty, setFormIsDirty] = useState(false);
216
+
217
+ const { proceed, reset, status } = useBlocker({
218
+ shouldBlockFn: () => formIsDirty,
219
+ withResolver: true,
220
+ });
221
+
222
+ return (
223
+ <>
224
+ <form>{/* ... */}</form>
225
+ {status === "blocked" && (
226
+ <div>
227
+ <p>Are you sure you want to leave?</p>
228
+ <button onClick={proceed}>Yes</button>
229
+ <button onClick={reset}>No</button>
230
+ </div>
231
+ )}
232
+ </>
233
+ );
234
+ }
235
+ ```
236
+
237
+ Control `beforeunload` separately:
238
+
239
+ ```tsx
240
+ useBlocker({
241
+ shouldBlockFn: () => formIsDirty,
242
+ enableBeforeUnload: formIsDirty,
243
+ });
244
+ ```
245
+
246
+ ### linkOptions for Reusable Navigation Options
247
+
248
+ `linkOptions` provides eager type-checking on navigation options objects, so errors surface at definition, not at spread-site:
249
+
250
+ ```tsx
251
+ import { linkOptions, Link, useNavigate, redirect } from "@tanstack/react-router";
252
+
253
+ const dashboardLinkOptions = linkOptions({
254
+ to: "/dashboard",
255
+ search: { search: "" },
256
+ });
257
+
258
+ // Use anywhere: Link, navigate, redirect
259
+ function Nav() {
260
+ const navigate = useNavigate();
261
+
262
+ return (
263
+ <div>
264
+ <Link {...dashboardLinkOptions}>Dashboard</Link>
265
+ <button onClick={() => navigate(dashboardLinkOptions)}>Go</button>
266
+ </div>
267
+ );
268
+ }
269
+
270
+ // Also works in an array for navigation bars
271
+ const navOptions = linkOptions([
272
+ { to: "/dashboard", label: "Summary", activeOptions: { exact: true } },
273
+ { to: "/dashboard/invoices", label: "Invoices" },
274
+ { to: "/dashboard/users", label: "Users" },
275
+ ]);
276
+
277
+ function NavBar() {
278
+ return (
279
+ <nav>
280
+ {navOptions.map((option) => (
281
+ <Link {...option} key={option.to} activeProps={{ className: "font-bold" }}>
282
+ {option.label}
283
+ </Link>
284
+ ))}
285
+ </nav>
286
+ );
287
+ }
288
+ ```
289
+
290
+ ### createLink for Custom Components
291
+
292
+ Wraps any component with TanStack Router's type-safe navigation:
293
+
294
+ ```tsx
295
+ import * as React from "react";
296
+ import { createLink, LinkComponent } from "@tanstack/react-router";
297
+
298
+ interface BasicLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {}
299
+
300
+ const BasicLinkComponent = React.forwardRef<HTMLAnchorElement, BasicLinkProps>((props, ref) => {
301
+ return <a ref={ref} {...props} className="block px-3 py-2 text-blue-700" />;
302
+ });
303
+
304
+ const CreatedLinkComponent = createLink(BasicLinkComponent);
305
+
306
+ export const CustomLink: LinkComponent<typeof BasicLinkComponent> = (props) => {
307
+ return <CreatedLinkComponent preload="intent" {...props} />;
308
+ };
309
+ ```
310
+
311
+ Usage retains full type safety:
312
+
313
+ ```tsx
314
+ <CustomLink to="/dashboard/invoices/$invoiceId" params={{ invoiceId: 0 }} />
315
+ ```
316
+
317
+ ### Scroll Restoration
318
+
319
+ Enable globally on the router:
320
+
321
+ ```tsx
322
+ const router = createRouter({
323
+ routeTree,
324
+ scrollRestoration: true,
325
+ });
326
+ ```
327
+
328
+ For nested scrollable areas:
329
+
330
+ ```tsx
331
+ const router = createRouter({
332
+ routeTree,
333
+ scrollRestoration: true,
334
+ scrollToTopSelectors: ["#main-scrollable-area"],
335
+ });
336
+ ```
337
+
338
+ Custom cache keys:
339
+
340
+ ```tsx
341
+ const router = createRouter({
342
+ routeTree,
343
+ scrollRestoration: true,
344
+ getScrollRestorationKey: (location) => location.pathname,
345
+ });
346
+ ```
347
+
348
+ Prevent scroll reset for a specific navigation:
349
+
350
+ ```tsx
351
+ <Link to="/posts" resetScroll={false}>
352
+ Posts
353
+ </Link>
354
+ ```
355
+
356
+ ### MatchRoute for Pending UI
357
+
358
+ ```tsx
359
+ import { Link, MatchRoute } from "@tanstack/react-router";
360
+
361
+ function Nav() {
362
+ return (
363
+ <Link to="/users">
364
+ Users
365
+ <MatchRoute to="/users" pending>
366
+ <Spinner />
367
+ </MatchRoute>
368
+ </Link>
369
+ );
370
+ }
371
+ ```
372
+
373
+ ## Common Mistakes
374
+
375
+ ### CRITICAL: Interpolating params into the `to` string
376
+
377
+ ```tsx
378
+ // WRONG — breaks type safety and param encoding
379
+ <Link to={`/posts/${postId}`}>Post</Link>
380
+
381
+ // CORRECT — use the params option
382
+ <Link to="/posts/$postId" params={{ postId }}>Post</Link>
383
+ ```
384
+
385
+ Dynamic segments are declared with `$` in the route path. Always pass them via `params`. This applies to `Link`, `useNavigate`, `Navigate`, and `router.navigate`.
386
+
387
+ ### MEDIUM: Using useNavigate for clickable elements
388
+
389
+ ```tsx
390
+ // WRONG — no href, no cmd+click, no preloading, no accessibility
391
+ function BadNav() {
392
+ const navigate = useNavigate();
393
+ return <button onClick={() => navigate({ to: "/posts" })}>Posts</button>;
394
+ }
395
+
396
+ // CORRECT — real <a> tag with href, accessible, preloadable
397
+ function GoodNav() {
398
+ return <Link to="/posts">Posts</Link>;
399
+ }
400
+ ```
401
+
402
+ Use `useNavigate` only for programmatic side-effect navigation (after form submit, async action, etc).
403
+
404
+ ### HIGH: Not providing `from` for relative navigation
405
+
406
+ ```tsx
407
+ // WRONG — without from, ".." resolves from root
408
+ <Link to="..">Back</Link>
409
+
410
+ // CORRECT — provide from for relative resolution
411
+ <Link from={Route.fullPath} to="..">Back</Link>
412
+ ```
413
+
414
+ Without `from`, only absolute paths are autocompleted and type-safe. Relative paths like `..` resolve from root instead of the current route.
415
+
416
+ ### HIGH: Using search as object instead of function loses existing params
417
+
418
+ ```tsx
419
+ // WRONG — replaces ALL search params with just { page: 2 }
420
+ <Link to="." search={{ page: 2 }}>Page 2</Link>
421
+
422
+ // CORRECT — preserves existing search params, updates page
423
+ <Link to="." search={(prev) => ({ ...prev, page: 2 })}>Page 2</Link>
424
+ ```
425
+
426
+ When you pass `search` as a plain object, it replaces all search params. Use the function form to spread previous params and selectively update.
427
+
428
+ ---
429
+
430
+ ## Cross-References
431
+
432
+ - See also: **router-core/search-params/SKILL.md** — Link `search` prop interacts with search param validation
433
+ - See also: **router-core/type-safety/SKILL.md** — `from` narrowing improves type inference on Link