@tanstack/create 0.63.9 → 0.65.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 (95) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/add-to-app.js +5 -0
  3. package/dist/create-app.js +74 -16
  4. package/dist/custom-add-ons/shared.js +2 -0
  5. package/dist/file-helpers.js +14 -0
  6. package/dist/frameworks/react/add-ons/ai/info.json +1 -1
  7. package/dist/frameworks/react/add-ons/better-auth/info.json +1 -1
  8. package/dist/frameworks/react/add-ons/clerk/README.md +42 -1
  9. package/dist/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +94 -11
  10. package/dist/frameworks/react/add-ons/clerk/info.json +1 -1
  11. package/dist/frameworks/react/add-ons/compiler/info.json +1 -1
  12. package/dist/frameworks/react/add-ons/convex/info.json +1 -1
  13. package/dist/frameworks/react/add-ons/drizzle/info.json +1 -1
  14. package/dist/frameworks/react/add-ons/mcp/info.json +1 -1
  15. package/dist/frameworks/react/add-ons/neon/info.json +1 -1
  16. package/dist/frameworks/react/add-ons/paraglide/info.json +1 -1
  17. package/dist/frameworks/react/add-ons/prisma/info.json +1 -1
  18. package/dist/frameworks/react/add-ons/shadcn/info.json +1 -1
  19. package/dist/frameworks/react/add-ons/strapi/info.json +1 -1
  20. package/dist/frameworks/react/add-ons/t3env/info.json +1 -1
  21. package/dist/frameworks/react/add-ons/workos/info.json +1 -1
  22. package/dist/frameworks/react/hosts/cloudflare/README.md +11 -0
  23. package/dist/frameworks/react/hosts/cloudflare/info.json +1 -1
  24. package/dist/frameworks/react/hosts/netlify/README.md +11 -0
  25. package/dist/frameworks/react/hosts/netlify/info.json +1 -1
  26. package/dist/frameworks/react/hosts/nitro/README.md +12 -0
  27. package/dist/frameworks/react/hosts/nitro/info.json +1 -1
  28. package/dist/frameworks/react/hosts/railway/README.md +10 -0
  29. package/dist/frameworks/react/hosts/railway/info.json +1 -1
  30. package/dist/frameworks/solid/add-ons/better-auth/info.json +1 -1
  31. package/dist/frameworks/solid/add-ons/convex/info.json +1 -1
  32. package/dist/frameworks/solid/add-ons/solid-ui/info.json +1 -1
  33. package/dist/frameworks/solid/add-ons/strapi/info.json +1 -1
  34. package/dist/frameworks/solid/add-ons/t3env/info.json +1 -1
  35. package/dist/frameworks/solid/hosts/cloudflare/README.md +11 -0
  36. package/dist/frameworks/solid/hosts/cloudflare/info.json +1 -1
  37. package/dist/frameworks/solid/hosts/netlify/README.md +11 -0
  38. package/dist/frameworks/solid/hosts/netlify/info.json +1 -1
  39. package/dist/frameworks/solid/hosts/nitro/README.md +12 -0
  40. package/dist/frameworks/solid/hosts/nitro/info.json +1 -1
  41. package/dist/frameworks/solid/hosts/railway/README.md +10 -0
  42. package/dist/frameworks/solid/hosts/railway/info.json +1 -1
  43. package/dist/index.js +1 -1
  44. package/dist/integrations/intent.js +25 -0
  45. package/dist/types/add-to-app.d.ts +1 -0
  46. package/dist/types/file-helpers.d.ts +1 -0
  47. package/dist/types/index.d.ts +1 -1
  48. package/dist/types/integrations/intent.d.ts +2 -0
  49. package/dist/types/types.d.ts +1 -0
  50. package/package.json +1 -1
  51. package/src/add-to-app.ts +7 -0
  52. package/src/create-app.ts +89 -22
  53. package/src/custom-add-ons/shared.ts +2 -0
  54. package/src/file-helpers.ts +20 -0
  55. package/src/frameworks/react/add-ons/ai/info.json +1 -1
  56. package/src/frameworks/react/add-ons/better-auth/info.json +1 -1
  57. package/src/frameworks/react/add-ons/clerk/README.md +42 -1
  58. package/src/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +94 -11
  59. package/src/frameworks/react/add-ons/clerk/info.json +1 -1
  60. package/src/frameworks/react/add-ons/compiler/info.json +1 -1
  61. package/src/frameworks/react/add-ons/convex/info.json +1 -1
  62. package/src/frameworks/react/add-ons/drizzle/info.json +1 -1
  63. package/src/frameworks/react/add-ons/mcp/info.json +1 -1
  64. package/src/frameworks/react/add-ons/neon/info.json +1 -1
  65. package/src/frameworks/react/add-ons/paraglide/info.json +1 -1
  66. package/src/frameworks/react/add-ons/prisma/info.json +1 -1
  67. package/src/frameworks/react/add-ons/shadcn/info.json +1 -1
  68. package/src/frameworks/react/add-ons/strapi/info.json +1 -1
  69. package/src/frameworks/react/add-ons/t3env/info.json +1 -1
  70. package/src/frameworks/react/add-ons/workos/info.json +1 -1
  71. package/src/frameworks/react/hosts/cloudflare/README.md +11 -0
  72. package/src/frameworks/react/hosts/cloudflare/info.json +1 -1
  73. package/src/frameworks/react/hosts/netlify/README.md +11 -0
  74. package/src/frameworks/react/hosts/netlify/info.json +1 -1
  75. package/src/frameworks/react/hosts/nitro/README.md +12 -0
  76. package/src/frameworks/react/hosts/nitro/info.json +1 -1
  77. package/src/frameworks/react/hosts/railway/README.md +10 -0
  78. package/src/frameworks/react/hosts/railway/info.json +1 -1
  79. package/src/frameworks/solid/add-ons/better-auth/info.json +1 -1
  80. package/src/frameworks/solid/add-ons/convex/info.json +1 -1
  81. package/src/frameworks/solid/add-ons/solid-ui/info.json +1 -1
  82. package/src/frameworks/solid/add-ons/strapi/info.json +1 -1
  83. package/src/frameworks/solid/add-ons/t3env/info.json +1 -1
  84. package/src/frameworks/solid/hosts/cloudflare/README.md +11 -0
  85. package/src/frameworks/solid/hosts/cloudflare/info.json +1 -1
  86. package/src/frameworks/solid/hosts/netlify/README.md +11 -0
  87. package/src/frameworks/solid/hosts/netlify/info.json +1 -1
  88. package/src/frameworks/solid/hosts/nitro/README.md +12 -0
  89. package/src/frameworks/solid/hosts/nitro/info.json +1 -1
  90. package/src/frameworks/solid/hosts/railway/README.md +10 -0
  91. package/src/frameworks/solid/hosts/railway/info.json +1 -1
  92. package/src/index.ts +1 -0
  93. package/src/integrations/intent.ts +47 -0
  94. package/src/types.ts +1 -0
  95. package/tests/create-app.test.ts +95 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @tanstack/create
2
2
 
3
+ ## 0.65.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat(cli, create): close the gap between `tanstack create` and shipping a real app ([#445](https://github.com/TanStack/cli/pull/445))
8
+
9
+ A bundle of UX improvements aimed at beginners (especially those coming from Next.js) and the AI agents they pair with:
10
+
11
+ - **Tailored post-creation next steps.** The scaffold completion message now lists the env vars you still need to fill in `.env.local`, links the docs for each shipping-critical integration you picked (auth, database, ORM, deployment), and surfaces the Intent-wired AGENTS.md / CLAUDE.md with concrete prompt examples.
12
+ - **Pre-creation review screen.** After interactive prompts, the CLI shows a categorized summary (auth, database, ORM, deploy, other) and asks for confirmation before writing files. Conflicting selections (two auth providers, two ORMs, etc.) are flagged in the same step.
13
+ - **`.env.example` generation.** A checked-in `.env.example` is now derived from the env-var schemas of selected add-ons, with descriptions and a `(required)` marker. Plays nicely with add-ons that ship their own `_dot_env.example.append`.
14
+ - **Better add-on descriptions.** Concept-first one-liners replace generic "Add X to your application." Reads like a menu instead of a list of brand names.
15
+ - **Deployment quickstarts.** Each `--deployment` host (Netlify, Cloudflare, Railway, Nitro) now contributes its own README section explaining the actual steps to ship — push, dashboard URL, env var sync.
16
+ - **Clerk demo route parity.** Clerk's scaffold now ships a proper sign-in flow (matching Better Auth's depth) using Clerk's prebuilt components, plus a richer README with route-protection patterns and a production checklist.
17
+ - **Intent install passes `--map`.** The auto-invoked `intent install` now writes explicit task→skill mappings into the agent config instead of relying on runtime discovery, so agents see directly which skill matches which task.
18
+ - **`tanstack clean-demos` command.** A new subcommand removes leftover `demo.*` and `example.*` files (and prunes empty `routes/demo`/`routes/example` directories) so a beginner can ship without the scaffold's training wheels.
19
+
20
+ ## 0.64.0
21
+
22
+ ### Minor Changes
23
+
24
+ - feat(cli): auto-install TanStack Intent during scaffolding ([#442](https://github.com/TanStack/cli/pull/442))
25
+
26
+ `tanstack create` and `tanstack add` now run `npx @tanstack/intent install`
27
+ after dependency installation, wiring up skill mappings for coding agents.
28
+ The behavior is controlled by a new `--intent` / `--no-intent` flag (default
29
+ on) and persists to `.cta.json` so subsequent `add` invocations honor the
30
+ original choice. Failures are surfaced as warnings instead of aborting the
31
+ scaffold.
32
+
3
33
  ## 0.63.9
4
34
 
5
35
  ### Patch Changes
@@ -11,6 +11,7 @@ import { isBase64, recursivelyGatherFilesFromEnvironment, } from './file-helpers
11
11
  import { mergePackageJSON } from './package-json.js';
12
12
  import { runSpecialSteps } from './special-steps/index.js';
13
13
  import { loadStarter } from './custom-add-ons/starter.js';
14
+ import { setupIntent } from './integrations/intent.js';
14
15
  export async function hasPendingGitChanges(environment, cwd) {
15
16
  const { stdout } = await environment.execute('git', ['status', '--porcelain'], cwd);
16
17
  return stdout.length > 0;
@@ -29,6 +30,7 @@ async function createOptions(json, addOns, targetDir) {
29
30
  ]),
30
31
  targetDir,
31
32
  starter,
33
+ intent: json.intent ?? false,
32
34
  };
33
35
  }
34
36
  async function runCreateApp(options) {
@@ -203,6 +205,9 @@ export async function addToApp(environment, addOns, cwd, options) {
203
205
  }
204
206
  // Handle new commands
205
207
  await runNewCommands(environment, persistedOptions, cwd, output);
208
+ const intent = options?.intent ?? persistedOptions.intent ?? true;
209
+ newOptions.intent = intent;
210
+ await setupIntent(environment, cwd, newOptions);
206
211
  environment.startStep({
207
212
  id: 'write-config-file',
208
213
  type: 'file',
@@ -1,5 +1,5 @@
1
1
  import { basename, resolve } from 'node:path';
2
- import { isBase64 } from './file-helpers.js';
2
+ import { isBase64, isDemoFilePath } from './file-helpers.js';
3
3
  import { formatCommand } from './utils.js';
4
4
  import { writeConfigFileToEnvironment } from './config-file.js';
5
5
  import { getPackageManagerScriptCommand, packageManagerInstall, translateExecuteCommand, } from './package-manager.js';
@@ -8,21 +8,8 @@ import { resolvePackageJSONLatest } from './npm-resolver.js';
8
8
  import { createTemplateFile } from './template-file.js';
9
9
  import { installShadcnComponents } from './integrations/shadcn.js';
10
10
  import { setupGit } from './integrations/git.js';
11
+ import { setupIntent } from './integrations/intent.js';
11
12
  import { runSpecialSteps } from './special-steps/index.js';
12
- function isDemoFilePath(path) {
13
- if (!path)
14
- return false;
15
- const normalized = path.replace(/\\/g, '/');
16
- if (normalized.includes('/routes/demo/') ||
17
- normalized.includes('/routes/example/')) {
18
- return true;
19
- }
20
- const filename = normalized.split('/').pop() || '';
21
- return (filename.startsWith('demo.') ||
22
- filename.startsWith('demo-') ||
23
- filename.startsWith('example.') ||
24
- filename.startsWith('example-'));
25
- }
26
13
  function stripExamplesFromOptions(options) {
27
14
  if (options.includeExamples !== false) {
28
15
  return options;
@@ -214,6 +201,7 @@ async function runCommandsAndInstallDependencies(environment, options) {
214
201
  s.stop(`${options.starter.name} commands complete`);
215
202
  }
216
203
  await installShadcnComponents(environment, options.targetDir, options);
204
+ await setupIntent(environment, options.targetDir, options);
217
205
  }
218
206
  async function seedEnvValues(environment, options) {
219
207
  const envVarValues = options.envVarValues || {};
@@ -238,6 +226,74 @@ async function seedEnvValues(environment, options) {
238
226
  }
239
227
  await environment.writeFile(envLocalPath, envContents);
240
228
  }
229
+ async function writeEnvExample(environment, options) {
230
+ const envExamplePath = resolve(options.targetDir, '.env.example');
231
+ const existing = environment.exists(envExamplePath)
232
+ ? await environment.readFile(envExamplePath)
233
+ : '';
234
+ const declared = new Set();
235
+ for (const match of existing.matchAll(/^([A-Z_][A-Z0-9_]*)=/gm)) {
236
+ declared.add(match[1]);
237
+ }
238
+ const sections = [];
239
+ for (const addOn of options.chosenAddOns) {
240
+ const lines = [];
241
+ for (const envVar of addOn.envVars || []) {
242
+ if (declared.has(envVar.name))
243
+ continue;
244
+ declared.add(envVar.name);
245
+ if (envVar.description) {
246
+ const required = envVar.required ? ' (required)' : '';
247
+ lines.push(`# ${envVar.description}${required}`);
248
+ }
249
+ lines.push(`${envVar.name}=`);
250
+ }
251
+ if (lines.length > 0) {
252
+ sections.push(`# ${addOn.name}\n${lines.join('\n')}`);
253
+ }
254
+ }
255
+ if (sections.length === 0)
256
+ return;
257
+ const additions = sections.join('\n\n');
258
+ const newContent = existing
259
+ ? `${existing.trimEnd()}\n\n${additions}\n`
260
+ : `${additions}\n`;
261
+ await environment.writeFile(envExamplePath, newContent);
262
+ }
263
+ const SHIPPING_CATEGORIES = new Set(['auth', 'database', 'orm', 'deploy']);
264
+ function buildNextSteps(options) {
265
+ const collectedEnv = new Set(Object.keys(options.envVarValues || {}));
266
+ const listedEnvVars = new Set();
267
+ const envVarLines = [];
268
+ const docLines = [];
269
+ for (const addOn of options.chosenAddOns) {
270
+ if (addOn.link && addOn.category && SHIPPING_CATEGORIES.has(addOn.category)) {
271
+ docLines.push(` • ${addOn.name} (${addOn.category}) — ${addOn.link}`);
272
+ }
273
+ for (const envVar of addOn.envVars || []) {
274
+ if (listedEnvVars.has(envVar.name))
275
+ continue;
276
+ listedEnvVars.add(envVar.name);
277
+ const required = envVar.required ? ' (required)' : '';
278
+ const status = collectedEnv.has(envVar.name)
279
+ ? ' — already set from your input'
280
+ : ' — needs a value';
281
+ const desc = envVar.description ? ` — ${envVar.description}` : '';
282
+ envVarLines.push(` • ${envVar.name}${required}${desc}${status}`);
283
+ }
284
+ }
285
+ const sections = [];
286
+ if (envVarLines.length > 0) {
287
+ sections.push(`Environment variables (review/fill in .env.local before deploying):\n${envVarLines.join('\n')}`);
288
+ }
289
+ if (docLines.length > 0) {
290
+ sections.push(`Docs for the integrations you picked:\n${docLines.join('\n')}`);
291
+ }
292
+ if (options.intent) {
293
+ sections.push(`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nwith explicit skill mappings for the libraries you installed. Try asking your agent:\n • "migrate this Next.js page to TanStack Start"\n • "add a protected /dashboard route"\n • "show me how to use TanStack Router search params"`);
294
+ }
295
+ return sections.length > 0 ? `\nNext steps:\n\n${sections.join('\n\n')}\n` : '';
296
+ }
241
297
  function report(environment, options) {
242
298
  const warnings = [];
243
299
  for (const addOn of options.chosenAddOns) {
@@ -266,12 +322,13 @@ ${environment.getErrors().join('\n')}`;
266
322
  ? ''
267
323
  : `% cd ${options.projectName}
268
324
  `;
325
+ const nextSteps = buildNextSteps(options);
269
326
  // Use the force luke! :)
270
327
  environment.outro(`${locationMessage}
271
328
 
272
329
  Use the following commands to start your app:
273
330
  ${cdInstruction}% ${formatCommand(getPackageManagerScriptCommand(options.packageManager, ['dev']))}
274
-
331
+ ${nextSteps}
275
332
  Please read the README.md file for information on testing, styling, adding routes, etc.${errorStatement}`);
276
333
  }
277
334
  export async function createApp(environment, options) {
@@ -279,6 +336,7 @@ export async function createApp(environment, options) {
279
336
  environment.startRun();
280
337
  await writeFiles(environment, effectiveOptions);
281
338
  await seedEnvValues(environment, effectiveOptions);
339
+ await writeEnvExample(environment, effectiveOptions);
282
340
  await runCommandsAndInstallDependencies(environment, effectiveOptions);
283
341
  environment.finishRun();
284
342
  report(environment, effectiveOptions);
@@ -60,6 +60,7 @@ export async function createAppOptionsFromPersisted(json) {
60
60
  starter: json.starter ? await loadStarter(json.starter) : undefined,
61
61
  chosenAddOns,
62
62
  addOnOptions: populateAddOnOptionsDefaults(chosenAddOns),
63
+ intent: json.intent ?? false,
63
64
  };
64
65
  }
65
66
  export function createSerializedOptionsFromPersisted(json) {
@@ -78,6 +79,7 @@ export function createSerializedOptionsFromPersisted(json) {
78
79
  framework: json.framework,
79
80
  starter: json.starter,
80
81
  addOnOptions: {},
82
+ intent: json.intent ?? false,
81
83
  };
82
84
  }
83
85
  export async function runCreateApp(options) {
@@ -90,6 +90,20 @@ export function relativePath(from, to, stripExtension = false) {
90
90
  export function isDirectory(path) {
91
91
  return statSync(path).isDirectory();
92
92
  }
93
+ export function isDemoFilePath(path) {
94
+ if (!path)
95
+ return false;
96
+ const normalized = path.replace(/\\/g, '/');
97
+ if (normalized.includes('/routes/demo/') ||
98
+ normalized.includes('/routes/example/')) {
99
+ return true;
100
+ }
101
+ const filename = normalized.split('/').pop() || '';
102
+ return (filename.startsWith('demo.') ||
103
+ filename.startsWith('demo-') ||
104
+ filename.startsWith('example.') ||
105
+ filename.startsWith('example-'));
106
+ }
93
107
  export function findFilesRecursively(path, files) {
94
108
  const dirFiles = readdirSync(path);
95
109
  for (const file of dirFiles) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "AI",
3
- "description": "TanStack AI integration and examples.",
3
+ "description": "Streaming chat UI with model-agnostic backend (OpenAI, Anthropic, etc).",
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Better Auth",
3
- "description": "Add Better Auth authentication to your application.",
3
+ "description": "Self-hosted user accounts and sessions (open source, full control).",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
6
  "category": "auth",
@@ -1,3 +1,44 @@
1
1
  ## Setting up Clerk
2
2
 
3
- - Set the `VITE_CLERK_PUBLISHABLE_KEY` in your `.env.local`.
3
+ 1. Sign up at [clerk.com](https://clerk.com) and create an application
4
+ 2. Copy the **Publishable Key** from the Clerk dashboard
5
+ 3. Set it in your `.env.local`:
6
+ ```bash
7
+ VITE_CLERK_PUBLISHABLE_KEY=pk_test_...
8
+ ```
9
+ 4. Visit the demo route at `/demo/clerk` once `npm run dev` is running
10
+
11
+ ### What's wired up
12
+
13
+ - **`<ClerkProvider>`** at the app root (`src/integrations/clerk/provider.tsx`) handles auth context for the whole tree
14
+ - **`<SignInButton>` / `<UserButton>`** in the header swap based on auth state
15
+ - **`/demo/clerk`** shows Clerk's prebuilt sign-in UI and a signed-in greeting
16
+
17
+ ### Protecting a route
18
+
19
+ Wrap any component in `<SignedIn>` / `<SignedOut>`:
20
+
21
+ ```tsx
22
+ import { SignedIn, SignedOut, RedirectToSignIn } from '@clerk/clerk-react'
23
+
24
+ function ProtectedPage() {
25
+ return (
26
+ <>
27
+ <SignedIn>
28
+ <YourPageContent />
29
+ </SignedIn>
30
+ <SignedOut>
31
+ <RedirectToSignIn />
32
+ </SignedOut>
33
+ </>
34
+ )
35
+ }
36
+ ```
37
+
38
+ For server-side checks (route loaders, server functions), see the Clerk docs on [`auth()`](https://clerk.com/docs/references/backend/auth).
39
+
40
+ ### Production checklist
41
+
42
+ - Replace the test keys with **production keys** from a dedicated production Clerk instance
43
+ - Configure your production domain under **Domains** in the Clerk dashboard
44
+ - Set up social providers (Google, GitHub, etc.) under **User & Authentication → Social Connections**
@@ -1,20 +1,103 @@
1
1
  import { createFileRoute } from '@tanstack/react-router'
2
- import { useUser } from '@clerk/clerk-react'
2
+ import {
3
+ SignIn,
4
+ SignedIn,
5
+ SignedOut,
6
+ useUser,
7
+ } from '@clerk/clerk-react'
3
8
 
4
9
  export const Route = createFileRoute('/demo/clerk')({
5
- component: App,
10
+ component: ClerkDemo,
6
11
  })
7
12
 
8
- function App() {
9
- const { isSignedIn, user, isLoaded } = useUser()
13
+ function ClerkDemo() {
14
+ return (
15
+ <div className="flex justify-center py-10 px-4">
16
+ <div className="w-full max-w-md p-6 space-y-6">
17
+ <SignedOut>
18
+ <div className="space-y-1.5">
19
+ <h1 className="text-lg font-semibold leading-none tracking-tight">
20
+ Sign in to continue
21
+ </h1>
22
+ <p className="text-sm text-neutral-500 dark:text-neutral-400">
23
+ Clerk renders the sign-in UI, manages sessions, and handles social providers for you.
24
+ </p>
25
+ </div>
26
+ <div className="flex justify-center pt-2">
27
+ <SignIn routing="hash" />
28
+ </div>
29
+ <p className="text-xs text-center text-neutral-400 dark:text-neutral-500">
30
+ Built with{' '}
31
+ <a
32
+ href="https://clerk.com"
33
+ target="_blank"
34
+ rel="noopener noreferrer"
35
+ className="font-medium hover:text-neutral-600 dark:hover:text-neutral-300"
36
+ >
37
+ CLERK
38
+ </a>
39
+ .
40
+ </p>
41
+ </SignedOut>
10
42
 
11
- if (!isLoaded) {
12
- return <div className="p-4">Loading...</div>
13
- }
43
+ <SignedIn>
44
+ <SignedInGreeting />
45
+ </SignedIn>
46
+ </div>
47
+ </div>
48
+ )
49
+ }
50
+
51
+ function SignedInGreeting() {
52
+ const { user } = useUser()
53
+ if (!user) return null
54
+
55
+ const email = user.primaryEmailAddress?.emailAddress
56
+ const initial = (user.firstName || email || 'U').charAt(0).toUpperCase()
57
+
58
+ return (
59
+ <div className="space-y-6">
60
+ <div className="space-y-1.5">
61
+ <h1 className="text-lg font-semibold leading-none tracking-tight">
62
+ Welcome back
63
+ </h1>
64
+ <p className="text-sm text-neutral-500 dark:text-neutral-400">
65
+ You're signed in as {email}
66
+ </p>
67
+ </div>
14
68
 
15
- if (!isSignedIn) {
16
- return <div className="p-4">Sign in to view this page</div>
17
- }
69
+ <div className="flex items-center gap-3">
70
+ {user.imageUrl ? (
71
+ <img src={user.imageUrl} alt="" className="h-10 w-10 rounded-full" />
72
+ ) : (
73
+ <div className="h-10 w-10 bg-neutral-200 dark:bg-neutral-800 flex items-center justify-center rounded-full">
74
+ <span className="text-sm font-medium text-neutral-600 dark:text-neutral-400">
75
+ {initial}
76
+ </span>
77
+ </div>
78
+ )}
79
+ <div className="flex-1 min-w-0">
80
+ <p className="text-sm font-medium truncate">
81
+ {user.firstName} {user.lastName}
82
+ </p>
83
+ <p className="text-xs text-neutral-500 dark:text-neutral-400 truncate">
84
+ {email}
85
+ </p>
86
+ </div>
87
+ </div>
18
88
 
19
- return <div className="p-4">Hello {user.firstName}!</div>
89
+ <p className="text-xs text-center text-neutral-400 dark:text-neutral-500">
90
+ Manage your account from the avatar in the header. Built with{' '}
91
+ <a
92
+ href="https://clerk.com"
93
+ target="_blank"
94
+ rel="noopener noreferrer"
95
+ className="font-medium hover:text-neutral-600 dark:hover:text-neutral-300"
96
+ >
97
+ CLERK
98
+ </a>
99
+ .
100
+ </p>
101
+ </div>
102
+ )
20
103
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Clerk",
3
- "description": "Add Clerk authentication to your application.",
3
+ "description": "Hosted user accounts with prebuilt sign-in UI and social providers (managed).",
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "Compiler",
3
3
  "phase": "setup",
4
- "description": "Add React Compiler",
4
+ "description": "Auto-memoize components and hooks (fewer re-renders, no manual useMemo/useCallback).",
5
5
  "link": "https://react.dev/learn/react-compiler",
6
6
  "modes": ["code-router", "file-router"],
7
7
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Convex",
3
- "description": "Add the Convex database to your application.",
3
+ "description": "Reactive document database with real-time queries and serverless functions.",
4
4
  "link": "https://convex.dev",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Drizzle",
3
- "description": "Add Drizzle ORM to your application.",
3
+ "description": "Type-safe SQL query builder for Postgres, SQLite, or MySQL.",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
6
  "category": "orm",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "MCP",
3
3
  "phase": "setup",
4
- "description": "Add Model Context Protocol (MCP) support.",
4
+ "description": "Expose your app as an MCP server so AI clients (Claude, Cursor) can call into it.",
5
5
  "link": "https://mcp.dev",
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Neon",
3
- "description": "Add the Neon database to your application.",
3
+ "description": "Serverless Postgres (auto-scales to zero, branchable per environment).",
4
4
  "link": "https://neon.com",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Paraglide (i18n)",
3
- "description": "i18n with localized routing",
3
+ "description": "Type-safe i18n with localized routing and message bundles.",
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Prisma",
3
- "description": "Add Prisma Postgres, or Prisma ORM with other DBs to your application.",
3
+ "description": "Type-safe database client with schema migrations (Postgres, MySQL, SQLite, MongoDB).",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
6
  "category": "orm",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Shadcn",
3
- "description": "Add Shadcn UI to your application.",
3
+ "description": "Copy-paste accessible UI components (Tailwind + Radix primitives).",
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router", "code-router"],
6
6
  "link": "https://ui.shadcn.com/",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Strapi",
3
- "description": "Use the Strapi CMS to manage your content.",
3
+ "description": "Headless CMS with admin UI (self-hosted, content models in TypeScript).",
4
4
  "link": "https://strapi.io/",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "T3Env",
3
- "description": "Add type safety to your environment variables",
3
+ "description": "Validate process.env at build time (catch missing/wrong env vars before runtime).",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
6
  "category": "tooling",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "WorkOS",
3
- "description": "Add WorkOS authentication to your application.",
3
+ "description": "Enterprise SSO, SAML, and directory sync (good for B2B apps).",
4
4
  "phase": "add-on",
5
5
  "modes": ["file-router"],
6
6
  "type": "add-on",
@@ -0,0 +1,11 @@
1
+ ## Deploy to Cloudflare Workers
2
+
3
+ This project uses the Cloudflare Vite plugin (configured in `vite.config.ts`) and `wrangler.jsonc`:
4
+
5
+ 1. Install Wrangler: `npm install -g wrangler`
6
+ 2. Authenticate: `wrangler login`
7
+ 3. Deploy: `npx wrangler deploy`
8
+
9
+ For production env vars, run `wrangler secret put MY_VAR` for each secret listed in `.env.example`. Public (non-secret) vars go in `wrangler.jsonc` under `vars`.
10
+
11
+ KV, D1, R2, and Durable Object bindings are configured in `wrangler.jsonc` — see https://developers.cloudflare.com/workers/wrangler/configuration/.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Cloudflare",
3
- "description": "Cloudflare deployment setup",
3
+ "description": "Deploy to Cloudflare Workers (edge runtime, KV/D1/R2 bindings).",
4
4
  "link": "https://developers.cloudflare.com/workers/vite-plugin/",
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
@@ -0,0 +1,11 @@
1
+ ## Deploy to Netlify
2
+
3
+ This project ships with `netlify.toml` configured for a Netlify site:
4
+
5
+ 1. Push this repo to GitHub
6
+ 2. Visit https://app.netlify.com/start and import the repo
7
+ 3. Netlify auto-detects the build (`vite build` → `dist/client`)
8
+ 4. Open **Site settings → Environment variables** and add anything from `.env.example` that needs a real value in production
9
+ 5. Trigger the first deploy
10
+
11
+ Server functions and API routes run on Netlify Functions. For lower-latency request handling, see Netlify Edge Functions: https://docs.netlify.com/edge-functions/overview.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Netlify",
3
- "description": "Netlify deployment setup",
3
+ "description": "Deploy to Netlify (Functions and Edge Functions, GitHub-driven).",
4
4
  "link": "https://docs.netlify.com",
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
@@ -0,0 +1,12 @@
1
+ ## Deploy with Nitro
2
+
3
+ This project uses Nitro as a generic server adapter, so it can run on any Node-compatible host.
4
+
5
+ ```bash
6
+ npm run build
7
+ node dist/server/index.mjs
8
+ ```
9
+
10
+ The build output is a self-contained Node server. To deploy, push the `dist/` directory to your host (Render, Fly.io, your own VPS, etc.) and run the server command above.
11
+
12
+ For host-specific presets (Vercel, Netlify, Cloudflare, AWS Lambda, etc.) and tuning, see https://v3.nitro.build/deploy.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Nitro (agnostic)",
3
- "description": "Nitro deployment setup",
3
+ "description": "Generic Nitro adapter (deploy to any Node-compatible host).",
4
4
  "link": "https://v3.nitro.build/",
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
@@ -0,0 +1,10 @@
1
+ ## Deploy to Railway
2
+
3
+ This project ships with `nixpacks.toml` so Railway detects the build automatically:
4
+
5
+ 1. Push this repo to GitHub
6
+ 2. Visit https://railway.com/new and create a project from your repo
7
+ 3. In the **Variables** tab, add the entries from `.env.example` with their production values
8
+ 4. Railway runs `vite build` and serves from `dist/client`
9
+
10
+ Need a database? Click **+ New** in your project to provision Postgres, MySQL, or Redis directly into the same environment — the connection string is auto-injected as `DATABASE_URL`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Railway",
3
- "description": "Railway deployment setup",
3
+ "description": "Deploy to Railway (full-stack PaaS for Node + databases).",
4
4
  "link": "https://railway.com/",
5
5
  "phase": "add-on",
6
6
  "modes": ["file-router", "code-router"],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Better Auth",
3
- "description": "Add Better Auth authentication to your application.",
3
+ "description": "Self-hosted user accounts and sessions (open source, full control).",
4
4
  "phase": "add-on",
5
5
  "type": "add-on",
6
6
  "category": "auth",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Convex",
3
- "description": "Add the Convex database to your application.",
3
+ "description": "Reactive document database with real-time queries and serverless functions.",
4
4
  "link": "https://convex.dev",
5
5
  "phase": "add-on",
6
6
  "type": "add-on",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Solid-UI",
3
- "description": "Add Solid-UI to your application.",
3
+ "description": "Copy-paste accessible UI components for Solid (Tailwind + Radix-style primitives).",
4
4
  "phase": "add-on",
5
5
  "link": "https://ui.shadcn.com/",
6
6
  "modes": ["file-router", "code-router"],