@tanstack/cta-framework-react-cra 0.43.1 → 0.44.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 (41) hide show
  1. package/add-ons/apollo-client/README.md +150 -0
  2. package/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +75 -0
  3. package/add-ons/apollo-client/info.json +19 -0
  4. package/add-ons/apollo-client/package.json +8 -0
  5. package/add-ons/apollo-client/small-logo.svg +11 -0
  6. package/add-ons/convex/package.json +2 -2
  7. package/add-ons/db/assets/src/hooks/demo.useChat.ts +1 -1
  8. package/add-ons/db/assets/src/routes/demo/db-chat-api.ts +4 -1
  9. package/add-ons/db/package.json +1 -1
  10. package/add-ons/mcp/package.json +1 -1
  11. package/add-ons/neon/package.json +1 -1
  12. package/add-ons/sentry/assets/instrument.server.mjs +16 -9
  13. package/add-ons/sentry/assets/src/routes/demo/sentry.testing.tsx +42 -2
  14. package/add-ons/shadcn/package.json +1 -1
  15. package/add-ons/start/assets/src/router.tsx.ejs +34 -10
  16. package/add-ons/start/package.json +2 -2
  17. package/add-ons/store/package.json +3 -3
  18. package/add-ons/storybook/package.json +2 -2
  19. package/examples/tanchat/assets/src/hooks/useAudioRecorder.ts +85 -0
  20. package/examples/tanchat/assets/src/hooks/useTTS.ts +78 -0
  21. package/examples/tanchat/assets/src/lib/model-selection.ts +78 -0
  22. package/examples/tanchat/assets/src/lib/vendor-capabilities.ts +55 -0
  23. package/examples/tanchat/assets/src/routes/demo/api.available-providers.ts +35 -0
  24. package/examples/tanchat/assets/src/routes/demo/api.image.ts +74 -0
  25. package/examples/tanchat/assets/src/routes/demo/api.structured.ts +168 -0
  26. package/examples/tanchat/assets/src/routes/demo/api.tanchat.ts +89 -0
  27. package/examples/tanchat/assets/src/routes/demo/api.transcription.ts +89 -0
  28. package/examples/tanchat/assets/src/routes/demo/api.tts.ts +81 -0
  29. package/examples/tanchat/assets/src/routes/demo/image.tsx +257 -0
  30. package/examples/tanchat/assets/src/routes/demo/structured.tsx +460 -0
  31. package/examples/tanchat/assets/src/routes/demo/tanchat.css +14 -7
  32. package/examples/tanchat/assets/src/routes/demo/tanchat.tsx +301 -81
  33. package/examples/tanchat/info.json +10 -7
  34. package/examples/tanchat/package.json +8 -5
  35. package/package.json +2 -2
  36. package/project/base/src/routes/__root.tsx.ejs +14 -6
  37. package/tests/react-cra.test.ts +14 -0
  38. package/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json +31 -0
  39. package/tests/snapshots/react-cra/cr-ts-start-npm.json +2 -2
  40. package/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json +2 -2
  41. package/examples/tanchat/assets/src/routes/demo/api.tanchat.ts.ejs +0 -72
@@ -0,0 +1,31 @@
1
+ {
2
+ "files": {
3
+ ".cta.json": "{\n \"addOns\": true,\n \"git\": true,\n \"mode\": \"file-router\",\n \"packageManager\": \"npm\",\n \"projectName\": \"TEST\",\n \"tailwind\": true,\n \"typescript\": true,\n \"variableValues\": {},\n \"version\": 1,\n \"framework\": \"react-cra\",\n \"chosenAddOns\": [\n \"start\",\n \"apollo-client\"\n ]\n}",
4
+ ".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\ncount.txt\n.env\n.nitro\n.tanstack\n.wrangler\n.output\n.vinxi\ntodos.json\n",
5
+ "/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
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
+ "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
+ "/src/components/Header.tsx": "import { Link } from '@tanstack/react-router'\n\nimport { useState } from 'react'\nimport {\n ChevronDown,\n ChevronRight,\n Home,\n Menu,\n Network,\n SquareFunction,\n StickyNote,\n X,\n} from 'lucide-react'\n\nexport default function Header() {\n const [isOpen, setIsOpen] = useState(false)\n const [groupedExpanded, setGroupedExpanded] = useState<\n Record<string, boolean>\n >({})\n\n return (\n <>\n <header className=\"p-4 flex items-center bg-gray-800 text-white shadow-lg\">\n <button\n onClick={() => setIsOpen(true)}\n className=\"p-2 hover:bg-gray-700 rounded-lg transition-colors\"\n aria-label=\"Open menu\"\n >\n <Menu size={24} />\n </button>\n <h1 className=\"ml-4 text-xl font-semibold\">\n <Link to=\"/\">\n <img\n src=\"/tanstack-word-logo-white.svg\"\n alt=\"TanStack Logo\"\n className=\"h-10\"\n />\n </Link>\n </h1>\n </header>\n\n <aside\n className={`fixed top-0 left-0 h-full w-80 bg-gray-900 text-white shadow-2xl z-50 transform transition-transform duration-300 ease-in-out flex flex-col ${\n isOpen ? 'translate-x-0' : '-translate-x-full'\n }`}\n >\n <div className=\"flex items-center justify-between p-4 border-b border-gray-700\">\n <h2 className=\"text-xl font-bold\">Navigation</h2>\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n aria-label=\"Close menu\"\n >\n <X size={24} />\n </button>\n </div>\n\n <nav className=\"flex-1 p-4 overflow-y-auto\">\n <Link\n to=\"/\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <Home size={20} />\n <span className=\"font-medium\">Home</span>\n </Link>\n\n {/* Demo Links Start */}\n\n <Link\n to=\"/demo/start/server-funcs\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <SquareFunction size={20} />\n <span className=\"font-medium\">Start - Server Functions</span>\n </Link>\n\n <Link\n to=\"/demo/start/api-request\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <Network size={20} />\n <span className=\"font-medium\">Start - API Request</span>\n </Link>\n\n <div className=\"flex flex-row justify-between\">\n <Link\n to=\"/demo/start/ssr\"\n onClick={() => setIsOpen(false)}\n className=\"flex-1 flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex-1 flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Start - SSR Demos</span>\n </Link>\n <button\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n onClick={() =>\n setGroupedExpanded((prev) => ({\n ...prev,\n StartSSRDemo: !prev.StartSSRDemo,\n }))\n }\n >\n {groupedExpanded.StartSSRDemo ? (\n <ChevronDown size={20} />\n ) : (\n <ChevronRight size={20} />\n )}\n </button>\n </div>\n {groupedExpanded.StartSSRDemo && (\n <div className=\"flex flex-col ml-4\">\n <Link\n to=\"/demo/start/ssr/spa-mode\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">SPA Mode</span>\n </Link>\n\n <Link\n to=\"/demo/start/ssr/full-ssr\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Full SSR</span>\n </Link>\n\n <Link\n to=\"/demo/start/ssr/data-only\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Data Only</span>\n </Link>\n </div>\n )}\n\n <Link\n to=\"/demo/apollo-client\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <Network size={20} />\n <span className=\"font-medium\">Apollo Client</span>\n </Link>\n\n {/* Demo Links End */}\n </nav>\n </aside>\n </>\n )\n}\n",
9
+ "/src/data/demo.punk-songs.ts": "import { createServerFn } from '@tanstack/react-start'\n\nexport const getPunkSongs = createServerFn({\n method: 'GET',\n}).handler(async () => [\n { id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' },\n { id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' },\n { id: 3, name: 'The Middle', artist: 'Jimmy Eat World' },\n { id: 4, name: 'My Own Worst Enemy', artist: 'Lit' },\n { id: 5, name: 'Fat Lip', artist: 'Sum 41' },\n { id: 6, name: 'All the Small Things', artist: 'blink-182' },\n { id: 7, name: 'Beverly Hills', artist: 'Weezer' },\n])\n",
10
+ "/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\nimport {\n routerWithApolloClient,\n ApolloClient,\n InMemoryCache,\n} from '@apollo/client-integration-tanstack-start'\nimport { HttpLink } from '@apollo/client'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n // Configure Apollo Client\n const apolloClient = new ApolloClient({\n cache: new InMemoryCache(),\n link: new HttpLink({\n uri:\n import.meta.env.VITE_GRAPHQL_ENDPOINT ||\n 'https://countries.trevorblades.com/',\n }),\n })\n\n const router = createRouter({\n routeTree,\n context: {\n ...routerWithApolloClient.defaultContext,\n },\n\n defaultPreload: 'intent',\n })\n\n return routerWithApolloClient(router, apolloClient)\n}\n",
11
+ "/src/routes/__root.tsx": "import {\n HeadContent,\n Scripts,\n createRootRouteWithContext,\n} from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nimport Header from '../components/Header'\n\nimport appCss from '../styles.css?url'\n\nimport type { ApolloClientIntegration } from '@apollo/client-integration-tanstack-start'\n\ninterface MyRouterContext extends ApolloClientIntegration.RouterContext {}\n\nexport const Route = createRootRouteWithContext<MyRouterContext>()({\n head: () => ({\n meta: [\n {\n charSet: 'utf-8',\n },\n {\n name: 'viewport',\n content: 'width=device-width, initial-scale=1',\n },\n {\n title: 'TanStack Start Starter',\n },\n ],\n links: [\n {\n rel: 'stylesheet',\n href: appCss,\n },\n ],\n }),\n\n shellComponent: RootDocument,\n})\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Header />\n {children}\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n <Scripts />\n </body>\n </html>\n )\n}\n",
12
+ "/src/routes/demo.apollo-client.tsx": "import { gql, TypedDocumentNode } from '@apollo/client'\nimport { useReadQuery } from '@apollo/client/react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport React from 'react'\n\n// Example GraphQL query - replace with your own schema\nconst EXAMPLE_QUERY: TypedDocumentNode<{\n continents: { __typename: string; code: string; name: string }\n}> = gql`\n query ExampleQuery {\n continents {\n code\n name\n }\n }\n`\n\nexport const Route = createFileRoute('/demo/apollo-client')({\n component: RouteComponent,\n loader: ({ context: { preloadQuery } }) => {\n // Preload the query in the loader for optimal performance\n const queryRef = preloadQuery(EXAMPLE_QUERY, {\n variables: {},\n })\n return {\n queryRef,\n }\n },\n})\n\nfunction RouteComponent() {\n const { queryRef } = Route.useLoaderData()\n const { data } = useReadQuery(queryRef)\n\n return (\n <div className=\"p-4\">\n <h2 className=\"text-2xl font-bold mb-4\">Apollo Client Demo</h2>\n <div className=\"bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded mb-4\">\n <p className=\"font-bold\">Apollo Client is configured!</p>\n <p className=\"text-sm mt-2\">\n This demo uses{' '}\n <code className=\"bg-blue-200 px-1 rounded\">preloadQuery</code> in the\n loader and{' '}\n <code className=\"bg-blue-200 px-1 rounded\">useReadQuery</code> in the\n component for optimal streaming SSR performance.\n </p>\n </div>\n <div className=\"bg-gray-100 p-4 rounded\">\n <h3 className=\"font-bold mb-2\">Query Result:</h3>\n <pre className=\"text-sm overflow-x-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n </div>\n <div className=\"mt-4 text-sm text-gray-600\">\n <p>📝 Next steps:</p>\n <ul className=\"list-disc ml-6 mt-2\">\n <li>\n Configure your GraphQL endpoint in{' '}\n <code className=\"bg-gray-200 px-1 rounded\">src/router.tsx</code>\n </li>\n <li>Replace the example query with your actual GraphQL schema</li>\n <li>\n Learn more:{' '}\n <a\n href=\"https://www.apollographql.com/docs/react\"\n className=\"text-blue-600 hover:underline\"\n >\n Apollo Client Docs\n </a>\n </li>\n </ul>\n </div>\n </div>\n )\n}\n",
13
+ "/src/routes/demo/api.names.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nexport const Route = createFileRoute('/demo/api/names')({\n server: {\n handlers: {\n GET: () => json(['Alice', 'Bob', 'Charlie']),\n },\n },\n})\n",
14
+ "/src/routes/demo/start.api-request.tsx": "import { useEffect, useState } from 'react'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState<Array<string>>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
15
+ "/src/routes/demo/start.server-funcs.tsx": "import fs from 'node:fs'\nimport { useCallback, useState } from 'react'\nimport { createFileRoute, useRouter } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\n\n/*\nconst loggingMiddleware = createMiddleware().server(\n async ({ next, request }) => {\n console.log(\"Request:\", request.url);\n return next();\n }\n);\nconst loggedServerFunction = createServerFn({ method: \"GET\" }).middleware([\n loggingMiddleware,\n]);\n*/\n\nconst TODOS_FILE = 'todos.json'\n\nasync function readTodos() {\n return JSON.parse(\n await fs.promises.readFile(TODOS_FILE, 'utf-8').catch(() =>\n JSON.stringify(\n [\n { id: 1, name: 'Get groceries' },\n { id: 2, name: 'Buy a new phone' },\n ],\n null,\n 2,\n ),\n ),\n )\n}\n\nconst getTodos = createServerFn({\n method: 'GET',\n}).handler(async () => await readTodos())\n\nconst addTodo = createServerFn({ method: 'POST' })\n .inputValidator((d: string) => d)\n .handler(async ({ data }) => {\n const todos = await readTodos()\n todos.push({ id: todos.length + 1, name: data })\n await fs.promises.writeFile(TODOS_FILE, JSON.stringify(todos, null, 2))\n return todos\n })\n\nexport const Route = createFileRoute('/demo/start/server-funcs')({\n component: Home,\n loader: async () => await getTodos(),\n})\n\nfunction Home() {\n const router = useRouter()\n let todos = Route.useLoaderData()\n\n const [todo, setTodo] = useState('')\n\n const submitTodo = useCallback(async () => {\n todos = await addTodo({ data: todo })\n setTodo('')\n router.invalidate()\n }, [addTodo, todo])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #23272a 0%, #18181b 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start Server Functions - Todo Example</h1>\n <ul className=\"mb-4 space-y-2\">\n {todos?.map((t) => (\n <li\n key={t.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{t.name}</span>\n </li>\n ))}\n </ul>\n <div className=\"flex flex-col gap-2\">\n <input\n type=\"text\"\n value={todo}\n onChange={(e) => setTodo(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n submitTodo()\n }\n }}\n placeholder=\"Enter a new todo...\"\n className=\"w-full px-4 py-3 rounded-lg border border-white/20 bg-white/10 backdrop-blur-sm text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent\"\n />\n <button\n disabled={todo.trim().length === 0}\n onClick={submitTodo}\n className=\"bg-blue-500 hover:bg-blue-600 disabled:bg-blue-500/50 disabled:cursor-not-allowed text-white font-bold py-3 px-4 rounded-lg transition-colors\"\n >\n Add todo\n </button>\n </div>\n </div>\n </div>\n )\n}\n",
16
+ "/src/routes/demo/start.ssr.data-only.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/data-only')({\n ssr: 'data-only',\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-pink-400\">\n Data Only SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
17
+ "/src/routes/demo/start.ssr.full-ssr.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/full-ssr')({\n component: RouteComponent,\n loader: async () => await getPunkSongs(),\n})\n\nfunction RouteComponent() {\n const punkSongs = Route.useLoaderData()\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-purple-400\">\n Full SSR - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
18
+ "/src/routes/demo/start.ssr.index.tsx": "import { createFileRoute, Link } from '@tanstack/react-router'\n\nexport const Route = createFileRoute('/demo/start/ssr/')({\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-900 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-4xl font-bold mb-8 text-center bg-gradient-to-r from-pink-500 via-purple-500 to-green-400 bg-clip-text text-transparent\">\n SSR Demos\n </h1>\n <div className=\"flex flex-col gap-4\">\n <Link\n to=\"/demo/start/ssr/spa-mode\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-pink-600 to-pink-500 hover:from-pink-700 hover:to-pink-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-pink-500/50 border-2 border-pink-400\"\n >\n SPA Mode\n </Link>\n <Link\n to=\"/demo/start/ssr/full-ssr\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-purple-600 to-purple-500 hover:from-purple-700 hover:to-purple-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-purple-500/50 border-2 border-purple-400\"\n >\n Full SSR\n </Link>\n <Link\n to=\"/demo/start/ssr/data-only\"\n className=\"text-2xl font-bold py-6 px-8 rounded-lg bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white text-center shadow-lg transform transition-all hover:scale-105 hover:shadow-green-500/50 border-2 border-green-400\"\n >\n Data Only\n </Link>\n </div>\n </div>\n </div>\n )\n}\n",
19
+ "/src/routes/demo/start.ssr.spa-mode.tsx": "import { useEffect, useState } from 'react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { getPunkSongs } from '@/data/demo.punk-songs'\n\nexport const Route = createFileRoute('/demo/start/ssr/spa-mode')({\n ssr: false,\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const [punkSongs, setPunkSongs] = useState<\n Awaited<ReturnType<typeof getPunkSongs>>\n >([])\n\n useEffect(() => {\n getPunkSongs().then(setPunkSongs)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen bg-gradient-to-br from-zinc-800 to-black p-4 text-white\"\n style={{\n backgroundImage:\n 'radial-gradient(50% 50% at 20% 60%, #1a1a1a 0%, #0a0a0a 50%, #000000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-3xl font-bold mb-6 text-green-400\">\n SPA Mode - Punk Songs\n </h1>\n <ul className=\"space-y-3\">\n {punkSongs.map((song) => (\n <li\n key={song.id}\n className=\"bg-white/10 border border-white/20 rounded-lg p-4 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white font-medium\">\n {song.name}\n </span>\n <span className=\"text-white/60\"> - {song.artist}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
20
+ "/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport {\n Zap,\n Server,\n Route as RouteIcon,\n Shield,\n Waves,\n Sparkles,\n} from 'lucide-react'\n\nexport const Route = createFileRoute('/')({ component: App })\n\nfunction App() {\n const features = [\n {\n icon: <Zap className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Powerful Server Functions',\n description:\n 'Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.',\n },\n {\n icon: <Server className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Flexible Server Side Rendering',\n description:\n 'Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.',\n },\n {\n icon: <RouteIcon className=\"w-12 h-12 text-cyan-400\" />,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: <Shield className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Strongly Typed Everything',\n description:\n 'End-to-end type safety from server to client. Catch errors before they reach production.',\n },\n {\n icon: <Waves className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Full Streaming Support',\n description:\n 'Stream data from server to client progressively. Perfect for AI applications and real-time updates.',\n },\n {\n icon: <Sparkles className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Next Generation Ready',\n description:\n 'Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.',\n },\n ]\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900\">\n <section className=\"relative py-20 px-6 text-center overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10\"></div>\n <div className=\"relative max-w-5xl mx-auto\">\n <div className=\"flex items-center justify-center gap-6 mb-6\">\n <img\n src=\"/tanstack-circle-logo.png\"\n alt=\"TanStack Logo\"\n className=\"w-24 h-24 md:w-32 md:h-32\"\n />\n <h1 className=\"text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]\">\n <span className=\"text-gray-300\">TANSTACK</span>{' '}\n <span className=\"bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent\">\n START\n </span>\n </h1>\n </div>\n <p className=\"text-2xl md:text-3xl text-gray-300 mb-4 font-light\">\n The framework for next generation AI applications\n </p>\n <p className=\"text-lg text-gray-400 max-w-3xl mx-auto mb-8\">\n Full-stack framework powered by TanStack Router for React and Solid.\n Build modern applications with server functions, streaming, and type\n safety.\n </p>\n <div className=\"flex flex-col items-center gap-4\">\n <a\n href=\"https://tanstack.com/start\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50\"\n >\n Documentation\n </a>\n <p className=\"text-gray-400 text-sm mt-2\">\n Begin your TanStack Start journey by editing{' '}\n <code className=\"px-2 py-1 bg-slate-700 rounded text-cyan-400\">\n /src/routes/index.tsx\n </code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"py-16 px-6 max-w-7xl mx-auto\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {features.map((feature, index) => (\n <div\n key={index}\n className=\"bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10\"\n >\n <div className=\"mb-4\">{feature.icon}</div>\n <h3 className=\"text-xl font-semibold text-white mb-3\">\n {feature.title}\n </h3>\n <p className=\"text-gray-400 leading-relaxed\">\n {feature.description}\n </p>\n </div>\n ))}\n </div>\n </section>\n </div>\n )\n}\n",
21
+ "/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
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 start\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
+ "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
+ "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 tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\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
+ },
27
+ "commands": [
28
+ "git init",
29
+ "npm install"
30
+ ]
31
+ }
@@ -7,7 +7,7 @@
7
7
  "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
8
8
  "/src/components/Header.tsx": "import { Link } from '@tanstack/react-router'\n\nimport { useState } from 'react'\nimport {\n ChevronDown,\n ChevronRight,\n Home,\n Menu,\n Network,\n SquareFunction,\n StickyNote,\n X,\n} from 'lucide-react'\n\nexport default function Header() {\n const [isOpen, setIsOpen] = useState(false)\n const [groupedExpanded, setGroupedExpanded] = useState<\n Record<string, boolean>\n >({})\n\n return (\n <>\n <header className=\"p-4 flex items-center bg-gray-800 text-white shadow-lg\">\n <button\n onClick={() => setIsOpen(true)}\n className=\"p-2 hover:bg-gray-700 rounded-lg transition-colors\"\n aria-label=\"Open menu\"\n >\n <Menu size={24} />\n </button>\n <h1 className=\"ml-4 text-xl font-semibold\">\n <Link to=\"/\">\n <img\n src=\"/tanstack-word-logo-white.svg\"\n alt=\"TanStack Logo\"\n className=\"h-10\"\n />\n </Link>\n </h1>\n </header>\n\n <aside\n className={`fixed top-0 left-0 h-full w-80 bg-gray-900 text-white shadow-2xl z-50 transform transition-transform duration-300 ease-in-out flex flex-col ${\n isOpen ? 'translate-x-0' : '-translate-x-full'\n }`}\n >\n <div className=\"flex items-center justify-between p-4 border-b border-gray-700\">\n <h2 className=\"text-xl font-bold\">Navigation</h2>\n <button\n onClick={() => setIsOpen(false)}\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n aria-label=\"Close menu\"\n >\n <X size={24} />\n </button>\n </div>\n\n <nav className=\"flex-1 p-4 overflow-y-auto\">\n <Link\n to=\"/\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <Home size={20} />\n <span className=\"font-medium\">Home</span>\n </Link>\n\n {/* Demo Links Start */}\n\n <Link\n to=\"/demo/start/server-funcs\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <SquareFunction size={20} />\n <span className=\"font-medium\">Start - Server Functions</span>\n </Link>\n\n <Link\n to=\"/demo/start/api-request\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <Network size={20} />\n <span className=\"font-medium\">Start - API Request</span>\n </Link>\n\n <div className=\"flex flex-row justify-between\">\n <Link\n to=\"/demo/start/ssr\"\n onClick={() => setIsOpen(false)}\n className=\"flex-1 flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex-1 flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Start - SSR Demos</span>\n </Link>\n <button\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n onClick={() =>\n setGroupedExpanded((prev) => ({\n ...prev,\n StartSSRDemo: !prev.StartSSRDemo,\n }))\n }\n >\n {groupedExpanded.StartSSRDemo ? (\n <ChevronDown size={20} />\n ) : (\n <ChevronRight size={20} />\n )}\n </button>\n </div>\n {groupedExpanded.StartSSRDemo && (\n <div className=\"flex flex-col ml-4\">\n <Link\n to=\"/demo/start/ssr/spa-mode\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">SPA Mode</span>\n </Link>\n\n <Link\n to=\"/demo/start/ssr/full-ssr\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Full SSR</span>\n </Link>\n\n <Link\n to=\"/demo/start/ssr/data-only\"\n onClick={() => setIsOpen(false)}\n className=\"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2\"\n activeProps={{\n className:\n 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',\n }}\n >\n <StickyNote size={20} />\n <span className=\"font-medium\">Data Only</span>\n </Link>\n </div>\n )}\n\n {/* Demo Links End */}\n </nav>\n </aside>\n </>\n )\n}\n",
9
9
  "/src/data/demo.punk-songs.ts": "import { createServerFn } from '@tanstack/react-start'\n\nexport const getPunkSongs = createServerFn({\n method: 'GET',\n}).handler(async () => [\n { id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' },\n { id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' },\n { id: 3, name: 'The Middle', artist: 'Jimmy Eat World' },\n { id: 4, name: 'My Own Worst Enemy', artist: 'Lit' },\n { id: 5, name: 'Fat Lip', artist: 'Sum 41' },\n { id: 6, name: 'All the Small Things', artist: 'blink-182' },\n { id: 7, name: 'Beverly Hills', artist: 'Weezer' },\n])\n",
10
- "/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n const router = createRouter({\n routeTree,\n scrollRestoration: true,\n defaultPreloadStaleTime: 0,\n })\n\n return router\n}\n",
10
+ "/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n const router = createRouter({\n routeTree,\n context: {},\n\n scrollRestoration: true,\n defaultPreloadStaleTime: 0,\n })\n\n return router\n}\n",
11
11
  "/src/routes/__root.tsx": "import { HeadContent, Scripts, 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\nimport appCss from '../styles.css?url'\n\nexport const Route = createRootRoute({\n head: () => ({\n meta: [\n {\n charSet: 'utf-8',\n },\n {\n name: 'viewport',\n content: 'width=device-width, initial-scale=1',\n },\n {\n title: 'TanStack Start Starter',\n },\n ],\n links: [\n {\n rel: 'stylesheet',\n href: appCss,\n },\n ],\n }),\n\n shellComponent: RootDocument,\n})\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Header />\n {children}\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n ]}\n />\n <Scripts />\n </body>\n </html>\n )\n}\n",
12
12
  "/src/routes/demo/api.names.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nexport const Route = createFileRoute('/demo/api/names')({\n server: {\n handlers: {\n GET: () => json(['Alice', 'Bob', 'Charlie']),\n },\n },\n})\n",
13
13
  "/src/routes/demo/start.api-request.tsx": "import { useEffect, useState } from 'react'\n\nimport { createFileRoute } from '@tanstack/react-router'\n\nfunction getNames() {\n return fetch('/demo/api/names').then((res) => res.json() as Promise<string[]>)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState<Array<string>>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n <div\n className=\"flex items-center justify-center min-h-screen p-4 text-white\"\n style={{\n backgroundColor: '#000',\n backgroundImage:\n 'radial-gradient(ellipse 60% 60% at 0% 100%, #444 0%, #222 60%, #000 100%)',\n }}\n >\n <div className=\"w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10\">\n <h1 className=\"text-2xl mb-4\">Start API Request Demo - Names List</h1>\n <ul className=\"mb-4 space-y-2\">\n {names.map((name) => (\n <li\n key={name}\n className=\"bg-white/10 border border-white/20 rounded-lg p-3 backdrop-blur-sm shadow-md\"\n >\n <span className=\"text-lg text-white\">{name}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n )\n}\n",
@@ -19,7 +19,7 @@
19
19
  "/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport {\n Zap,\n Server,\n Route as RouteIcon,\n Shield,\n Waves,\n Sparkles,\n} from 'lucide-react'\n\nexport const Route = createFileRoute('/')({ component: App })\n\nfunction App() {\n const features = [\n {\n icon: <Zap className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Powerful Server Functions',\n description:\n 'Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.',\n },\n {\n icon: <Server className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Flexible Server Side Rendering',\n description:\n 'Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.',\n },\n {\n icon: <RouteIcon className=\"w-12 h-12 text-cyan-400\" />,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: <Shield className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Strongly Typed Everything',\n description:\n 'End-to-end type safety from server to client. Catch errors before they reach production.',\n },\n {\n icon: <Waves className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Full Streaming Support',\n description:\n 'Stream data from server to client progressively. Perfect for AI applications and real-time updates.',\n },\n {\n icon: <Sparkles className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Next Generation Ready',\n description:\n 'Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.',\n },\n ]\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900\">\n <section className=\"relative py-20 px-6 text-center overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10\"></div>\n <div className=\"relative max-w-5xl mx-auto\">\n <div className=\"flex items-center justify-center gap-6 mb-6\">\n <img\n src=\"/tanstack-circle-logo.png\"\n alt=\"TanStack Logo\"\n className=\"w-24 h-24 md:w-32 md:h-32\"\n />\n <h1 className=\"text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]\">\n <span className=\"text-gray-300\">TANSTACK</span>{' '}\n <span className=\"bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent\">\n START\n </span>\n </h1>\n </div>\n <p className=\"text-2xl md:text-3xl text-gray-300 mb-4 font-light\">\n The framework for next generation AI applications\n </p>\n <p className=\"text-lg text-gray-400 max-w-3xl mx-auto mb-8\">\n Full-stack framework powered by TanStack Router for React and Solid.\n Build modern applications with server functions, streaming, and type\n safety.\n </p>\n <div className=\"flex flex-col items-center gap-4\">\n <a\n href=\"https://tanstack.com/start\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50\"\n >\n Documentation\n </a>\n <p className=\"text-gray-400 text-sm mt-2\">\n Begin your TanStack Start journey by editing{' '}\n <code className=\"px-2 py-1 bg-slate-700 rounded text-cyan-400\">\n /src/routes/index.tsx\n </code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"py-16 px-6 max-w-7xl mx-auto\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {features.map((feature, index) => (\n <div\n key={index}\n className=\"bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10\"\n >\n <div className=\"mb-4\">{feature.icon}</div>\n <h3 className=\"text-xl font-semibold text-white mb-3\">\n {feature.title}\n </h3>\n <p className=\"text-gray-400 leading-relaxed\">\n {feature.description}\n </p>\n </div>\n ))}\n </div>\n </section>\n </div>\n )\n}\n",
20
20
  "/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
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 start\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
- "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.544.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\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}",
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
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 tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\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
  },
@@ -9,7 +9,7 @@
9
9
  "/src/data/demo.punk-songs.ts": "import { createServerFn } from '@tanstack/react-start'\n\nexport const getPunkSongs = createServerFn({\n method: 'GET',\n}).handler(async () => [\n { id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' },\n { id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' },\n { id: 3, name: 'The Middle', artist: 'Jimmy Eat World' },\n { id: 4, name: 'My Own Worst Enemy', artist: 'Lit' },\n { id: 5, name: 'Fat Lip', artist: 'Sum 41' },\n { id: 6, name: 'All the Small Things', artist: 'blink-182' },\n { id: 7, name: 'Beverly Hills', artist: 'Weezer' },\n])\n",
10
10
  "/src/integrations/tanstack-query/devtools.tsx": "import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'\n\nexport default {\n name: 'Tanstack Query',\n render: <ReactQueryDevtoolsPanel />,\n}\n",
11
11
  "/src/integrations/tanstack-query/root-provider.tsx": "import { QueryClient, QueryClientProvider } from '@tanstack/react-query'\n\nexport function getContext() {\n const queryClient = new QueryClient()\n return {\n queryClient,\n }\n}\n\nexport function Provider({\n children,\n queryClient,\n}: {\n children: React.ReactNode\n queryClient: QueryClient\n}) {\n return (\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n )\n}\n",
12
- "/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\nimport { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'\nimport * as TanstackQuery from './integrations/tanstack-query/root-provider'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n const rqContext = TanstackQuery.getContext()\n\n const router = createRouter({\n routeTree,\n context: { ...rqContext },\n defaultPreload: 'intent',\n })\n\n setupRouterSsrQueryIntegration({ router, queryClient: rqContext.queryClient })\n\n return router\n}\n",
12
+ "/src/router.tsx": "import { createRouter } from '@tanstack/react-router'\nimport { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'\nimport * as TanstackQuery from './integrations/tanstack-query/root-provider'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\n// Create a new router instance\nexport const getRouter = () => {\n const rqContext = TanstackQuery.getContext()\n\n const router = createRouter({\n routeTree,\n context: {\n ...rqContext,\n },\n\n defaultPreload: 'intent',\n })\n\n setupRouterSsrQueryIntegration({ router, queryClient: rqContext.queryClient })\n\n return router\n}\n",
13
13
  "/src/routes/__root.tsx": "import {\n HeadContent,\n Scripts,\n createRootRouteWithContext,\n} from '@tanstack/react-router'\nimport { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'\nimport { TanStackDevtools } from '@tanstack/react-devtools'\n\nimport Header from '../components/Header'\n\nimport TanStackQueryDevtools from '../integrations/tanstack-query/devtools'\n\nimport appCss from '../styles.css?url'\n\nimport type { QueryClient } from '@tanstack/react-query'\n\ninterface MyRouterContext {\n queryClient: QueryClient\n}\n\nexport const Route = createRootRouteWithContext<MyRouterContext>()({\n head: () => ({\n meta: [\n {\n charSet: 'utf-8',\n },\n {\n name: 'viewport',\n content: 'width=device-width, initial-scale=1',\n },\n {\n title: 'TanStack Start Starter',\n },\n ],\n links: [\n {\n rel: 'stylesheet',\n href: appCss,\n },\n ],\n }),\n\n shellComponent: RootDocument,\n})\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\">\n <head>\n <HeadContent />\n </head>\n <body>\n <Header />\n {children}\n <TanStackDevtools\n config={{\n position: 'bottom-right',\n }}\n plugins={[\n {\n name: 'Tanstack Router',\n render: <TanStackRouterDevtoolsPanel />,\n },\n TanStackQueryDevtools,\n ]}\n />\n <Scripts />\n </body>\n </html>\n )\n}\n",
14
14
  "/src/routes/demo/api.names.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nexport const Route = createFileRoute('/demo/api/names')({\n server: {\n handlers: {\n GET: () => json(['Alice', 'Bob', 'Charlie']),\n },\n },\n})\n",
15
15
  "/src/routes/demo/api.tq-todos.ts": "import { createFileRoute } from '@tanstack/react-router'\n\nconst todos = [\n {\n id: 1,\n name: 'Buy groceries',\n },\n {\n id: 2,\n name: 'Buy mobile phone',\n },\n {\n id: 3,\n name: 'Buy laptop',\n },\n]\n\nexport const Route = createFileRoute('/demo/api/tq-todos')({\n server: {\n handlers: {\n GET: () => {\n return Response.json(todos)\n },\n POST: async ({ request }) => {\n const name = await request.json()\n const todo = {\n id: todos.length + 1,\n name,\n }\n todos.push(todo)\n return Response.json(todo)\n },\n },\n },\n})\n",
@@ -23,7 +23,7 @@
23
23
  "/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/react-router'\nimport {\n Zap,\n Server,\n Route as RouteIcon,\n Shield,\n Waves,\n Sparkles,\n} from 'lucide-react'\n\nexport const Route = createFileRoute('/')({ component: App })\n\nfunction App() {\n const features = [\n {\n icon: <Zap className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Powerful Server Functions',\n description:\n 'Write server-side code that seamlessly integrates with your client components. Type-safe, secure, and simple.',\n },\n {\n icon: <Server className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Flexible Server Side Rendering',\n description:\n 'Full-document SSR, streaming, and progressive enhancement out of the box. Control exactly what renders where.',\n },\n {\n icon: <RouteIcon className=\"w-12 h-12 text-cyan-400\" />,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: <Shield className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Strongly Typed Everything',\n description:\n 'End-to-end type safety from server to client. Catch errors before they reach production.',\n },\n {\n icon: <Waves className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Full Streaming Support',\n description:\n 'Stream data from server to client progressively. Perfect for AI applications and real-time updates.',\n },\n {\n icon: <Sparkles className=\"w-12 h-12 text-cyan-400\" />,\n title: 'Next Generation Ready',\n description:\n 'Built from the ground up for modern web applications. Deploy anywhere JavaScript runs.',\n },\n ]\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900\">\n <section className=\"relative py-20 px-6 text-center overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10\"></div>\n <div className=\"relative max-w-5xl mx-auto\">\n <div className=\"flex items-center justify-center gap-6 mb-6\">\n <img\n src=\"/tanstack-circle-logo.png\"\n alt=\"TanStack Logo\"\n className=\"w-24 h-24 md:w-32 md:h-32\"\n />\n <h1 className=\"text-6xl md:text-7xl font-black text-white [letter-spacing:-0.08em]\">\n <span className=\"text-gray-300\">TANSTACK</span>{' '}\n <span className=\"bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent\">\n START\n </span>\n </h1>\n </div>\n <p className=\"text-2xl md:text-3xl text-gray-300 mb-4 font-light\">\n The framework for next generation AI applications\n </p>\n <p className=\"text-lg text-gray-400 max-w-3xl mx-auto mb-8\">\n Full-stack framework powered by TanStack Router for React and Solid.\n Build modern applications with server functions, streaming, and type\n safety.\n </p>\n <div className=\"flex flex-col items-center gap-4\">\n <a\n href=\"https://tanstack.com/start\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"px-8 py-3 bg-cyan-500 hover:bg-cyan-600 text-white font-semibold rounded-lg transition-colors shadow-lg shadow-cyan-500/50\"\n >\n Documentation\n </a>\n <p className=\"text-gray-400 text-sm mt-2\">\n Begin your TanStack Start journey by editing{' '}\n <code className=\"px-2 py-1 bg-slate-700 rounded text-cyan-400\">\n /src/routes/index.tsx\n </code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"py-16 px-6 max-w-7xl mx-auto\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {features.map((feature, index) => (\n <div\n key={index}\n className=\"bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-xl p-6 hover:border-cyan-500/50 transition-all duration-300 hover:shadow-lg hover:shadow-cyan-500/10\"\n >\n <div className=\"mb-4\">{feature.icon}</div>\n <h3 className=\"text-xl font-semibold text-white mb-3\">\n {feature.title}\n </h3>\n <p className=\"text-gray-400 leading-relaxed\">\n {feature.description}\n </p>\n </div>\n ))}\n </div>\n </section>\n </div>\n )\n}\n",
24
24
  "/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
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 start\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
- "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.544.0\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tailwindcss\": \"^4.0.6\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\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}",
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
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 tailwindcss from '@tailwindcss/vite'\n\nconst config = defineConfig({\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
  },
@@ -1,72 +0,0 @@
1
- import { createFileRoute } from '@tanstack/react-router'
2
- import { chat, maxIterations, toStreamResponse } from '@tanstack/ai'
3
- import { anthropic } from '@tanstack/ai-anthropic'
4
-
5
- import { getGuitars, recommendGuitarToolDef } from '@/lib/example.guitar-tools'
6
-
7
- const SYSTEM_PROMPT = `You are a helpful assistant for a store that sells guitars.
8
-
9
- CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THIS EXACT WORKFLOW:
10
-
11
- When a user asks for a guitar recommendation:
12
- 1. FIRST: Use the getGuitars tool (no parameters needed)
13
- 2. SECOND: Use the recommendGuitar tool with the ID of the guitar you want to recommend
14
- 3. NEVER write a recommendation directly - ALWAYS use the recommendGuitar tool
15
-
16
- IMPORTANT:
17
- - The recommendGuitar tool will display the guitar in a special, appealing format
18
- - You MUST use recommendGuitar for ANY guitar recommendation
19
- - ONLY recommend guitars from our inventory (use getGuitars first)
20
- - The recommendGuitar tool has a buy button - this is how customers purchase
21
- - Do NOT describe the guitar yourself - let the recommendGuitar tool do it
22
- `
23
-
24
- export const Route = createFileRoute('/demo/api/tanchat')({
25
- server: {
26
- handlers: {
27
- POST: async ({ request }) => {
28
- // Capture request signal before reading body (it may be aborted after body is consumed)
29
- const requestSignal = request.signal
30
-
31
- // If request is already aborted, return early
32
- if (requestSignal.aborted) {
33
- return new Response(null, { status: 499 }) // 499 = Client Closed Request
34
- }
35
-
36
- const abortController = new AbortController()
37
-
38
- try {
39
- const { messages } = await request.json()
40
-
41
- const stream = chat({
42
- adapter: anthropic(),
43
- model: 'claude-haiku-4-5',
44
- tools: [
45
- getGuitars, // Server tool
46
- recommendGuitarToolDef, // No server execute - client will handle
47
- ],
48
- systemPrompts: [SYSTEM_PROMPT],
49
- agentLoopStrategy: maxIterations(5),
50
- messages,
51
- abortController,
52
- })
53
-
54
- return toStreamResponse(stream, { abortController })
55
- } catch (error: any) {
56
- console.error('Chat API error:', error)
57
- // If request was aborted, return early (don't send error response)
58
- if (error.name === 'AbortError' || abortController.signal.aborted) {
59
- return new Response(null, { status: 499 }) // 499 = Client Closed Request
60
- }
61
- return new Response(
62
- JSON.stringify({ error: 'Failed to process chat request' }),
63
- {
64
- status: 500,
65
- headers: { 'Content-Type': 'application/json' },
66
- },
67
- )
68
- }
69
- },
70
- },
71
- },
72
- })