@tanstack/solid-start 2.0.0-alpha.4 → 2.0.0-alpha.5
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/solid-start/SKILL.md +280 -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/solid-start",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.5",
|
|
4
4
|
"description": "Modern and scalable routing for Solid 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/solid-start-client": "2.0.0-alpha.
|
|
102
|
-
"@tanstack/solid-start-server": "2.0.0-alpha.
|
|
103
|
-
"@tanstack/start-plugin-core": "1.
|
|
104
|
-
"@tanstack/solid-router": "2.0.0-alpha.
|
|
105
|
-
"@tanstack/start-client-core": "1.166.
|
|
106
|
-
"@tanstack/start-server-core": "1.166.
|
|
104
|
+
"@tanstack/solid-start-client": "2.0.0-alpha.5",
|
|
105
|
+
"@tanstack/solid-start-server": "2.0.0-alpha.5",
|
|
106
|
+
"@tanstack/start-plugin-core": "1.167.1",
|
|
107
|
+
"@tanstack/solid-router": "2.0.0-alpha.5",
|
|
108
|
+
"@tanstack/start-client-core": "1.166.13",
|
|
109
|
+
"@tanstack/start-server-core": "1.166.13"
|
|
107
110
|
},
|
|
108
111
|
"devDependencies": {
|
|
112
|
+
"@tanstack/intent": "^0.0.14",
|
|
109
113
|
"vite": "*",
|
|
110
114
|
"@tanstack/router-utils": "1.161.6"
|
|
111
115
|
},
|
|
@@ -114,6 +118,9 @@
|
|
|
114
118
|
"@solidjs/web": "2.0.0-beta.3",
|
|
115
119
|
"vite": ">=7.0.0"
|
|
116
120
|
},
|
|
121
|
+
"bin": {
|
|
122
|
+
"intent": "./bin/intent.js"
|
|
123
|
+
},
|
|
117
124
|
"scripts": {
|
|
118
125
|
"clean": "rimraf ./dist && rimraf ./coverage",
|
|
119
126
|
"test": "pnpm test:build",
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: solid-start
|
|
3
|
+
description: >-
|
|
4
|
+
Solid bindings for TanStack Start: useServerFn hook, tanstackStart
|
|
5
|
+
Vite plugin, StartClient, StartServer, Solid-specific setup,
|
|
6
|
+
re-exports from @tanstack/start-client-core. Full project setup
|
|
7
|
+
with Solid.
|
|
8
|
+
type: framework
|
|
9
|
+
library: tanstack-start
|
|
10
|
+
library_version: '1.166.2'
|
|
11
|
+
framework: solid
|
|
12
|
+
requires:
|
|
13
|
+
- start-core
|
|
14
|
+
sources:
|
|
15
|
+
- TanStack/router:packages/solid-start/src
|
|
16
|
+
- TanStack/router:docs/start/framework/solid/build-from-scratch.md
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Solid Start (`@tanstack/solid-start`)
|
|
20
|
+
|
|
21
|
+
This skill builds on start-core. Read [start-core](../../../start-client-core/skills/start-core/SKILL.md) first for foundational concepts.
|
|
22
|
+
|
|
23
|
+
This skill covers the Solid-specific bindings, setup, and patterns for TanStack Start.
|
|
24
|
+
|
|
25
|
+
> **CRITICAL**: All code is ISOMORPHIC by default. Loaders run on BOTH server and client. Use `createServerFn` for server-only logic.
|
|
26
|
+
|
|
27
|
+
> **CRITICAL**: Do not confuse `@tanstack/solid-start` with SolidStart (`@solidjs/start`). They are completely different frameworks with different APIs.
|
|
28
|
+
|
|
29
|
+
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
|
|
30
|
+
|
|
31
|
+
## Package API Surface
|
|
32
|
+
|
|
33
|
+
`@tanstack/solid-start` re-exports everything from `@tanstack/start-client-core` plus:
|
|
34
|
+
|
|
35
|
+
- `useServerFn` — Solid hook for calling server functions from components
|
|
36
|
+
|
|
37
|
+
All core APIs (`createServerFn`, `createMiddleware`, `createStart`, `createIsomorphicFn`, `createServerOnlyFn`, `createClientOnlyFn`) are available from `@tanstack/solid-start`.
|
|
38
|
+
|
|
39
|
+
Server utilities (`getRequest`, `getRequestHeader`, `setResponseHeader`, `setCookie`, `getCookie`, `useSession`) are imported from `@tanstack/solid-start/server`.
|
|
40
|
+
|
|
41
|
+
## Full Project Setup
|
|
42
|
+
|
|
43
|
+
### 1. Install Dependencies
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm i @tanstack/solid-start @tanstack/solid-router solid-js
|
|
47
|
+
npm i -D vite vite-plugin-solid typescript
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. package.json
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"type": "module",
|
|
55
|
+
"scripts": {
|
|
56
|
+
"dev": "vite dev",
|
|
57
|
+
"build": "vite build",
|
|
58
|
+
"start": "node .output/server/index.mjs"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. tsconfig.json
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"compilerOptions": {
|
|
68
|
+
"jsx": "preserve",
|
|
69
|
+
"jsxImportSource": "solid-js",
|
|
70
|
+
"moduleResolution": "Bundler",
|
|
71
|
+
"module": "ESNext",
|
|
72
|
+
"target": "ES2022",
|
|
73
|
+
"skipLibCheck": true,
|
|
74
|
+
"strictNullChecks": true
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 4. vite.config.ts
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { defineConfig } from 'vite'
|
|
83
|
+
import { tanstackStart } from '@tanstack/solid-start/plugin/vite'
|
|
84
|
+
import solidPlugin from 'vite-plugin-solid'
|
|
85
|
+
|
|
86
|
+
export default defineConfig({
|
|
87
|
+
plugins: [
|
|
88
|
+
tanstackStart(), // MUST come before solid plugin
|
|
89
|
+
solidPlugin({ ssr: true }),
|
|
90
|
+
],
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 5. Router Factory (src/router.tsx)
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { createRouter } from '@tanstack/solid-router'
|
|
98
|
+
import { routeTree } from './routeTree.gen'
|
|
99
|
+
|
|
100
|
+
export function getRouter() {
|
|
101
|
+
const router = createRouter({
|
|
102
|
+
routeTree,
|
|
103
|
+
scrollRestoration: true,
|
|
104
|
+
})
|
|
105
|
+
return router
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 6. Root Route (src/routes/\_\_root.tsx)
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import {
|
|
113
|
+
Outlet,
|
|
114
|
+
createRootRoute,
|
|
115
|
+
HeadContent,
|
|
116
|
+
Scripts,
|
|
117
|
+
} from '@tanstack/solid-router'
|
|
118
|
+
import { HydrationScript } from 'solid-js/web'
|
|
119
|
+
import { Suspense } from 'solid-js'
|
|
120
|
+
|
|
121
|
+
export const Route = createRootRoute({
|
|
122
|
+
head: () => ({
|
|
123
|
+
meta: [
|
|
124
|
+
{ charSet: 'utf-8' },
|
|
125
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
126
|
+
{ title: 'My TanStack Start App' },
|
|
127
|
+
],
|
|
128
|
+
}),
|
|
129
|
+
// shellComponent renders the HTML document shell (always SSR'd)
|
|
130
|
+
shellComponent: RootDocument,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
function RootDocument(props: { children: any }) {
|
|
134
|
+
return (
|
|
135
|
+
<html>
|
|
136
|
+
<head>
|
|
137
|
+
<HydrationScript />
|
|
138
|
+
</head>
|
|
139
|
+
<body>
|
|
140
|
+
<HeadContent />
|
|
141
|
+
<Suspense>{props.children}</Suspense>
|
|
142
|
+
<Scripts />
|
|
143
|
+
</body>
|
|
144
|
+
</html>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 7. Index Route (src/routes/index.tsx)
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { createFileRoute } from '@tanstack/solid-router'
|
|
153
|
+
import { createServerFn } from '@tanstack/solid-start'
|
|
154
|
+
|
|
155
|
+
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
|
|
156
|
+
return 'Hello from TanStack Start!'
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
export const Route = createFileRoute('/')({
|
|
160
|
+
loader: () => getGreeting(),
|
|
161
|
+
component: HomePage,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
function HomePage() {
|
|
165
|
+
const greeting = Route.useLoaderData()
|
|
166
|
+
return <h1>{greeting()}</h1>
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## useServerFn Hook
|
|
171
|
+
|
|
172
|
+
Use `useServerFn` to call server functions from Solid components with automatic redirect handling:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { createServerFn, useServerFn } from '@tanstack/solid-start'
|
|
176
|
+
import { createSignal } from 'solid-js'
|
|
177
|
+
|
|
178
|
+
const updatePost = createServerFn({ method: 'POST' })
|
|
179
|
+
.inputValidator((data: { id: string; title: string }) => data)
|
|
180
|
+
.handler(async ({ data }) => {
|
|
181
|
+
await db.posts.update(data.id, { title: data.title })
|
|
182
|
+
return { success: true }
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
function EditPostForm(props: { postId: string }) {
|
|
186
|
+
const updatePostFn = useServerFn(updatePost)
|
|
187
|
+
const [title, setTitle] = createSignal('')
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<form
|
|
191
|
+
onSubmit={async (e) => {
|
|
192
|
+
e.preventDefault()
|
|
193
|
+
await updatePostFn({ data: { id: props.postId, title: title() } })
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
<input value={title()} onInput={(e) => setTitle(e.target.value)} />
|
|
197
|
+
<button type="submit">Save</button>
|
|
198
|
+
</form>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Unlike the React version, `useServerFn` does NOT wrap the returned function in any memoization (no `useCallback` equivalent needed — Solid's `setup` runs once).
|
|
204
|
+
|
|
205
|
+
## Solid-Specific Components
|
|
206
|
+
|
|
207
|
+
All routing components from `@tanstack/solid-router` work in Start:
|
|
208
|
+
|
|
209
|
+
- `<Outlet>` — renders matched child route
|
|
210
|
+
- `<Link>` — type-safe navigation
|
|
211
|
+
- `<Navigate>` — declarative redirect
|
|
212
|
+
- `<HeadContent>` — renders head tags via `@solidjs/meta` (must be in `<body>` — uses portals to inject into `<head>`)
|
|
213
|
+
- `<Scripts>` — renders body scripts (must be in `<body>`)
|
|
214
|
+
- `<Await>` — renders deferred data with `<Suspense>`
|
|
215
|
+
- `<ClientOnly>` — renders children only after hydration
|
|
216
|
+
- `<CatchBoundary>` — error boundary wrapping `Solid.ErrorBoundary`
|
|
217
|
+
|
|
218
|
+
## Hooks Reference
|
|
219
|
+
|
|
220
|
+
All hooks from `@tanstack/solid-router` work in Start. Most return `Accessor<T>` — call the accessor to read:
|
|
221
|
+
|
|
222
|
+
- `useRouter()` — router instance (NOT an Accessor)
|
|
223
|
+
- `useRouterState()` — `Accessor<T>`, subscribe to router state
|
|
224
|
+
- `useNavigate()` — navigation function (NOT an Accessor)
|
|
225
|
+
- `useSearch({ from })` — `Accessor<T>`, validated search params
|
|
226
|
+
- `useParams({ from })` — `Accessor<T>`, path params
|
|
227
|
+
- `useLoaderData({ from })` — `Accessor<T>`, loader data
|
|
228
|
+
- `useMatch({ from })` — `Accessor<T>`, full route match
|
|
229
|
+
- `useRouteContext({ from })` — `Accessor<T>`, route context
|
|
230
|
+
- `Route.useLoaderData()` — `Accessor<T>`, typed loader data (preferred in route files)
|
|
231
|
+
- `Route.useSearch()` — `Accessor<T>`, typed search params (preferred in route files)
|
|
232
|
+
|
|
233
|
+
## Common Mistakes
|
|
234
|
+
|
|
235
|
+
### 1. CRITICAL: Importing from wrong package
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
// WRONG — this is the SPA router, NOT Start
|
|
239
|
+
import { createServerFn } from '@tanstack/solid-router'
|
|
240
|
+
|
|
241
|
+
// CORRECT — server functions come from solid-start
|
|
242
|
+
import { createServerFn } from '@tanstack/solid-start'
|
|
243
|
+
|
|
244
|
+
// CORRECT — routing APIs come from solid-router (re-exported by Start too)
|
|
245
|
+
import { createFileRoute, Link } from '@tanstack/solid-router'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 2. CRITICAL: Forgetting to call Accessor
|
|
249
|
+
|
|
250
|
+
Most hooks return `Accessor<T>`. Must call to read the value.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
// WRONG
|
|
254
|
+
const data = Route.useLoaderData()
|
|
255
|
+
return <h1>{data.message}</h1>
|
|
256
|
+
|
|
257
|
+
// CORRECT
|
|
258
|
+
const data = Route.useLoaderData()
|
|
259
|
+
return <h1>{data().message}</h1>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 3. HIGH: Missing Scripts component
|
|
263
|
+
|
|
264
|
+
Without `<Scripts />` in the root route's `<body>`, client JavaScript doesn't load and the app won't hydrate.
|
|
265
|
+
|
|
266
|
+
### 4. HIGH: Solid plugin before Start plugin in Vite config
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
// WRONG
|
|
270
|
+
plugins: [solidPlugin(), tanstackStart()]
|
|
271
|
+
|
|
272
|
+
// CORRECT
|
|
273
|
+
plugins: [tanstackStart(), solidPlugin()]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Cross-References
|
|
277
|
+
|
|
278
|
+
- [start-core](../../../start-client-core/skills/start-core/SKILL.md) — core Start concepts
|
|
279
|
+
- [router-core](../../../router-core/skills/router-core/SKILL.md) — routing fundamentals
|
|
280
|
+
- [solid-router](../../../solid-router/skills/solid-router/SKILL.md) — Solid Router hooks and components
|