@tanstack/cta-framework-react-cra 0.46.2 → 0.48.0

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 (37) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/add-ons/better-auth/README.md +32 -0
  3. package/add-ons/better-auth/assets/_dot_env.local.append +3 -0
  4. package/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +43 -0
  5. package/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
  6. package/add-ons/better-auth/assets/src/lib/auth.ts +7 -0
  7. package/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
  8. package/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +232 -0
  9. package/add-ons/better-auth/info.json +26 -0
  10. package/add-ons/better-auth/logo.svg +7 -0
  11. package/add-ons/better-auth/package.json +5 -0
  12. package/add-ons/better-auth/small-logo.svg +9 -0
  13. package/add-ons/start/assets/src/routes/demo/start.api-request.tsx.ejs +16 -1
  14. package/add-ons/start/assets/src/routes/demo/start.css.ejs +43 -0
  15. package/add-ons/start/assets/src/routes/demo/start.server-funcs.tsx.ejs +33 -1
  16. package/add-ons/start/assets/src/routes/demo/start.ssr.spa-mode.tsx.ejs +0 -1
  17. package/add-ons/start/assets/src/routes/index.tsx.ejs +4 -2
  18. package/add-ons/start/assets/vite.config.ts.ejs +2 -1
  19. package/add-ons/start/info.json +3 -1
  20. package/add-ons/tRPC/assets/src/routes/api.trpc.$.tsx +1 -0
  21. package/hosts/cloudflare/info.json +1 -0
  22. package/hosts/cloudflare/{package.json → package.json.ejs} +1 -1
  23. package/hosts/netlify/info.json +1 -0
  24. package/hosts/nitro/info.json +1 -0
  25. package/package.json +2 -2
  26. package/project/base/src/components/Header.css.ejs +18 -0
  27. package/project/base/src/components/Header.tsx.ejs +8 -1
  28. package/project/base/vite.config.ts.ejs +2 -1
  29. package/tests/snapshots/react-cra/cr-js-form-npm.json +3 -2
  30. package/tests/snapshots/react-cra/cr-js-npm.json +2 -1
  31. package/tests/snapshots/react-cra/cr-ts-npm.json +2 -1
  32. package/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json +1 -1
  33. package/tests/snapshots/react-cra/cr-ts-start-npm.json +1 -1
  34. package/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json +1 -1
  35. package/tests/snapshots/react-cra/fr-ts-biome-npm.json +3 -2
  36. package/tests/snapshots/react-cra/fr-ts-npm.json +2 -1
  37. package/tests/snapshots/react-cra/fr-ts-tw-npm.json +1 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # @tanstack/cta-framework-react-cra
2
+
3
+ ## 0.48.0
4
+
5
+ ### Minor Changes
6
+
7
+ - no will prompt about overriding a directory that has contents ([#289](https://github.com/TanStack/create-tsrouter-app/pull/289))
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`3087532`](https://github.com/TanStack/create-tsrouter-app/commit/308753249af11bf5c9e374789e973a934c753520)]:
12
+ - @tanstack/cta-engine@0.48.0
13
+
14
+ ## 0.47.0
15
+
16
+ ### Minor Changes
17
+
18
+ - Smakll content fixes ([`7647683`](https://github.com/TanStack/create-tsrouter-app/commit/76476838fc427d71535881b959530307ca4664a2))
19
+
20
+ - allowing for no tailwind ([#151](https://github.com/TanStack/create-tsrouter-app/pull/151))
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [[`7647683`](https://github.com/TanStack/create-tsrouter-app/commit/76476838fc427d71535881b959530307ca4664a2), [`f1f58fe`](https://github.com/TanStack/create-tsrouter-app/commit/f1f58feed7d7df1e0c5e0fc4dd3af02e11df09e5)]:
25
+ - @tanstack/cta-engine@0.47.0
@@ -0,0 +1,32 @@
1
+ ## Setting up Better Auth
2
+
3
+ 1. Generate and set the `BETTER_AUTH_SECRET` environment variable in your `.env.local`:
4
+
5
+ ```bash
6
+ npx @better-auth/cli secret
7
+ ```
8
+
9
+ 2. Visit the [Better Auth documentation](https://www.better-auth.com) to unlock the full potential of authentication in your app.
10
+
11
+ ### Adding a Database (Optional)
12
+
13
+ Better Auth can work in stateless mode, but to persist user data, add a database:
14
+
15
+ ```typescript
16
+ // src/lib/auth.ts
17
+ import { betterAuth } from "better-auth";
18
+ import { Pool } from "pg";
19
+
20
+ export const auth = betterAuth({
21
+ database: new Pool({
22
+ connectionString: process.env.DATABASE_URL,
23
+ }),
24
+ // ... rest of config
25
+ });
26
+ ```
27
+
28
+ Then run migrations:
29
+
30
+ ```bash
31
+ npx @better-auth/cli migrate
32
+ ```
@@ -0,0 +1,3 @@
1
+ # Better Auth configuration
2
+ BETTER_AUTH_URL=http://localhost:3000
3
+ BETTER_AUTH_SECRET= # Generate a secret key: `npx @better-auth/cli secret`
@@ -0,0 +1,43 @@
1
+ import { authClient } from "@/lib/auth-client";
2
+ import { Link } from "@tanstack/react-router";
3
+
4
+ export default function BetterAuthHeader() {
5
+ const { data: session, isPending } = authClient.useSession();
6
+
7
+ if (isPending) {
8
+ return (
9
+ <div className="h-8 w-8 bg-neutral-100 dark:bg-neutral-800 animate-pulse" />
10
+ );
11
+ }
12
+
13
+ if (session?.user) {
14
+ return (
15
+ <div className="flex items-center gap-2">
16
+ {session.user.image ? (
17
+ <img src={session.user.image} alt="" className="h-8 w-8" />
18
+ ) : (
19
+ <div className="h-8 w-8 bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center">
20
+ <span className="text-xs font-medium text-neutral-600 dark:text-neutral-400">
21
+ {session.user.name?.charAt(0).toUpperCase() || "U"}
22
+ </span>
23
+ </div>
24
+ )}
25
+ <button
26
+ onClick={() => authClient.signOut()}
27
+ className="flex-1 h-9 px-4 text-sm font-medium bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-50 border border-neutral-300 dark:border-neutral-700 hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors"
28
+ >
29
+ Sign out
30
+ </button>
31
+ </div>
32
+ );
33
+ }
34
+
35
+ return (
36
+ <Link
37
+ to="/demo/better-auth"
38
+ className="h-9 px-4 text-sm font-medium bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-50 border border-neutral-300 dark:border-neutral-700 hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors inline-flex items-center"
39
+ >
40
+ Sign in
41
+ </Link>
42
+ );
43
+ }
@@ -0,0 +1,3 @@
1
+ import { createAuthClient } from 'better-auth/react'
2
+
3
+ export const authClient = createAuthClient()
@@ -0,0 +1,7 @@
1
+ import { betterAuth } from 'better-auth'
2
+
3
+ export const auth = betterAuth({
4
+ emailAndPassword: {
5
+ enabled: true,
6
+ },
7
+ })
@@ -0,0 +1,11 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+ import { auth } from '@/lib/auth'
3
+
4
+ export const Route = createFileRoute('/api/auth/$')({
5
+ server: {
6
+ handlers: {
7
+ GET: ({ request }) => auth.handler(request),
8
+ POST: ({ request }) => auth.handler(request),
9
+ },
10
+ },
11
+ })
@@ -0,0 +1,232 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { useState } from "react";
3
+ import { authClient } from "@/lib/auth-client";
4
+
5
+ export const Route = createFileRoute("/demo/better-auth")({
6
+ component: BetterAuthDemo,
7
+ });
8
+
9
+ function BetterAuthDemo() {
10
+ const { data: session, isPending } = authClient.useSession();
11
+ const [isSignUp, setIsSignUp] = useState(false);
12
+ const [email, setEmail] = useState("");
13
+ const [password, setPassword] = useState("");
14
+ const [name, setName] = useState("");
15
+ const [error, setError] = useState("");
16
+ const [loading, setLoading] = useState(false);
17
+
18
+ if (isPending) {
19
+ return (
20
+ <div className="flex items-center justify-center py-10">
21
+ <div className="h-5 w-5 animate-spin rounded-full border-2 border-neutral-200 border-t-neutral-900 dark:border-neutral-800 dark:border-t-neutral-100" />
22
+ </div>
23
+ );
24
+ }
25
+
26
+ if (session?.user) {
27
+ return (
28
+ <div className="flex justify-center py-10 px-4">
29
+ <div className="w-full max-w-md p-6 space-y-6">
30
+ <div className="space-y-1.5">
31
+ <h1 className="text-lg font-semibold leading-none tracking-tight">
32
+ Welcome back
33
+ </h1>
34
+ <p className="text-sm text-neutral-500 dark:text-neutral-400">
35
+ You're signed in as {session.user.email}
36
+ </p>
37
+ </div>
38
+
39
+ <div className="flex items-center gap-3">
40
+ {session.user.image ? (
41
+ <img src={session.user.image} alt="" className="h-10 w-10" />
42
+ ) : (
43
+ <div className="h-10 w-10 bg-neutral-200 dark:bg-neutral-800 flex items-center justify-center">
44
+ <span className="text-sm font-medium text-neutral-600 dark:text-neutral-400">
45
+ {session.user.name?.charAt(0).toUpperCase() || "U"}
46
+ </span>
47
+ </div>
48
+ )}
49
+ <div className="flex-1 min-w-0">
50
+ <p className="text-sm font-medium truncate">
51
+ {session.user.name}
52
+ </p>
53
+ <p className="text-xs text-neutral-500 dark:text-neutral-400 truncate">
54
+ {session.user.email}
55
+ </p>
56
+ </div>
57
+ </div>
58
+
59
+ <button
60
+ onClick={() => authClient.signOut()}
61
+ className="w-full h-9 px-4 text-sm font-medium border border-neutral-300 dark:border-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
62
+ >
63
+ Sign out
64
+ </button>
65
+
66
+ <p className="text-xs text-center text-neutral-400 dark:text-neutral-500">
67
+ Built with{" "}
68
+ <a
69
+ href="https://better-auth.com"
70
+ target="_blank"
71
+ rel="noopener noreferrer"
72
+ className="font-medium hover:text-neutral-600 dark:hover:text-neutral-300"
73
+ >
74
+ BETTER-AUTH
75
+ </a>
76
+ .
77
+ </p>
78
+ </div>
79
+ </div>
80
+ );
81
+ }
82
+
83
+ const handleSubmit = async (e: React.FormEvent) => {
84
+ e.preventDefault();
85
+ setError("");
86
+ setLoading(true);
87
+
88
+ try {
89
+ if (isSignUp) {
90
+ const result = await authClient.signUp.email({
91
+ email,
92
+ password,
93
+ name,
94
+ });
95
+ if (result.error) {
96
+ setError(result.error.message || "Sign up failed");
97
+ }
98
+ } else {
99
+ const result = await authClient.signIn.email({
100
+ email,
101
+ password,
102
+ });
103
+ if (result.error) {
104
+ setError(result.error.message || "Sign in failed");
105
+ }
106
+ }
107
+ } catch (err) {
108
+ setError("An unexpected error occurred");
109
+ } finally {
110
+ setLoading(false);
111
+ }
112
+ };
113
+
114
+ return (
115
+ <div className="flex justify-center py-10 px-4">
116
+ <div className="w-full max-w-md p-6">
117
+ <h1 className="text-lg font-semibold leading-none tracking-tight">
118
+ {isSignUp ? "Create an account" : "Sign in"}
119
+ </h1>
120
+ <p className="text-sm text-neutral-500 dark:text-neutral-400 mt-2 mb-6">
121
+ {isSignUp
122
+ ? "Enter your information to create an account"
123
+ : "Enter your email below to login to your account"}
124
+ </p>
125
+
126
+ <form onSubmit={handleSubmit} className="grid gap-4">
127
+ {isSignUp && (
128
+ <div className="grid gap-2">
129
+ <label
130
+ htmlFor="name"
131
+ className="text-sm font-medium leading-none"
132
+ >
133
+ Name
134
+ </label>
135
+ <input
136
+ id="name"
137
+ type="text"
138
+ value={name}
139
+ onChange={(e) => setName(e.target.value)}
140
+ className="flex h-9 w-full border border-neutral-300 dark:border-neutral-700 bg-transparent px-3 text-sm focus:outline-none focus:border-neutral-900 dark:focus:border-neutral-100 disabled:cursor-not-allowed disabled:opacity-50"
141
+ required
142
+ />
143
+ </div>
144
+ )}
145
+
146
+ <div className="grid gap-2">
147
+ <label htmlFor="email" className="text-sm font-medium leading-none">
148
+ Email
149
+ </label>
150
+ <input
151
+ id="email"
152
+ type="email"
153
+ value={email}
154
+ onChange={(e) => setEmail(e.target.value)}
155
+ className="flex h-9 w-full border border-neutral-300 dark:border-neutral-700 bg-transparent px-3 text-sm focus:outline-none focus:border-neutral-900 dark:focus:border-neutral-100 disabled:cursor-not-allowed disabled:opacity-50"
156
+ required
157
+ />
158
+ </div>
159
+
160
+ <div className="grid gap-2">
161
+ <label
162
+ htmlFor="password"
163
+ className="text-sm font-medium leading-none"
164
+ >
165
+ Password
166
+ </label>
167
+ <input
168
+ id="password"
169
+ type="password"
170
+ value={password}
171
+ onChange={(e) => setPassword(e.target.value)}
172
+ className="flex h-9 w-full border border-neutral-300 dark:border-neutral-700 bg-transparent px-3 text-sm focus:outline-none focus:border-neutral-900 dark:focus:border-neutral-100 disabled:cursor-not-allowed disabled:opacity-50"
173
+ required
174
+ minLength={8}
175
+ />
176
+ </div>
177
+
178
+ {error && (
179
+ <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 p-3">
180
+ <p className="text-sm text-red-600 dark:text-red-400">{error}</p>
181
+ </div>
182
+ )}
183
+
184
+ <button
185
+ type="submit"
186
+ disabled={loading}
187
+ className="w-full h-9 px-4 text-sm font-medium text-white bg-neutral-900 hover:bg-neutral-800 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-200 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
188
+ >
189
+ {loading ? (
190
+ <span className="flex items-center justify-center gap-2">
191
+ <span className="h-4 w-4 animate-spin rounded-full border-2 border-neutral-400 border-t-white dark:border-neutral-600 dark:border-t-neutral-900" />
192
+ <span>Please wait</span>
193
+ </span>
194
+ ) : isSignUp ? (
195
+ "Create account"
196
+ ) : (
197
+ "Sign in"
198
+ )}
199
+ </button>
200
+ </form>
201
+
202
+ <div className="mt-4 text-center">
203
+ <button
204
+ type="button"
205
+ onClick={() => {
206
+ setIsSignUp(!isSignUp);
207
+ setError("");
208
+ }}
209
+ className="text-sm text-neutral-500 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors"
210
+ >
211
+ {isSignUp
212
+ ? "Already have an account? Sign in"
213
+ : "Don't have an account? Sign up"}
214
+ </button>
215
+ </div>
216
+
217
+ <p className="mt-6 text-xs text-center text-neutral-400 dark:text-neutral-500">
218
+ Built with{" "}
219
+ <a
220
+ href="https://better-auth.com"
221
+ target="_blank"
222
+ rel="noopener noreferrer"
223
+ className="font-medium hover:text-neutral-600 dark:hover:text-neutral-300"
224
+ >
225
+ BETTER-AUTH
226
+ </a>
227
+ .
228
+ </p>
229
+ </div>
230
+ </div>
231
+ );
232
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "Better Auth",
3
+ "description": "Add Better Auth authentication to your application.",
4
+ "phase": "add-on",
5
+ "type": "add-on",
6
+ "priority": 26,
7
+ "link": "https://www.better-auth.com",
8
+ "modes": ["file-router"],
9
+ "tailwind": true,
10
+ "dependsOn": ["start"],
11
+ "routes": [
12
+ {
13
+ "url": "/demo/better-auth",
14
+ "name": "Better Auth",
15
+ "path": "src/routes/demo/better-auth.tsx",
16
+ "jsName": "BetterAuthDemo"
17
+ }
18
+ ],
19
+ "integrations": [
20
+ {
21
+ "type": "header-user",
22
+ "jsName": "BetterAuthHeader",
23
+ "path": "src/integrations/better-auth/header-user.tsx"
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">
3
+ <path d="M0 0 C165 0 330 0 500 0 C500 165 500 330 500 500 C335 500 170 500 0 500 C0 335 0 170 0 0 Z " fill="#000000" transform="translate(0,0)"/>
4
+ <path d="M0 0 C28.71 0 57.42 0 87 0 C87 27.39 87 54.78 87 83 C119.01 83 151.02 83 184 83 C184 55.61 184 28.22 184 0 C242.41 0 300.82 0 361 0 C361 85.47 361 170.94 361 259 C302.59 259 244.18 259 184 259 C184 231.61 184 204.22 184 176 C151.99 176 119.98 176 87 176 C87 203.39 87 230.78 87 259 C58.29 259 29.58 259 0 259 C0 173.53 0 88.06 0 0 Z " fill="#FCFCFC" transform="translate(69,121)"/>
5
+ <path d="M0 0 C58.41 0 116.82 0 177 0 C177 85.47 177 170.94 177 259 C118.59 259 60.18 259 0 259 C0 231.61 0 204.22 0 176 C28.05 176 56.1 176 85 176 C85 145.31 85 114.62 85 83 C56.95 83 28.9 83 0 83 C0 55.61 0 28.22 0 0 Z " fill="#FFFFFF" transform="translate(253,121)"/>
6
+ <path d="M0 0 C27.72 0 55.44 0 84 0 C84 30.03 84 60.06 84 91 C56.28 91 28.56 91 0 91 C0 60.97 0 30.94 0 0 Z " fill="#000000" transform="translate(253,205)"/>
7
+ </svg>
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "better-auth": "^1.4.12"
4
+ }
5
+ }
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
3
+ <g id="surface1">
4
+ <path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 0 0 C 42.238281 0 84.480469 0 128 0 C 128 42.238281 128 84.480469 128 128 C 85.761719 128 43.519531 128 0 128 C 0 85.761719 0 43.519531 0 0 Z M 0 0 "/>
5
+ <path style=" stroke:none;fill-rule:nonzero;fill:rgb(98.823529%,98.823529%,98.823529%);fill-opacity:1;" d="M 17.664062 30.976562 C 25.015625 30.976562 32.363281 30.976562 39.9375 30.976562 C 39.9375 37.988281 39.9375 45 39.9375 52.222656 C 48.128906 52.222656 56.324219 52.222656 64.769531 52.222656 C 64.769531 45.210938 64.769531 38.199219 64.769531 30.976562 C 79.722656 30.976562 94.675781 30.976562 110.078125 30.976562 C 110.078125 52.855469 110.078125 74.738281 110.078125 97.28125 C 95.128906 97.28125 80.175781 97.28125 64.769531 97.28125 C 64.769531 90.269531 64.769531 83.257812 64.769531 76.03125 C 56.574219 76.03125 48.378906 76.03125 39.9375 76.03125 C 39.9375 83.042969 39.9375 90.054688 39.9375 97.28125 C 32.585938 97.28125 25.238281 97.28125 17.664062 97.28125 C 17.664062 75.398438 17.664062 53.519531 17.664062 30.976562 Z M 17.664062 30.976562 "/>
6
+ <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 64.769531 30.976562 C 79.722656 30.976562 94.675781 30.976562 110.078125 30.976562 C 110.078125 52.855469 110.078125 74.738281 110.078125 97.28125 C 95.128906 97.28125 80.175781 97.28125 64.769531 97.28125 C 64.769531 90.269531 64.769531 83.257812 64.769531 76.03125 C 71.949219 76.03125 79.128906 76.03125 86.527344 76.03125 C 86.527344 68.175781 86.527344 60.320312 86.527344 52.222656 C 79.347656 52.222656 72.167969 52.222656 64.769531 52.222656 C 64.769531 45.210938 64.769531 38.199219 64.769531 30.976562 Z M 64.769531 30.976562 "/>
7
+ <path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 64.769531 52.480469 C 71.863281 52.480469 78.960938 52.480469 86.273438 52.480469 C 86.273438 60.167969 86.273438 67.855469 86.273438 75.777344 C 79.175781 75.777344 72.078125 75.777344 64.769531 75.777344 C 64.769531 68.089844 64.769531 60.402344 64.769531 52.480469 Z M 64.769531 52.480469 "/>
8
+ </g>
9
+ </svg>
@@ -3,7 +3,9 @@ import { useQuery } from '@tanstack/react-query'
3
3
  <% } else { %>
4
4
  import { useEffect, useState } from 'react'
5
5
  <% } %>
6
- import { createFileRoute } from '@tanstack/react-router'
6
+ import { createFileRoute } from '@tanstack/react-router'<% if (!tailwind) { %>
7
+ import './start.css'
8
+ <% } %>
7
9
 
8
10
  function getNames() {
9
11
  return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)
@@ -27,6 +29,7 @@ function Home() {
27
29
  }, [])
28
30
  <% } %>
29
31
  return (
32
+ <% if (tailwind) { %>
30
33
  <div
31
34
  className="flex items-center justify-center min-h-screen p-4 text-white"
32
35
  style={{
@@ -49,5 +52,17 @@ function Home() {
49
52
  </ul>
50
53
  </div>
51
54
  </div>
55
+ <% } else { %>
56
+ <div className="api-page">
57
+ <div className="content">
58
+ <h1>Start API Request Demo - Names List</h1>
59
+ <ul>
60
+ {names.map((name) => (
61
+ <li key={name}>{name}</li>
62
+ ))}
63
+ </ul>
64
+ </div>
65
+ </div>
66
+ <% } %>
52
67
  )
53
68
  }
@@ -0,0 +1,43 @@
1
+ <% if (tailwind) { ignoreFile() } %>.api-page {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ min-height: 100vh;
6
+ padding: 1rem;
7
+ color: #fff;
8
+ }
9
+
10
+ .api-page .content {
11
+ width: 100%;
12
+ max-width: 2xl;
13
+ padding: 8rem;
14
+ border-radius: 1rem;
15
+ backdrop-filter: blur(1rem);
16
+ background-color: rgba(0, 0, 0, 0.5);
17
+ box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.1);
18
+ border: 0.5rem solid rgba(0, 0, 0, 0.1);
19
+ }
20
+
21
+ .api-page .content h1 {
22
+ font-size: 2rem;
23
+ margin-bottom: 1rem;
24
+ }
25
+
26
+ .api-page .content ul {
27
+ margin-bottom: 1rem;
28
+ list-style: none;
29
+ padding: 0;
30
+ }
31
+
32
+ .api-page .content li {
33
+ background-color: rgba(255, 255, 255, 0.1);
34
+ padding: 0.5rem;
35
+ border-radius: 0.5rem;
36
+ border: 1px solid rgba(255, 255, 255, 0.2);
37
+ backdrop-filter: blur(0.5rem);
38
+ box-shadow: 0 0 0.5rem 0 rgba(255, 255, 255, 0.1);
39
+ }
40
+
41
+ .api-page .content li span {
42
+ font-size: 1.2rem;
43
+ }
@@ -42,7 +42,9 @@ function Home() {
42
42
  <% } else { %>import fs from 'node:fs'
43
43
  import { useCallback, useState } from 'react'
44
44
  import { createFileRoute, useRouter } from '@tanstack/react-router'
45
- import { createServerFn } from '@tanstack/react-start'
45
+ import { createServerFn } from '@tanstack/react-start'<% if (!tailwind) { %>
46
+ import './start.css'
47
+ <% } %>
46
48
 
47
49
  /*
48
50
  const loggingMiddleware = createMiddleware().server(
@@ -104,6 +106,7 @@ function Home() {
104
106
  }, [addTodo, todo])
105
107
 
106
108
  return (
109
+ <% if (tailwind) { %>
107
110
  <div
108
111
  className="flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white"
109
112
  style={{
@@ -146,6 +149,35 @@ function Home() {
146
149
  </div>
147
150
  </div>
148
151
  </div>
152
+ <% } else { %>
153
+ <div>
154
+ <h1>Start Server Functions - Todo Example</h1>
155
+ <ul>
156
+ {todos?.map((t) => (
157
+ <li key={t.id}>{t.name}</li>
158
+ ))}
159
+ </ul>
160
+ <div className="flex flex-col gap-2">
161
+ <input
162
+ type="text"
163
+ value={todo}
164
+ onChange={(e) => setTodo(e.target.value)}
165
+ onKeyDown={(e) => {
166
+ if (e.key === 'Enter') {
167
+ submitTodo()
168
+ }
169
+ }}
170
+ placeholder="Enter a new todo..."
171
+ />
172
+ <button
173
+ disabled={todo.trim().length === 0}
174
+ onClick={submitTodo}
175
+ >
176
+ Add todo
177
+ </button>
178
+ </div>
179
+ </div>
180
+ <% } %>
149
181
  )
150
182
  }
151
183
  <% } %>
@@ -49,7 +49,6 @@ function RouteComponent() {
49
49
  return (
50
50
  <div>
51
51
  <h1>SPA Mode - Punk Songs</h1>
52
- </div>
53
52
  <ul>
54
53
  {punkSongs.map((song) => (
55
54
  <li key={song.id}>
@@ -1,5 +1,4 @@
1
1
  import { createFileRoute } from "@tanstack/react-router"; <% if (!tailwind) { %>
2
- import logo from "../logo.svg"
3
2
  import "../App.css"
4
3
  <% } else { %>
5
4
  import {
@@ -115,7 +114,10 @@ return (
115
114
  ); <% } else { %> return (
116
115
  <div className="App">
117
116
  <header className="App-header">
118
- <img src="{logo}" className="App-logo" alt="logo" />
117
+ <img
118
+ src="/tanstack-circle-logo.png"
119
+ className="App-logo" alt="TanStack Logo"
120
+ />
119
121
  <p>Edit <code>src/routes/index.tsx</code> and save to reload.</p>
120
122
  <a
121
123
  className="App-link"
@@ -6,7 +6,8 @@ import { paraglideVitePlugin } from "@inlang/paraglide-js"
6
6
  import { tanstackStart } from '@tanstack/react-start/plugin/vite';
7
7
  import viteReact from '@vitejs/plugin-react'
8
8
  import viteTsConfigPaths from 'vite-tsconfig-paths'
9
- import { fileURLToPath, URL } from 'url'<% if (tailwind) { %>
9
+ import { fileURLToPath, URL } from 'url'
10
+ <% if (tailwind) { %>
10
11
  import tailwindcss from "@tailwindcss/vite"
11
12
  <% } %><% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportContent(integration) %>
12
13
  <% } %>
@@ -5,7 +5,9 @@
5
5
  "link": "https://tanstack.com/start/latest",
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
+ "tailwind": false,
8
9
  "priority": 26,
10
+ "warning": "TanStack Start is not yet at 1.0 and may change significantly or not be compatible with other add-ons.\nMigrating to Start might require deleting node_modules and re-installing.",
9
11
  "routes": [
10
12
  {
11
13
  "icon": "SquareFunction",
@@ -52,6 +54,6 @@
52
54
  ]
53
55
  }
54
56
  ],
55
- "deletedFiles": ["./index.html", "./src/main.tsx", "./src/App.css"],
57
+ "deletedFiles": ["./index.html", "./src/main.tsx"],
56
58
  "addOnSpecialSteps": ["rimraf-node-modules"]
57
59
  }
@@ -1,3 +1,4 @@
1
+ import { createServerFileRoute } from '@tanstack/react-start/server'
1
2
  import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
2
3
  import { trpcRouter } from '@/integrations/trpc/router'
3
4
  import { createFileRoute } from '@tanstack/react-router'
@@ -6,6 +6,7 @@
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
8
  "priority": 200,
9
+ "tailwind": false,
9
10
  "integrations": [
10
11
  {
11
12
  "type": "vite-plugin",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "scripts": {
3
- "deploy": "npm run build && wrangler deploy"
3
+ "deploy": "<%= packageManager %> run build && wrangler deploy"
4
4
  },
5
5
  "dependencies": {
6
6
  "@cloudflare/vite-plugin": "^1.13.8"
@@ -6,6 +6,7 @@
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
8
  "priority": 180,
9
+ "tailwind": false,
9
10
  "integrations": [
10
11
  {
11
12
  "type": "vite-plugin",
@@ -6,6 +6,7 @@
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
8
  "priority": 0,
9
+ "tailwind": false,
9
10
  "integrations": [
10
11
  {
11
12
  "type": "vite-plugin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.46.2",
3
+ "version": "0.48.0",
4
4
  "description": "CTA Framework for React (Create React App)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "author": "Jack Herrington <jherr@pobox.com>",
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@tanstack/cta-engine": "0.46.2"
26
+ "@tanstack/cta-engine": "0.48.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^24.6.0",
@@ -0,0 +1,18 @@
1
+ <% if (tailwind) { ignoreFile() } %>.header {
2
+ padding: 0.5rem;
3
+ display: flex;
4
+ gap: 0.5rem;
5
+ background-color: #fff;
6
+ color: #000;
7
+ justify-content: space-between;
8
+ }
9
+
10
+ .nav {
11
+ display: flex;
12
+ flex-direction: row;
13
+ }
14
+
15
+ .nav-item {
16
+ padding: 0 0.5rem;
17
+ font-weight: bold;
18
+ }
@@ -1,7 +1,8 @@
1
1
  <% if (addOns.length === 0 && integrations.length === 0 && routes.length === 0) { ignoreFile() } %>import { Link } from '@tanstack/react-router'
2
2
  <% for(const integration of integrations.filter(i => i.type === 'header-user')) { %>
3
3
  import <%= integration.jsName %> from "<%= relativePath(integration.path) %>";
4
- <% } %><% if (tailwind) {
4
+ <% } %><% if (!tailwind) { %>
5
+ import './Header.css'<% } %><% if (tailwind) {
5
6
  const icons = new Set([
6
7
  "Menu",
7
8
  "X",
@@ -156,9 +157,15 @@ const userHeaders = integrations.filter(i => i.type === 'header-user');
156
157
  );
157
158
  <% } else { %>
158
159
  return (
160
+ <% if (tailwind) { %>
159
161
  <header className="p-2 flex gap-2 bg-white text-black justify-between">
160
162
  <nav className="flex flex-row">
161
163
  <div className="px-2 font-bold">
164
+ <% } else { %>
165
+ <header className="header">
166
+ <nav className="nav">
167
+ <div className="nav-item">
168
+ <% } %>
162
169
  <Link to="/">Home</Link>
163
170
  </div>
164
171
  <% for(const addOn of addOns) {
@@ -1,7 +1,8 @@
1
1
  <% if (addOnEnabled.start) { ignoreFile() } %>import { defineConfig } from "vite";
2
2
  import { devtools } from '@tanstack/devtools-vite'<% if (addOnEnabled.paraglide) { %>
3
3
  import { paraglideVitePlugin } from "@inlang/paraglide-js"<% } %>
4
- import viteReact from "@vitejs/plugin-react";<% if (tailwind) { %>
4
+ import viteReact from "@vitejs/plugin-react";
5
+ <% if (tailwind) { %>
5
6
  import tailwindcss from "@tailwindcss/vite";
6
7
  <% } %><%if (fileRouter) { %>
7
8
  import { tanstackRouter } from "@tanstack/router-plugin/vite";<% } %><% if (addOnEnabled['module-federation']) { %>
@@ -6,7 +6,8 @@
6
6
  "/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/App.css": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n",
9
- "/src/components/Header.jsx": "import { Link } from '@tanstack/react-router'\n\nexport default function Header() {\n return (\n <header className=\"p-2 flex gap-2 bg-white text-black justify-between\">\n <nav className=\"flex flex-row\">\n <div className=\"px-2 font-bold\">\n <Link to=\"/\">Home</Link>\n </div>\n\n <div className=\"px-2 font-bold\">\n <Link to=\"/demo/form/simple\">Simple Form</Link>\n </div>\n\n <div className=\"px-2 font-bold\">\n <Link to=\"/demo/form/address\">Address Form</Link>\n </div>\n </nav>\n </header>\n )\n}\n",
9
+ "/src/components/Header.css": ".header {\n padding: 0.5rem;\n display: flex;\n gap: 0.5rem;\n background-color: #fff;\n color: #000;\n justify-content: space-between;\n}\n\n.nav {\n display: flex;\n flex-direction: row;\n}\n\n.nav-item {\n padding: 0 0.5rem;\n font-weight: bold;\n}",
10
+ "/src/components/Header.jsx": "import { Link } from '@tanstack/react-router'\n\nimport './Header.css'\n\nexport default function Header() {\n return (\n <header className=\"header\">\n <nav className=\"nav\">\n <div className=\"nav-item\">\n <Link to=\"/\">Home</Link>\n </div>\n\n <div className=\"px-2 font-bold\">\n <Link to=\"/demo/form/simple\">Simple Form</Link>\n </div>\n\n <div className=\"px-2 font-bold\">\n <Link to=\"/demo/form/address\">Address Form</Link>\n </div>\n </nav>\n </header>\n )\n}\n",
10
11
  "/src/components/demo.FormComponents.jsx": "import { useStore } from '@tanstack/react-form'\n\nimport { useFieldContext, useFormContext } from '@/hooks/demo.form-context'\n\nexport function SubscribeButton({ label }: { label: string }) {\n const form = useFormContext()\n return (\n <form.Subscribe selector={(state) => state.isSubmitting}>\n {(isSubmitting) => (\n <button\n type=\"submit\"\n disabled={isSubmitting}\n className=\"px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors disabled:opacity-50\"\n >\n {label}\n </button>\n )}\n </form.Subscribe>\n )\n}\n\nfunction ErrorMessages({\n errors,\n}: {\n errors: Array<string | { message: string }>\n}) {\n return (\n <>\n {errors.map((error) => (\n <div\n key={typeof error === 'string' ? error : error.message}\n className=\"text-red-500 mt-1 font-bold\"\n >\n {typeof error === 'string' ? error : error.message}\n </div>\n ))}\n </>\n )\n}\n\nexport function TextField({\n label,\n placeholder,\n}: {\n label: string\n placeholder?: string\n}) {\n const field = useFieldContext<string>()\n const errors = useStore(field.store, (state) => state.meta.errors)\n\n return (\n <div>\n <label htmlFor={label} className=\"block font-bold mb-1 text-xl\">\n {label}\n <input\n value={field.state.value}\n placeholder={placeholder}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n className=\"w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500\"\n />\n </label>\n {field.state.meta.isTouched && <ErrorMessages errors={errors} />}\n </div>\n )\n}\n\nexport function TextArea({\n label,\n rows = 3,\n}: {\n label: string\n rows?: number\n}) {\n const field = useFieldContext<string>()\n const errors = useStore(field.store, (state) => state.meta.errors)\n\n return (\n <div>\n <label htmlFor={label} className=\"block font-bold mb-1 text-xl\">\n {label}\n <textarea\n value={field.state.value}\n onBlur={field.handleBlur}\n rows={rows}\n onChange={(e) => field.handleChange(e.target.value)}\n className=\"w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500\"\n />\n </label>\n {field.state.meta.isTouched && <ErrorMessages errors={errors} />}\n </div>\n )\n}\n\nexport function Select({\n label,\n values,\n}: {\n label: string\n values: Array<{ label: string; value: string }>\n placeholder?: string\n}) {\n const field = useFieldContext<string>()\n const errors = useStore(field.store, (state) => state.meta.errors)\n\n return (\n <div>\n <label htmlFor={label} className=\"block font-bold mb-1 text-xl\">\n {label}\n </label>\n <select\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n className=\"w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500\"\n >\n {values.map((value) => (\n <option key={value.value} value={value.value}>\n {value.label}\n </option>\n ))}\n </select>\n {field.state.meta.isTouched && <ErrorMessages errors={errors} />}\n </div>\n )\n}\n",
11
12
  "/src/hooks/demo.form-context.js": "import { createFormHookContexts } from '@tanstack/react-form'\n\nexport const { fieldContext, useFieldContext, formContext, useFormContext } =\n createFormHookContexts()\n",
12
13
  "/src/hooks/demo.form.js": "import { createFormHook } from '@tanstack/react-form'\n\nimport {\n Select,\n SubscribeButton,\n TextArea,\n TextField,\n} from '../components/demo.FormComponents'\nimport { fieldContext, formContext } from './demo.form-context'\n\nexport const { useAppForm } = createFormHook({\n fieldComponents: {\n TextField,\n Select,\n TextArea,\n },\n formComponents: {\n SubscribeButton,\n },\n fieldContext,\n formContext,\n})\n",
@@ -20,7 +21,7 @@
20
21
  "README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run dev\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses CSS for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json();\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.jsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.jsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
21
22
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.jsx\"></script>\n </body>\n</html>\n",
22
23
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-form\": \"^1.0.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"zod\": \"^4.1.11\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
23
- "vite.config.js": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
24
+ "vite.config.js": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
24
25
  },
25
26
  "commands": [
26
27
  "git init",
@@ -6,6 +6,7 @@
6
6
  "/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/App.css": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n",
9
+ "/src/components/Header.css": ".header {\n padding: 0.5rem;\n display: flex;\n gap: 0.5rem;\n background-color: #fff;\n color: #000;\n justify-content: space-between;\n}\n\n.nav {\n display: flex;\n flex-direction: row;\n}\n\n.nav-item {\n padding: 0 0.5rem;\n font-weight: bold;\n}",
9
10
  "/src/main.jsx": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { RouterProvider, createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\nimport './styles.css'\nimport reportWebVitals from './reportWebVitals.js'\n\n// Create a new router instance\nconst router = createRouter({\n routeTree,\n context: {},\n defaultPreload: 'intent',\n scrollRestoration: true,\n defaultStructuralSharing: true,\n defaultPreloadStaleTime: 0,\n})\n\n// Register the router instance for type safety\ndeclare module '@tanstack/react-router' {\n interface Register {\n router: typeof router\n }\n}\n\n// Render the app\nconst rootElement = document.getElementById('app')\nif (rootElement && !rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement)\n root.render(\n <StrictMode>\n <RouterProvider router={router} />\n </StrictMode>,\n )\n}\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n",
10
11
  "/src/reportWebVitals.js": "const reportWebVitals = (onPerfEntry) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {\n onCLS(onPerfEntry)\n onINP(onPerfEntry)\n onFCP(onPerfEntry)\n onLCP(onPerfEntry)\n onTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n",
11
12
  "/src/routes/__root.jsx": "import { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n </>\n ),\n})\n",
@@ -14,7 +15,7 @@
14
15
  "README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run dev\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses CSS for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json();\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.jsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.jsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
15
16
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.jsx\"></script>\n </body>\n</html>\n",
16
17
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
17
- "vite.config.js": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
18
+ "vite.config.js": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
18
19
  },
19
20
  "commands": [
20
21
  "git init",
@@ -6,6 +6,7 @@
6
6
  "/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/App.css": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n",
9
+ "/src/components/Header.css": ".header {\n padding: 0.5rem;\n display: flex;\n gap: 0.5rem;\n background-color: #fff;\n color: #000;\n justify-content: space-between;\n}\n\n.nav {\n display: flex;\n flex-direction: row;\n}\n\n.nav-item {\n padding: 0 0.5rem;\n font-weight: bold;\n}",
9
10
  "/src/main.tsx": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { RouterProvider, createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\nimport './styles.css'\nimport reportWebVitals from './reportWebVitals.ts'\n\n// Create a new router instance\nconst router = createRouter({\n routeTree,\n context: {},\n defaultPreload: 'intent',\n scrollRestoration: true,\n defaultStructuralSharing: true,\n defaultPreloadStaleTime: 0,\n})\n\n// Register the router instance for type safety\ndeclare module '@tanstack/react-router' {\n interface Register {\n router: typeof router\n }\n}\n\n// Render the app\nconst rootElement = document.getElementById('app')\nif (rootElement && !rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement)\n root.render(\n <StrictMode>\n <RouterProvider router={router} />\n </StrictMode>,\n )\n}\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n",
10
11
  "/src/reportWebVitals.ts": "const reportWebVitals = (onPerfEntry?: () => void) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {\n onCLS(onPerfEntry)\n onINP(onPerfEntry)\n onFCP(onPerfEntry)\n onLCP(onPerfEntry)\n onTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n",
11
12
  "/src/routes/__root.tsx": "import { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n </>\n ),\n})\n",
@@ -15,7 +16,7 @@
15
16
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
16
17
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
17
18
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
18
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
19
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
19
20
  },
20
21
  "commands": [
21
22
  "git init",
@@ -22,7 +22,7 @@
22
22
  "README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run dev\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n# Apollo Client Integration\n\nThis add-on integrates Apollo Client with TanStack Start to provide modern streaming SSR support for GraphQL data fetching.\n\n## Dependencies\n\nThe following packages are automatically installed:\n\n- `@apollo/client` - Apollo Client core\n- `@apollo/client-integration-tanstack-start` - TanStack Start integration\n- `graphql` - GraphQL implementation\n\n## Configuration\n\n### 1. GraphQL Endpoint\n\nConfigure your GraphQL API endpoint in `src/router.tsx`:\n\n```tsx\n// Configure Apollo Client\nconst apolloClient = new ApolloClient({\n cache: new InMemoryCache(),\n link: new HttpLink({\n uri: 'https://your-graphql-api.example.com/graphql', // Update this!\n }),\n})\n```\n\nYou can use environment variables by creating a `.env.local` file:\n\n```bash\nVITE_GRAPHQL_ENDPOINT=https://your-api.com/graphql\n```\n\nThe default configuration already uses this pattern:\n\n```tsx\nuri: import.meta.env.VITE_GRAPHQL_ENDPOINT ||\n 'https://your-graphql-api.example.com/graphql'\n```\n\n## Usage Patterns\n\n### Pattern 1: Loader with preloadQuery (Recommended for SSR)\n\nUse `preloadQuery` in route loaders for optimal streaming SSR performance:\n\n```tsx\nimport { gql, TypedDocumentNode } from '@apollo/client'\nimport { useReadQuery } from '@apollo/client/react'\nimport { createFileRoute } from '@tanstack/react-router'\n\nconst MY_QUERY: TypedDocumentNode<{\n posts: { id: string; title: string; content: string }[]\n}> = gql`\n query GetData {\n posts {\n id\n title\n content\n }\n }\n`\n\nexport const Route = createFileRoute('/my-route')({\n component: RouteComponent,\n loader: ({ context: { preloadQuery } }) => {\n const queryRef = preloadQuery(MY_QUERY, {\n variables: {},\n })\n return { queryRef }\n },\n})\n\nfunction RouteComponent() {\n const { queryRef } = Route.useLoaderData()\n const { data } = useReadQuery(queryRef)\n\n return <div>{/* render your data */}</div>\n}\n```\n\n### Pattern 2: useSuspenseQuery\n\nUse `useSuspenseQuery` directly in components with automatic suspense support:\n\n```tsx\nimport { gql, TypedDocumentNode } from '@apollo/client'\nimport { useSuspenseQuery } from '@apollo/client/react'\nimport { createFileRoute } from '@tanstack/react-router'\n\nconst MY_QUERY: TypedDocumentNode<{\n posts: { id: string; title: string }[]\n}> = gql`\n query GetData {\n posts {\n id\n title\n }\n }\n`\n\nexport const Route = createFileRoute('/my-route')({\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { data } = useSuspenseQuery(MY_QUERY)\n\n return <div>{/* render your data */}</div>\n}\n```\n\n### Pattern 3: Manual Refetching\n\n```tsx\nimport { useQueryRefHandlers, useReadQuery } from '@apollo/client/react'\n\nfunction MyComponent() {\n const { queryRef } = Route.useLoaderData()\n const { refetch } = useQueryRefHandlers(queryRef)\n const { data } = useReadQuery(queryRef)\n\n return (\n <div>\n <button onClick={() => refetch()}>Refresh</button>\n {/* render data */}\n </div>\n )\n}\n```\n\n## Important Notes\n\n### SSR Optimization\n\nThe integration automatically handles:\n\n- Query deduplication across server and client\n- Streaming SSR with `@defer` directive support\n- Proper cache hydration\n\n## Learn More\n\n- [Apollo Client Documentation](https://www.apollographql.com/docs/react)\n- [@apollo/client-integration-tanstack-start](https://www.npmjs.com/package/@apollo/client-integration-tanstack-start)\n\n## Demo\n\nVisit `/demo/apollo-client` in your application to see a working example of Apollo Client integration.\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
23
23
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite dev --port 3000\",\n \"build\": \"vite build\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@apollo/client\": \"^4.0.0\",\n \"@apollo/client-integration-tanstack-start\": \"^0.14.2-rc.0\",\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/react-router-ssr-query\": \"^1.131.7\",\n \"@tanstack/react-start\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"graphql\": \"^16.10.0\",\n \"lucide-react\": \"^0.561.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"rxjs\": \"^7.8.2\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^6.0.2\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
24
24
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": false,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
25
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
25
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\n\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
26
26
  },
27
27
  "commands": [
28
28
  "git init",
@@ -21,7 +21,7 @@
21
21
  "README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run dev\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
22
22
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite dev --port 3000\",\n \"build\": \"vite build\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/react-router-ssr-query\": \"^1.131.7\",\n \"@tanstack/react-start\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"lucide-react\": \"^0.561.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^6.0.2\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
23
23
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": false,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
24
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
24
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\n\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
25
25
  },
26
26
  "commands": [
27
27
  "git init",
@@ -25,7 +25,7 @@
25
25
  "README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run dev\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Testing\n\nThis project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:\n\n```bash\nnpm run test\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.\n\n```tsx\nimport { Link } from \"@tanstack/react-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\n\nimport { Link } from \"@tanstack/react-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).\n\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).\n\n### React-Query\n\nReact-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.\n\nFirst add your dependencies:\n\n```bash\nnpm install @tanstack/react-query @tanstack/react-query-devtools\n```\n\nNext we'll need to create a query client and provider. We recommend putting those in `main.tsx`.\n\n```tsx\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n\n// ...\n\nconst queryClient = new QueryClient();\n\n// ...\n\nif (!rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement);\n\n root.render(\n <QueryClientProvider client={queryClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>\n );\n}\n```\n\nYou can also add TanStack Query Devtools to the root route (optional).\n\n```tsx\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nconst rootRoute = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <ReactQueryDevtools buttonPosition=\"top-right\" />\n <TanStackRouterDevtools />\n </>\n ),\n});\n```\n\nNow you can use `useQuery` to fetch your data.\n\n```tsx\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport \"./App.css\";\n\nfunction App() {\n const { data } = useQuery({\n queryKey: [\"people\"],\n queryFn: () =>\n fetch(\"https://swapi.dev/api/people\")\n .then((res) => res.json())\n .then((data) => data.results as { name: string }[]),\n initialData: [],\n });\n\n return (\n <div>\n <ul>\n {data.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport default App;\n```\n\nYou can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).\n\n## State Management\n\nAnother common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.\n\nFirst you need to add TanStack Store as a dependency:\n\n```bash\nnpm install @tanstack/store\n```\n\nNow let's create a simple counter in the `src/App.tsx` file as a demonstration.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nfunction App() {\n const count = useStore(countStore);\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n </div>\n );\n}\n\nexport default App;\n```\n\nOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.\n\nLet's check this out by doubling the count using derived state.\n\n```tsx\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store, Derived } from \"@tanstack/store\";\nimport \"./App.css\";\n\nconst countStore = new Store(0);\n\nconst doubledStore = new Derived({\n fn: () => countStore.state * 2,\n deps: [countStore],\n});\ndoubledStore.mount();\n\nfunction App() {\n const count = useStore(countStore);\n const doubledCount = useStore(doubledStore);\n\n return (\n <div>\n <button onClick={() => countStore.setState((n) => n + 1)}>\n Increment - {count}\n </button>\n <div>Doubled - {doubledCount}</div>\n </div>\n );\n}\n\nexport default App;\n```\n\nWe use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.\n\nOnce we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.\n\nYou can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
26
26
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite dev --port 3000\",\n \"build\": \"vite build\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-query\": \"^5.66.5\",\n \"@tanstack/react-query-devtools\": \"^5.84.2\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/react-router-ssr-query\": \"^1.131.7\",\n \"@tanstack/react-start\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"lucide-react\": \"^0.561.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^6.0.2\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
27
27
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": false,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
28
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
28
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport { tanstackStart } from '@tanstack/react-start/plugin/vite'\nimport viteReact from '@vitejs/plugin-react'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\nimport { fileURLToPath, URL } from 'url'\n\nimport tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n plugins: [\n devtools(),\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n tailwindcss(),\n tanstackStart(),\n viteReact(),\n ],\n})\n\nexport default config\n"
29
29
  },
30
30
  "commands": [
31
31
  "git init",
@@ -6,7 +6,8 @@
6
6
  "/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/App.css": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n",
9
- "/src/components/Header.tsx": "import { Link } from '@tanstack/react-router'\n\nexport default function Header() {\n return (\n <header className=\"p-2 flex gap-2 bg-white text-black justify-between\">\n <nav className=\"flex flex-row\">\n <div className=\"px-2 font-bold\">\n <Link to=\"/\">Home</Link>\n </div>\n </nav>\n </header>\n )\n}\n",
9
+ "/src/components/Header.css": ".header {\n padding: 0.5rem;\n display: flex;\n gap: 0.5rem;\n background-color: #fff;\n color: #000;\n justify-content: space-between;\n}\n\n.nav {\n display: flex;\n flex-direction: row;\n}\n\n.nav-item {\n padding: 0 0.5rem;\n font-weight: bold;\n}",
10
+ "/src/components/Header.tsx": "import { Link } from '@tanstack/react-router'\n\nimport './Header.css'\n\nexport default function Header() {\n return (\n <header className=\"header\">\n <nav className=\"nav\">\n <div className=\"nav-item\">\n <Link to=\"/\">Home</Link>\n </div>\n </nav>\n </header>\n )\n}\n",
10
11
  "/src/main.tsx": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { RouterProvider, createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\nimport './styles.css'\nimport reportWebVitals from './reportWebVitals.ts'\n\n// Create a new router instance\nconst router = createRouter({\n routeTree,\n context: {},\n defaultPreload: 'intent',\n scrollRestoration: true,\n defaultStructuralSharing: true,\n defaultPreloadStaleTime: 0,\n})\n\n// Register the router instance for type safety\ndeclare module '@tanstack/react-router' {\n interface Register {\n router: typeof router\n }\n}\n\n// Render the app\nconst rootElement = document.getElementById('app')\nif (rootElement && !rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement)\n root.render(\n <StrictMode>\n <RouterProvider router={router} />\n </StrictMode>,\n )\n}\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n",
11
12
  "/src/reportWebVitals.ts": "const reportWebVitals = (onPerfEntry?: () => void) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {\n onCLS(onPerfEntry)\n onINP(onPerfEntry)\n onFCP(onPerfEntry)\n onLCP(onPerfEntry)\n onTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n",
12
13
  "/src/routes/__root.tsx": "import { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nimport Header from '../components/Header'\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <Header />\n <Outlet />\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n </>\n ),\n})\n",
@@ -17,7 +18,7 @@
17
18
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
18
19
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\",\n \"format\": \"biome format\",\n \"lint\": \"biome lint\",\n \"check\": \"biome check\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.2.4\",\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
19
20
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
20
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
21
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
21
22
  },
22
23
  "commands": [
23
24
  "git init",
@@ -6,6 +6,7 @@
6
6
  "/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/App.css": ".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n",
9
+ "/src/components/Header.css": ".header {\n padding: 0.5rem;\n display: flex;\n gap: 0.5rem;\n background-color: #fff;\n color: #000;\n justify-content: space-between;\n}\n\n.nav {\n display: flex;\n flex-direction: row;\n}\n\n.nav-item {\n padding: 0 0.5rem;\n font-weight: bold;\n}",
9
10
  "/src/main.tsx": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { RouterProvider, createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\nimport './styles.css'\nimport reportWebVitals from './reportWebVitals.ts'\n\n// Create a new router instance\nconst router = createRouter({\n routeTree,\n context: {},\n defaultPreload: 'intent',\n scrollRestoration: true,\n defaultStructuralSharing: true,\n defaultPreloadStaleTime: 0,\n})\n\n// Register the router instance for type safety\ndeclare module '@tanstack/react-router' {\n interface Register {\n router: typeof router\n }\n}\n\n// Render the app\nconst rootElement = document.getElementById('app')\nif (rootElement && !rootElement.innerHTML) {\n const root = ReactDOM.createRoot(rootElement)\n root.render(\n <StrictMode>\n <RouterProvider router={router} />\n </StrictMode>,\n )\n}\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n",
10
11
  "/src/reportWebVitals.ts": "const reportWebVitals = (onPerfEntry?: () => void) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {\n onCLS(onPerfEntry)\n onINP(onPerfEntry)\n onFCP(onPerfEntry)\n onLCP(onPerfEntry)\n onTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n",
11
12
  "/src/routes/__root.tsx": "import { Outlet, createRootRoute } from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <Outlet />\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n </>\n ),\n})\n",
@@ -15,7 +16,7 @@
15
16
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
16
17
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
17
18
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
18
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
19
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
19
20
  },
20
21
  "commands": [
21
22
  "git init",
@@ -14,7 +14,7 @@
14
14
  "index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-tsrouter-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <title>Create TanStack App - TEST</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
15
15
  "package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite --port 3000\",\n \"build\": \"vite build && tsc\",\n \"preview\": \"vite preview\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/react-devtools\": \"^0.7.0\",\n \"@tanstack/react-router\": \"^1.132.0\",\n \"@tanstack/react-router-devtools\": \"^1.132.0\",\n \"@tanstack/router-plugin\": \"^1.132.0\",\n \"lucide-react\": \"^0.545.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tailwindcss\": \"^4.0.6\"\n },\n \"devDependencies\": {\n \"@tanstack/devtools-vite\": \"^0.3.11\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^22.10.2\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@vitejs/plugin-react\": \"^5.0.4\",\n \"jsdom\": \"^27.0.0\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^7.1.7\",\n \"vitest\": \"^3.0.5\",\n \"web-vitals\": \"^5.1.0\"\n }\n}",
16
16
  "tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n",
17
- "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\nimport tailwindcss from '@tailwindcss/vite'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n tailwindcss(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
17
+ "vite.config.ts": "import { defineConfig } from 'vite'\nimport { devtools } from '@tanstack/devtools-vite'\nimport viteReact from '@vitejs/plugin-react'\n\nimport tailwindcss from '@tailwindcss/vite'\n\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\nimport { fileURLToPath, URL } from 'node:url'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n devtools(),\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n viteReact(),\n tailwindcss(),\n ],\n resolve: {\n alias: {\n '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})\n"
18
18
  },
19
19
  "commands": [
20
20
  "git init",