@tanstack/cta-framework-react-cra 0.47.0 → 0.48.1

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 (49) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/add-ons/ai/info.json +2 -0
  3. package/add-ons/apollo-client/info.json +2 -0
  4. package/add-ons/better-auth/README.md +32 -0
  5. package/add-ons/better-auth/assets/_dot_env.local.append +3 -0
  6. package/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +43 -0
  7. package/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
  8. package/add-ons/better-auth/assets/src/lib/auth.ts +9 -0
  9. package/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
  10. package/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +232 -0
  11. package/add-ons/better-auth/info.json +29 -0
  12. package/add-ons/better-auth/logo.svg +7 -0
  13. package/add-ons/better-auth/package.json +5 -0
  14. package/add-ons/better-auth/small-logo.svg +9 -0
  15. package/add-ons/clerk/info.json +3 -0
  16. package/add-ons/compiler/info.json +2 -0
  17. package/add-ons/convex/info.json +3 -0
  18. package/add-ons/db/info.json +2 -0
  19. package/add-ons/drizzle/info.json +3 -0
  20. package/add-ons/form/info.json +2 -0
  21. package/add-ons/mcp/info.json +2 -0
  22. package/add-ons/module-federation/info.json +2 -0
  23. package/add-ons/neon/info.json +3 -0
  24. package/add-ons/oRPC/info.json +2 -0
  25. package/add-ons/paraglide/info.json +2 -0
  26. package/add-ons/prisma/info.json +3 -0
  27. package/add-ons/sentry/info.json +2 -0
  28. package/add-ons/shadcn/info.json +2 -0
  29. package/add-ons/start/info.json +2 -0
  30. package/add-ons/store/info.json +2 -0
  31. package/add-ons/storybook/info.json +2 -0
  32. package/add-ons/strapi/info.json +2 -0
  33. package/add-ons/t3env/info.json +2 -0
  34. package/add-ons/tRPC/info.json +2 -0
  35. package/add-ons/table/info.json +2 -0
  36. package/add-ons/tanstack-query/info.json +2 -0
  37. package/add-ons/workos/info.json +3 -0
  38. package/examples/events/info.json +2 -0
  39. package/examples/resume/info.json +2 -0
  40. package/hosts/cloudflare/info.json +3 -0
  41. package/hosts/cloudflare/{package.json → package.json.ejs} +1 -1
  42. package/hosts/netlify/info.json +3 -0
  43. package/hosts/nitro/info.json +3 -0
  44. package/hosts/railway/assets/nixpacks.toml +8 -0
  45. package/hosts/railway/info.json +20 -0
  46. package/hosts/railway/package.json +8 -0
  47. package/package.json +2 -2
  48. package/toolchains/biome/info.json +3 -0
  49. package/toolchains/eslint/info.json +3 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @tanstack/cta-framework-react-cra
2
2
 
3
+ ## 0.48.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`cdb6eef`](https://github.com/TanStack/create-tsrouter-app/commit/cdb6eef79274a4041eae5e8cd9d43539c9a9a77a)]:
8
+ - @tanstack/cta-engine@0.49.0
9
+
10
+ ## 0.48.0
11
+
12
+ ### Minor Changes
13
+
14
+ - no will prompt about overriding a directory that has contents ([#289](https://github.com/TanStack/create-tsrouter-app/pull/289))
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [[`3087532`](https://github.com/TanStack/create-tsrouter-app/commit/308753249af11bf5c9e374789e973a934c753520)]:
19
+ - @tanstack/cta-engine@0.48.0
20
+
3
21
  ## 0.47.0
4
22
 
5
23
  ### Minor Changes
@@ -4,6 +4,8 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
7
+ "category": "tanstack",
8
+ "color": "#00D1B2",
7
9
  "priority": 60,
8
10
  "link": "",
9
11
  "routes": [
@@ -4,6 +4,8 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
7
+ "category": "api",
8
+ "color": "#311C87",
7
9
  "priority": 15,
8
10
  "link": "https://github.com/apollographql/apollo-client-integrations/tree/main/packages/tanstack-start",
9
11
  "dependsOn": ["start"],
@@ -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,9 @@
1
+ import { betterAuth } from 'better-auth'
2
+ import { tanstackStartCookies } from 'better-auth/tanstack-start'
3
+
4
+ export const auth = betterAuth({
5
+ emailAndPassword: {
6
+ enabled: true,
7
+ },
8
+ plugins: [tanstackStartCookies()],
9
+ })
@@ -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,29 @@
1
+ {
2
+ "name": "Better Auth",
3
+ "description": "Add Better Auth authentication to your application.",
4
+ "phase": "add-on",
5
+ "type": "add-on",
6
+ "category": "auth",
7
+ "exclusive": ["auth"],
8
+ "color": "#000000",
9
+ "priority": 26,
10
+ "link": "https://www.better-auth.com",
11
+ "modes": ["file-router"],
12
+ "tailwind": true,
13
+ "dependsOn": ["start"],
14
+ "routes": [
15
+ {
16
+ "url": "/demo/better-auth",
17
+ "name": "Better Auth",
18
+ "path": "src/routes/demo/better-auth.tsx",
19
+ "jsName": "BetterAuthDemo"
20
+ }
21
+ ],
22
+ "integrations": [
23
+ {
24
+ "type": "header-user",
25
+ "jsName": "BetterAuthHeader",
26
+ "path": "src/integrations/better-auth/header-user.tsx"
27
+ }
28
+ ]
29
+ }
@@ -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>
@@ -4,6 +4,9 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
7
+ "category": "auth",
8
+ "exclusive": ["auth"],
9
+ "color": "#6C47FF",
7
10
  "priority": 150,
8
11
  "link": "https://clerk.com",
9
12
  "tailwind": true,
@@ -5,6 +5,8 @@
5
5
  "link": "https://react.dev/learn/react-compiler",
6
6
  "modes": ["code-router", "file-router"],
7
7
  "type": "add-on",
8
+ "category": "tooling",
9
+ "color": "#61DAFB",
8
10
  "priority": 50,
9
11
  "routes": []
10
12
  }
@@ -4,6 +4,9 @@
4
4
  "link": "https://convex.dev",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
7
+ "category": "database",
8
+ "exclusive": ["database", "orm"],
9
+ "color": "#EE342F",
7
10
  "priority": 140,
8
11
  "modes": ["file-router"],
9
12
  "routes": [
@@ -3,6 +3,8 @@
3
3
  "description": "TanStack DB",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
+ "category": "tanstack",
7
+ "color": "#00D1B2",
6
8
  "priority": 48,
7
9
  "modes": ["file-router"],
8
10
  "link": "https://tanstack.com/db/latest",
@@ -3,6 +3,9 @@
3
3
  "description": "Add Drizzle ORM to your application.",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
+ "category": "orm",
7
+ "exclusive": ["orm"],
8
+ "color": "#C026D3",
6
9
  "priority": 46,
7
10
  "link": "https://orm.drizzle.team/",
8
11
  "modes": ["file-router"],
@@ -3,6 +3,8 @@
3
3
  "description": "TanStack Form",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
+ "category": "tanstack",
7
+ "color": "#FACC15",
6
8
  "priority": 44,
7
9
  "modes": ["file-router", "code-router"],
8
10
  "link": "https://tanstack.com/form/latest",
@@ -5,6 +5,8 @@
5
5
  "link": "https://mcp.dev",
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
+ "category": "api",
9
+ "color": "#10B981",
8
10
  "priority": 42,
9
11
  "warning": "MCP is still in development and may change significantly or not be compatible with other add-ons.\nThe MCP implementation does not support authentication.",
10
12
  "routes": [
@@ -5,5 +5,7 @@
5
5
  "modes": ["code-router"],
6
6
  "link": "https://module-federation.io/",
7
7
  "type": "add-on",
8
+ "category": "tooling",
9
+ "color": "#1B72BE",
8
10
  "priority": 38
9
11
  }
@@ -4,6 +4,9 @@
4
4
  "link": "https://neon.com",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
7
+ "category": "database",
8
+ "exclusive": ["database"],
9
+ "color": "#00E599",
7
10
  "priority": 170,
8
11
  "modes": ["file-router"],
9
12
  "routes": [
@@ -6,6 +6,8 @@
6
6
  "link": "https://orpc.unnoq.com/",
7
7
  "dependsOn": ["tanstack-query", "start"],
8
8
  "type": "add-on",
9
+ "category": "api",
10
+ "color": "#FF6B6B",
9
11
  "priority": 34,
10
12
  "routes": [
11
13
  {
@@ -4,6 +4,8 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
7
+ "category": "i18n",
8
+ "color": "#14B8A6",
7
9
  "priority": 30,
8
10
  "link": "https://github.com/paraglidejs/paraglide-js",
9
11
  "routes": [
@@ -3,6 +3,9 @@
3
3
  "description": "Add Prisma Postgres, or Prisma ORM with other DBs to your application.",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
+ "category": "orm",
7
+ "exclusive": ["orm"],
8
+ "color": "#2D3748",
6
9
  "priority": 120,
7
10
  "link": "https://www.prisma.io/",
8
11
  "modes": ["file-router"],
@@ -5,6 +5,8 @@
5
5
  "link": "https://sentry.com/",
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
+ "category": "monitoring",
9
+ "color": "#362D59",
8
10
  "priority": 130,
9
11
  "routes": [
10
12
  {
@@ -5,5 +5,7 @@
5
5
  "modes": ["file-router", "code-router"],
6
6
  "link": "https://ui.shadcn.com/",
7
7
  "type": "add-on",
8
+ "category": "styling",
9
+ "color": "#000000",
8
10
  "priority": 30
9
11
  }
@@ -5,6 +5,8 @@
5
5
  "link": "https://tanstack.com/start/latest",
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
+ "category": "tanstack",
9
+ "color": "#00D1B2",
8
10
  "tailwind": false,
9
11
  "priority": 26,
10
12
  "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.",
@@ -4,6 +4,8 @@
4
4
  "phase": "add-on",
5
5
  "link": "https://tanstack.com/store/latest",
6
6
  "type": "add-on",
7
+ "category": "tanstack",
8
+ "color": "#00D1B2",
7
9
  "priority": 22,
8
10
  "modes": ["file-router", "code-router"],
9
11
  "routes": [
@@ -5,6 +5,8 @@
5
5
  "modes": ["file-router"],
6
6
  "link": "https://storybook.js.org/",
7
7
  "type": "add-on",
8
+ "category": "tooling",
9
+ "color": "#FF4785",
8
10
  "priority": 18,
9
11
  "routes": [
10
12
  {
@@ -4,6 +4,8 @@
4
4
  "link": "https://strapi.io/",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
7
+ "category": "cms",
8
+ "color": "#4945FF",
7
9
  "priority": 110,
8
10
  "modes": ["file-router"],
9
11
  "routes": [
@@ -3,6 +3,8 @@
3
3
  "description": "Add type safety to your environment variables",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
+ "category": "tooling",
7
+ "color": "#6366F1",
6
8
  "priority": 29,
7
9
  "link": "https://github.com/t3-oss/t3-env",
8
10
  "modes": ["file-router", "code-router"]
@@ -6,6 +6,8 @@
6
6
  "link": "https://trpc.io/",
7
7
  "dependsOn": ["tanstack-query", "start"],
8
8
  "type": "add-on",
9
+ "category": "api",
10
+ "color": "#2596BE",
9
11
  "priority": 27,
10
12
  "routes": [
11
13
  {
@@ -5,6 +5,8 @@
5
5
  "modes": ["file-router", "code-router"],
6
6
  "link": "https://tanstack.com/table/latest",
7
7
  "type": "add-on",
8
+ "category": "tanstack",
9
+ "color": "#00D1B2",
8
10
  "priority": 28,
9
11
  "routes": [
10
12
  {
@@ -4,6 +4,8 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router", "code-router"],
6
6
  "type": "add-on",
7
+ "category": "tanstack",
8
+ "color": "#EF4444",
7
9
  "priority": 10,
8
10
  "link": "https://tanstack.com/query/latest",
9
11
  "routes": [
@@ -4,6 +4,9 @@
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
7
+ "category": "auth",
8
+ "exclusive": ["auth"],
9
+ "color": "#6363F1",
7
10
  "priority": 160,
8
11
  "link": "https://workos.com",
9
12
  "tailwind": true,
@@ -4,6 +4,8 @@
4
4
  "phase": "example",
5
5
  "modes": ["file-router"],
6
6
  "type": "example",
7
+ "category": "other",
8
+ "color": "#F59E0B",
7
9
  "priority": 10,
8
10
  "link": "",
9
11
  "routes": [
@@ -4,6 +4,8 @@
4
4
  "phase": "example",
5
5
  "modes": ["file-router"],
6
6
  "type": "example",
7
+ "category": "other",
8
+ "color": "#8B5CF6",
7
9
  "priority": 10,
8
10
  "link": "",
9
11
  "routes": [
@@ -5,6 +5,9 @@
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
+ "category": "deploy",
9
+ "exclusive": ["deploy"],
10
+ "color": "#F38020",
8
11
  "priority": 200,
9
12
  "tailwind": false,
10
13
  "integrations": [
@@ -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"
@@ -5,6 +5,9 @@
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
+ "category": "deploy",
9
+ "exclusive": ["deploy"],
10
+ "color": "#00C7B7",
8
11
  "priority": 180,
9
12
  "tailwind": false,
10
13
  "integrations": [
@@ -5,6 +5,9 @@
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
7
7
  "type": "deployment",
8
+ "category": "deploy",
9
+ "exclusive": ["deploy"],
10
+ "color": "#ECDC5A",
8
11
  "priority": 0,
9
12
  "tailwind": false,
10
13
  "integrations": [
@@ -0,0 +1,8 @@
1
+ [phases.setup]
2
+ nixPkgs = ["nodejs_22"]
3
+
4
+ [phases.build]
5
+ cmds = ["npm install", "npm run build"]
6
+
7
+ [start]
8
+ cmd = "npm run start"
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "Railway",
3
+ "description": "Railway deployment setup",
4
+ "link": "https://railway.com/",
5
+ "phase": "add-on",
6
+ "modes": ["file-router", "code-router"],
7
+ "type": "deployment",
8
+ "category": "deploy",
9
+ "exclusive": ["deploy"],
10
+ "color": "#9B4DCA",
11
+ "priority": 160,
12
+ "tailwind": false,
13
+ "integrations": [
14
+ {
15
+ "type": "vite-plugin",
16
+ "import": "import { nitro } from 'nitro/vite'",
17
+ "code": "nitro()"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "scripts": {
3
+ "start": "node .output/server/index.mjs"
4
+ },
5
+ "dependencies": {
6
+ "nitro": "npm:nitro-nightly@latest"
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.47.0",
3
+ "version": "0.48.1",
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.47.0"
26
+ "@tanstack/cta-engine": "0.49.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^24.6.0",
@@ -3,6 +3,9 @@
3
3
  "description": "Biome toolchain support.",
4
4
  "phase": "setup",
5
5
  "type": "toolchain",
6
+ "category": "tooling",
7
+ "exclusive": ["linter"],
8
+ "color": "#60A5FA",
6
9
  "priority": 2,
7
10
  "modes": ["code-router", "file-router"],
8
11
  "link": "https://biomejs.dev"
@@ -3,6 +3,9 @@
3
3
  "description": "ESLint + Prettier toolchain support.",
4
4
  "phase": "setup",
5
5
  "type": "toolchain",
6
+ "category": "tooling",
7
+ "exclusive": ["linter"],
8
+ "color": "#4B32C3",
6
9
  "priority": 0,
7
10
  "modes": ["code-router", "file-router"],
8
11
  "link": "https://eslint.org"