@tanstack/vue-start 1.166.14 → 1.166.15
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.
- package/bin/intent.js +25 -0
- package/package.json +15 -8
- package/skills/vue-start/SKILL.md +304 -0
package/bin/intent.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Auto-generated by @tanstack/intent setup
|
|
3
|
+
// Exposes the intent end-user CLI for consumers of this library.
|
|
4
|
+
// Commit this file, then add to your package.json:
|
|
5
|
+
// "bin": { "intent": "./bin/intent.js" }
|
|
6
|
+
try {
|
|
7
|
+
await import('@tanstack/intent/intent-library')
|
|
8
|
+
} catch (e) {
|
|
9
|
+
const isModuleNotFound =
|
|
10
|
+
e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND'
|
|
11
|
+
const missingIntentLibrary =
|
|
12
|
+
typeof e?.message === 'string' && e.message.includes('@tanstack/intent')
|
|
13
|
+
|
|
14
|
+
if (isModuleNotFound && missingIntentLibrary) {
|
|
15
|
+
console.error('@tanstack/intent is not installed.')
|
|
16
|
+
console.error('')
|
|
17
|
+
console.error('Install it as a dev dependency:')
|
|
18
|
+
console.error(' npm add -D @tanstack/intent')
|
|
19
|
+
console.error('')
|
|
20
|
+
console.error('Or run directly:')
|
|
21
|
+
console.error(' npx @tanstack/intent@latest list')
|
|
22
|
+
process.exit(1)
|
|
23
|
+
}
|
|
24
|
+
throw e
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/vue-start",
|
|
3
|
-
"version": "1.166.
|
|
3
|
+
"version": "1.166.15",
|
|
4
4
|
"description": "Modern and scalable routing for Vue applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -91,21 +91,25 @@
|
|
|
91
91
|
"sideEffects": false,
|
|
92
92
|
"files": [
|
|
93
93
|
"dist",
|
|
94
|
-
"src"
|
|
94
|
+
"src",
|
|
95
|
+
"skills",
|
|
96
|
+
"bin",
|
|
97
|
+
"!skills/_artifacts"
|
|
95
98
|
],
|
|
96
99
|
"engines": {
|
|
97
100
|
"node": ">=22.12.0"
|
|
98
101
|
},
|
|
99
102
|
"dependencies": {
|
|
100
103
|
"pathe": "^2.0.3",
|
|
101
|
-
"@tanstack/vue-start-
|
|
102
|
-
"@tanstack/vue-start-
|
|
103
|
-
"@tanstack/start-plugin-core": "1.166.
|
|
104
|
-
"@tanstack/vue-router": "1.167.
|
|
105
|
-
"@tanstack/start-client-core": "1.166.
|
|
106
|
-
"@tanstack/start-server-core": "1.166.
|
|
104
|
+
"@tanstack/vue-start-client": "1.166.12",
|
|
105
|
+
"@tanstack/vue-start-server": "1.166.12",
|
|
106
|
+
"@tanstack/start-plugin-core": "1.166.15",
|
|
107
|
+
"@tanstack/vue-router": "1.167.4",
|
|
108
|
+
"@tanstack/start-client-core": "1.166.12",
|
|
109
|
+
"@tanstack/start-server-core": "1.166.12"
|
|
107
110
|
},
|
|
108
111
|
"devDependencies": {
|
|
112
|
+
"@tanstack/intent": "^0.0.14",
|
|
109
113
|
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
|
110
114
|
"vite": "*",
|
|
111
115
|
"vue": "^3.5.25",
|
|
@@ -115,6 +119,9 @@
|
|
|
115
119
|
"vue": "^3.3.0",
|
|
116
120
|
"vite": ">=7.0.0"
|
|
117
121
|
},
|
|
122
|
+
"bin": {
|
|
123
|
+
"intent": "./bin/intent.js"
|
|
124
|
+
},
|
|
118
125
|
"scripts": {
|
|
119
126
|
"clean": "rimraf ./dist && rimraf ./coverage",
|
|
120
127
|
"test": "pnpm test:build",
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vue-start
|
|
3
|
+
description: >-
|
|
4
|
+
Vue bindings for TanStack Start: useServerFn hook, tanstackStart
|
|
5
|
+
Vite plugin, StartClient, StartServer, Vue-specific setup,
|
|
6
|
+
re-exports from @tanstack/start-client-core. Full project setup
|
|
7
|
+
with Vue.
|
|
8
|
+
type: framework
|
|
9
|
+
library: tanstack-start
|
|
10
|
+
library_version: '1.166.2'
|
|
11
|
+
framework: vue
|
|
12
|
+
requires:
|
|
13
|
+
- start-core
|
|
14
|
+
sources:
|
|
15
|
+
- TanStack/router:packages/vue-start/src
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Vue Start (`@tanstack/vue-start`)
|
|
19
|
+
|
|
20
|
+
This skill builds on start-core. Read [start-core](../../../start-client-core/skills/start-core/SKILL.md) first for foundational concepts.
|
|
21
|
+
|
|
22
|
+
This skill covers the Vue-specific bindings, setup, and patterns for TanStack Start.
|
|
23
|
+
|
|
24
|
+
> **CRITICAL**: All code is ISOMORPHIC by default. Loaders run on BOTH server and client. Use `createServerFn` for server-only logic.
|
|
25
|
+
|
|
26
|
+
> **CRITICAL**: Do not confuse `@tanstack/vue-start` with Nuxt. They are completely different frameworks with different APIs.
|
|
27
|
+
|
|
28
|
+
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
|
|
29
|
+
|
|
30
|
+
## Package API Surface
|
|
31
|
+
|
|
32
|
+
`@tanstack/vue-start` re-exports everything from `@tanstack/start-client-core` plus:
|
|
33
|
+
|
|
34
|
+
- `useServerFn` — Vue composable for calling server functions from components
|
|
35
|
+
|
|
36
|
+
All core APIs (`createServerFn`, `createMiddleware`, `createStart`, `createIsomorphicFn`, `createServerOnlyFn`, `createClientOnlyFn`) are available from `@tanstack/vue-start`.
|
|
37
|
+
|
|
38
|
+
Server utilities (`getRequest`, `getRequestHeader`, `setResponseHeader`, `setCookie`, `getCookie`, `useSession`) are imported from `@tanstack/vue-start/server`.
|
|
39
|
+
|
|
40
|
+
## Full Project Setup
|
|
41
|
+
|
|
42
|
+
### 1. Install Dependencies
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm i @tanstack/vue-start @tanstack/vue-router vue
|
|
46
|
+
npm i -D vite @vitejs/plugin-vue @vitejs/plugin-vue-jsx typescript
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. package.json
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"type": "module",
|
|
54
|
+
"scripts": {
|
|
55
|
+
"dev": "vite dev",
|
|
56
|
+
"build": "vite build",
|
|
57
|
+
"start": "node .output/server/index.mjs"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. tsconfig.json
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"compilerOptions": {
|
|
67
|
+
"jsx": "preserve",
|
|
68
|
+
"jsxImportSource": "vue",
|
|
69
|
+
"moduleResolution": "Bundler",
|
|
70
|
+
"module": "ESNext",
|
|
71
|
+
"target": "ES2022",
|
|
72
|
+
"skipLibCheck": true,
|
|
73
|
+
"strictNullChecks": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 4. vite.config.ts
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { defineConfig } from 'vite'
|
|
82
|
+
import { tanstackStart } from '@tanstack/vue-start/plugin/vite'
|
|
83
|
+
import vuePlugin from '@vitejs/plugin-vue'
|
|
84
|
+
import vueJsx from '@vitejs/plugin-vue-jsx'
|
|
85
|
+
|
|
86
|
+
export default defineConfig({
|
|
87
|
+
plugins: [
|
|
88
|
+
tanstackStart(), // MUST come before vue plugin
|
|
89
|
+
vuePlugin(),
|
|
90
|
+
vueJsx(), // Required for JSX/TSX route files
|
|
91
|
+
],
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 5. Router Factory (src/router.tsx)
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { createRouter } from '@tanstack/vue-router'
|
|
99
|
+
import { routeTree } from './routeTree.gen'
|
|
100
|
+
|
|
101
|
+
export function getRouter() {
|
|
102
|
+
const router = createRouter({
|
|
103
|
+
routeTree,
|
|
104
|
+
scrollRestoration: true,
|
|
105
|
+
})
|
|
106
|
+
return router
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 6. Root Route (src/routes/\_\_root.tsx)
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import {
|
|
114
|
+
Outlet,
|
|
115
|
+
createRootRoute,
|
|
116
|
+
HeadContent,
|
|
117
|
+
Scripts,
|
|
118
|
+
Html,
|
|
119
|
+
Body,
|
|
120
|
+
} from '@tanstack/vue-router'
|
|
121
|
+
|
|
122
|
+
export const Route = createRootRoute({
|
|
123
|
+
head: () => ({
|
|
124
|
+
meta: [
|
|
125
|
+
{ charSet: 'utf-8' },
|
|
126
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
127
|
+
{ title: 'My TanStack Start App' },
|
|
128
|
+
],
|
|
129
|
+
}),
|
|
130
|
+
component: RootComponent,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
function RootComponent() {
|
|
134
|
+
return (
|
|
135
|
+
<Html>
|
|
136
|
+
<head>
|
|
137
|
+
<HeadContent />
|
|
138
|
+
</head>
|
|
139
|
+
<Body>
|
|
140
|
+
<Outlet />
|
|
141
|
+
<Scripts />
|
|
142
|
+
</Body>
|
|
143
|
+
</Html>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 7. Index Route (src/routes/index.tsx)
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { createFileRoute } from '@tanstack/vue-router'
|
|
152
|
+
import { createServerFn } from '@tanstack/vue-start'
|
|
153
|
+
|
|
154
|
+
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
|
|
155
|
+
return 'Hello from TanStack Start!'
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
export const Route = createFileRoute('/')({
|
|
159
|
+
loader: () => getGreeting(),
|
|
160
|
+
component: HomePage,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
function HomePage() {
|
|
164
|
+
const greeting = Route.useLoaderData()
|
|
165
|
+
return <h1>{greeting.value}</h1>
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## useServerFn Composable
|
|
170
|
+
|
|
171
|
+
Use `useServerFn` to call server functions from Vue components with automatic redirect handling:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { createServerFn, useServerFn } from '@tanstack/vue-start'
|
|
175
|
+
import { ref } from 'vue'
|
|
176
|
+
|
|
177
|
+
const updatePost = createServerFn({ method: 'POST' })
|
|
178
|
+
.inputValidator((data: { id: string; title: string }) => data)
|
|
179
|
+
.handler(async ({ data }) => {
|
|
180
|
+
await db.posts.update(data.id, { title: data.title })
|
|
181
|
+
return { success: true }
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// In a component setup:
|
|
185
|
+
const updatePostFn = useServerFn(updatePost)
|
|
186
|
+
const title = ref('')
|
|
187
|
+
|
|
188
|
+
async function handleSubmit(postId: string) {
|
|
189
|
+
await updatePostFn({ data: { id: postId, title: title.value } })
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Unlike the React version, `useServerFn` does NOT wrap the returned function in `useCallback` — Vue's `setup()` runs once per component instance, so no memoization is needed.
|
|
194
|
+
|
|
195
|
+
## Vue-Specific Components
|
|
196
|
+
|
|
197
|
+
All routing components from `@tanstack/vue-router` work in Start:
|
|
198
|
+
|
|
199
|
+
- `<Outlet>` — renders matched child route
|
|
200
|
+
- `<Link>` — type-safe navigation with scoped slots
|
|
201
|
+
- `<Navigate>` — declarative redirect
|
|
202
|
+
- `<HeadContent>` — renders head tags (must be in `<head>`)
|
|
203
|
+
- `<Scripts>` — renders body scripts (must be in `<body>`)
|
|
204
|
+
- `<Await>` — renders deferred data with Vue `<Suspense>`
|
|
205
|
+
- `<ClientOnly>` — renders children only after `onMounted`
|
|
206
|
+
- `<CatchBoundary>` — error boundary via `onErrorCaptured`
|
|
207
|
+
- `<Html>` — SSR shell `<html>` wrapper
|
|
208
|
+
- `<Body>` — SSR shell `<body>` wrapper
|
|
209
|
+
|
|
210
|
+
## Composables Reference
|
|
211
|
+
|
|
212
|
+
All composables from `@tanstack/vue-router` work in Start. Most return `Ref<T>` — access via `.value`:
|
|
213
|
+
|
|
214
|
+
- `useRouter()` — router instance (NOT a Ref)
|
|
215
|
+
- `useRouterState()` — `Ref<T>`, subscribe to router state
|
|
216
|
+
- `useNavigate()` — navigation function (NOT a Ref)
|
|
217
|
+
- `useSearch({ from })` — `Ref<T>`, validated search params
|
|
218
|
+
- `useParams({ from })` — `Ref<T>`, path params
|
|
219
|
+
- `useLoaderData({ from })` — `Ref<T>`, loader data
|
|
220
|
+
- `useMatch({ from })` — `Ref<T>`, full route match
|
|
221
|
+
- `useRouteContext({ from })` — `Ref<T>`, route context
|
|
222
|
+
- `Route.useLoaderData()` — `Ref<T>`, typed loader data (preferred in route files)
|
|
223
|
+
- `Route.useSearch()` — `Ref<T>`, typed search params (preferred in route files)
|
|
224
|
+
|
|
225
|
+
## Common Mistakes
|
|
226
|
+
|
|
227
|
+
### 1. CRITICAL: Importing from wrong package
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// WRONG — this is the SPA router, NOT Start
|
|
231
|
+
import { createServerFn } from '@tanstack/vue-router'
|
|
232
|
+
|
|
233
|
+
// CORRECT — server functions come from vue-start
|
|
234
|
+
import { createServerFn } from '@tanstack/vue-start'
|
|
235
|
+
|
|
236
|
+
// CORRECT — routing APIs come from vue-router
|
|
237
|
+
import { createFileRoute, Link } from '@tanstack/vue-router'
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 2. CRITICAL: Forgetting .value in script blocks
|
|
241
|
+
|
|
242
|
+
Most composables return `Ref<T>`. In `<script>`, access via `.value`.
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
// WRONG
|
|
246
|
+
const data = Route.useLoaderData()
|
|
247
|
+
console.log(data.message) // undefined!
|
|
248
|
+
|
|
249
|
+
// CORRECT
|
|
250
|
+
const data = Route.useLoaderData()
|
|
251
|
+
console.log(data.value.message)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### 3. HIGH: Missing Scripts component
|
|
255
|
+
|
|
256
|
+
Without `<Scripts />` in the root route's `<body>`, client JavaScript doesn't load and the app won't hydrate.
|
|
257
|
+
|
|
258
|
+
### 4. HIGH: Vue plugin before Start plugin in Vite config
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
// WRONG
|
|
262
|
+
plugins: [vuePlugin(), tanstackStart()]
|
|
263
|
+
|
|
264
|
+
// CORRECT
|
|
265
|
+
plugins: [tanstackStart(), vuePlugin()]
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 5. HIGH: Using Html/Body incorrectly
|
|
269
|
+
|
|
270
|
+
Vue Start uses `<Html>` and `<Body>` components for the SSR document shell. On the server they render `<html>` and `<body>` tags; on the client they handle hydration properly.
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
// WRONG — plain HTML tags can cause hydration mismatches
|
|
274
|
+
function RootComponent() {
|
|
275
|
+
return (
|
|
276
|
+
<html>
|
|
277
|
+
<body>
|
|
278
|
+
<Outlet />
|
|
279
|
+
</body>
|
|
280
|
+
</html>
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// CORRECT — use Html and Body components
|
|
285
|
+
function RootComponent() {
|
|
286
|
+
return (
|
|
287
|
+
<Html>
|
|
288
|
+
<head>
|
|
289
|
+
<HeadContent />
|
|
290
|
+
</head>
|
|
291
|
+
<Body>
|
|
292
|
+
<Outlet />
|
|
293
|
+
<Scripts />
|
|
294
|
+
</Body>
|
|
295
|
+
</Html>
|
|
296
|
+
)
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Cross-References
|
|
301
|
+
|
|
302
|
+
- [start-core](../../../start-client-core/skills/start-core/SKILL.md) — core Start concepts
|
|
303
|
+
- [router-core](../../../router-core/skills/router-core/SKILL.md) — routing fundamentals
|
|
304
|
+
- [vue-router](../../../vue-router/skills/vue-router/SKILL.md) — Vue Router composables and components
|