From 91d8b231394524b35aebcc1aaff8988828466456 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 17 Dec 2025 16:26:36 +0100 Subject: [PATCH 1/4] apollo client add-on --- .../react-cra/add-ons/apollo-client/README.md | 150 ++++++++++++++++++ .../assets/src/routes/demo.apollo-client.tsx | 76 +++++++++ .../react-cra/add-ons/apollo-client/info.json | 19 +++ .../add-ons/apollo-client/package.json | 7 + .../add-ons/apollo-client/small-logo.svg | 11 ++ .../react-cra/add-ons/convex/package.json | 4 +- frameworks/react-cra/add-ons/db/package.json | 2 +- frameworks/react-cra/add-ons/mcp/package.json | 2 +- .../react-cra/add-ons/neon/package.json | 2 +- .../react-cra/add-ons/shadcn/package.json | 2 +- .../add-ons/start/assets/src/router.tsx.ejs | 44 +++-- .../react-cra/add-ons/start/package.json | 4 +- .../react-cra/add-ons/store/package.json | 6 +- .../react-cra/add-ons/storybook/package.json | 4 +- .../project/base/src/routes/__root.tsx.ejs | 20 ++- frameworks/react-cra/src/checksum.ts | 2 +- frameworks/react-cra/tests/react-cra.test.ts | 14 ++ .../cr-ts-start-apollo-client-npm.json | 31 ++++ .../snapshots/react-cra/cr-ts-start-npm.json | 4 +- .../cr-ts-start-tanstack-query-npm.json | 4 +- frameworks/solid/src/checksum.ts | 2 +- 21 files changed, 375 insertions(+), 35 deletions(-) create mode 100644 frameworks/react-cra/add-ons/apollo-client/README.md create mode 100644 frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx create mode 100644 frameworks/react-cra/add-ons/apollo-client/info.json create mode 100644 frameworks/react-cra/add-ons/apollo-client/package.json create mode 100644 frameworks/react-cra/add-ons/apollo-client/small-logo.svg create mode 100644 frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json diff --git a/frameworks/react-cra/add-ons/apollo-client/README.md b/frameworks/react-cra/add-ons/apollo-client/README.md new file mode 100644 index 00000000..07437747 --- /dev/null +++ b/frameworks/react-cra/add-ons/apollo-client/README.md @@ -0,0 +1,150 @@ +# Apollo Client Integration + +This add-on integrates Apollo Client with TanStack Start to provide modern streaming SSR support for GraphQL data fetching. + +## Dependencies + +The following packages are automatically installed: + +- `@apollo/client` - Apollo Client core +- `@apollo/client-integration-tanstack-start` - TanStack Start integration +- `graphql` - GraphQL implementation + +## Configuration + +### 1. GraphQL Endpoint + +Configure your GraphQL API endpoint in `src/router.tsx`: + +```tsx +// Configure Apollo Client +const apolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: new HttpLink({ + uri: 'https://your-graphql-api.example.com/graphql', // Update this! + }), +}) +``` + +You can use environment variables by creating a `.env.local` file: + +```bash +VITE_GRAPHQL_ENDPOINT=https://your-api.com/graphql +``` + +The default configuration already uses this pattern: + +```tsx +uri: import.meta.env.VITE_GRAPHQL_ENDPOINT || + 'https://your-graphql-api.example.com/graphql' +``` + +## Usage Patterns + +### Pattern 1: Loader with preloadQuery (Recommended for SSR) + +Use `preloadQuery` in route loaders for optimal streaming SSR performance: + +```tsx +import { gql, TypedDocumentNode } from '@apollo/client' +import { useReadQuery } from '@apollo/client/react' +import { createFileRoute } from '@tanstack/react-router' + +const MY_QUERY: TypedDocumentNode<{ + posts: { id: string; title: string; content: string }[] +}> = gql` + query GetData { + posts { + id + title + content + } + } +` + +export const Route = createFileRoute('/my-route')({ + component: RouteComponent, + loader: ({ context: { preloadQuery } }) => { + const queryRef = preloadQuery(MY_QUERY, { + variables: {}, + }) + return { queryRef } + }, +}) + +function RouteComponent() { + const { queryRef } = Route.useLoaderData() + const { data } = useReadQuery(queryRef) + + return
{/* render your data */}
+} +``` + +### Pattern 2: useSuspenseQuery + +Use `useSuspenseQuery` directly in components with automatic suspense support: + +```tsx +import { gql, TypedDocumentNode } from '@apollo/client' +import { useSuspenseQuery } from '@apollo/client/react' +import { createFileRoute } from '@tanstack/react-router' + +const MY_QUERY: TypedDocumentNode<{ + posts: { id: string; title: string }[] +}> = gql` + query GetData { + posts { + id + title + } + } +` + +export const Route = createFileRoute('/my-route')({ + component: RouteComponent, +}) + +function RouteComponent() { + const { data } = useSuspenseQuery(MY_QUERY) + + return
{/* render your data */}
+} +``` + +### Pattern 3: Manual Refetching + +```tsx +import { useQueryRefHandlers, useReadQuery } from '@apollo/client/react' + +function MyComponent() { + const { queryRef } = Route.useLoaderData() + const { refetch } = useQueryRefHandlers(queryRef) + const { data } = useReadQuery(queryRef) + + return ( +
+ + {/* render data */} +
+ ) +} +``` + +## Important Notes + +### SSR Optimization + +The integration automatically handles: + +- Query deduplication across server and client +- Streaming SSR with `@defer` directive support +- Proper cache hydration + +## Learn More + +- [Apollo Client Documentation](https://www.apollographql.com/docs/react) +- [@apollo/client-integration-tanstack-start](https://www.npmjs.com/package/@apollo/client-integration-tanstack-start) + +## Demo + +Visit `/demo/apollo-client` in your application to see a working example of Apollo Client integration. diff --git a/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx b/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx new file mode 100644 index 00000000..9f7d6699 --- /dev/null +++ b/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx @@ -0,0 +1,76 @@ +import { gql, TypedDocumentNode } from '@apollo/client' +import { useReadQuery } from '@apollo/client/react' +import { createFileRoute } from '@tanstack/react-router' +import React from 'react' + +// Example GraphQL query - replace with your own schema +const EXAMPLE_QUERY: TypedDocumentNode<{ + posts: { id: string; title: string; content: string } +}> = gql` + query ExampleQuery { + posts { + id + title + content + } + } +` + +export const Route = createFileRoute('/demo/apollo-client')({ + component: RouteComponent, + loader: ({ context: { preloadQuery } }) => { + // Preload the query in the loader for optimal performance + const queryRef = preloadQuery(EXAMPLE_QUERY, { + variables: {}, + }) + return { + queryRef, + } + }, +}) + +function RouteComponent() { + const { queryRef } = Route.useLoaderData() + const { data } = useReadQuery(queryRef) + + return ( +
+

Apollo Client Demo

+
+

Apollo Client is configured!

+

+ This demo uses{' '} + preloadQuery in the + loader and{' '} + useReadQuery in the + component for optimal streaming SSR performance. +

+
+
+

Query Result:

+
+          {JSON.stringify(data, null, 2)}
+        
+
+
+

📝 Next steps:

+
    +
  • + Configure your GraphQL endpoint in{' '} + src/router.tsx +
  • +
  • Replace the example query with your actual GraphQL schema
  • +
  • + Learn more:{' '} + + Apollo Client Docs + +
  • +
+
+
+ ) +} diff --git a/frameworks/react-cra/add-ons/apollo-client/info.json b/frameworks/react-cra/add-ons/apollo-client/info.json new file mode 100644 index 00000000..13f067e7 --- /dev/null +++ b/frameworks/react-cra/add-ons/apollo-client/info.json @@ -0,0 +1,19 @@ +{ + "name": "Apollo Client", + "description": "Integrate Apollo Client with streaming SSR support for GraphQL data fetching.", + "phase": "add-on", + "modes": ["file-router"], + "type": "add-on", + "priority": 15, + "link": "https://github.com/apollographql/apollo-client-integrations/tree/main/packages/tanstack-start", + "dependsOn": ["start"], + "routes": [ + { + "icon": "Network", + "url": "/demo/apollo-client", + "name": "Apollo Client", + "path": "src/routes/demo.apollo-client.tsx", + "jsName": "ApolloClientDemo" + } + ] +} diff --git a/frameworks/react-cra/add-ons/apollo-client/package.json b/frameworks/react-cra/add-ons/apollo-client/package.json new file mode 100644 index 00000000..91c27fa7 --- /dev/null +++ b/frameworks/react-cra/add-ons/apollo-client/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "@apollo/client": "^4.0.0", + "@apollo/client-integration-tanstack-start": "^0.14.2-rc.0", + "graphql": "^16.10.0" + } +} diff --git a/frameworks/react-cra/add-ons/apollo-client/small-logo.svg b/frameworks/react-cra/add-ons/apollo-client/small-logo.svg new file mode 100644 index 00000000..189dafbe --- /dev/null +++ b/frameworks/react-cra/add-ons/apollo-client/small-logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/frameworks/react-cra/add-ons/convex/package.json b/frameworks/react-cra/add-ons/convex/package.json index 32e48ff7..a354f21b 100644 --- a/frameworks/react-cra/add-ons/convex/package.json +++ b/frameworks/react-cra/add-ons/convex/package.json @@ -1,7 +1,7 @@ { "dependencies": { - "@convex-dev/react-query": "0.0.0-alpha.11", + "@convex-dev/react-query": "0.1.0", "convex": "^1.27.3", - "lucide-react": "^0.544.0" + "lucide-react": "^0.561.0" } } diff --git a/frameworks/react-cra/add-ons/db/package.json b/frameworks/react-cra/add-ons/db/package.json index 2c72d199..f731a710 100644 --- a/frameworks/react-cra/add-ons/db/package.json +++ b/frameworks/react-cra/add-ons/db/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@tanstack/query-db-collection": "^0.2.0", + "@tanstack/query-db-collection": "^1.0.8", "@tanstack/react-db": "^0.1.1", "zod": "^4.0.14" } diff --git a/frameworks/react-cra/add-ons/mcp/package.json b/frameworks/react-cra/add-ons/mcp/package.json index bbd4a56a..9c190efa 100644 --- a/frameworks/react-cra/add-ons/mcp/package.json +++ b/frameworks/react-cra/add-ons/mcp/package.json @@ -1,6 +1,6 @@ { "dependencies": { "@modelcontextprotocol/sdk": "^1.17.0", - "zod": "4.1.11" + "zod": "4.2.1" } } diff --git a/frameworks/react-cra/add-ons/neon/package.json b/frameworks/react-cra/add-ons/neon/package.json index 517cee90..9b43203e 100644 --- a/frameworks/react-cra/add-ons/neon/package.json +++ b/frameworks/react-cra/add-ons/neon/package.json @@ -1,6 +1,6 @@ { "dependencies": { "@neondatabase/serverless": "^1.0.0", - "@neondatabase/vite-plugin-postgres": "^0.2.0" + "@neondatabase/vite-plugin-postgres": "^0.5.0" } } diff --git a/frameworks/react-cra/add-ons/shadcn/package.json b/frameworks/react-cra/add-ons/shadcn/package.json index 24d19a15..f5d922cd 100644 --- a/frameworks/react-cra/add-ons/shadcn/package.json +++ b/frameworks/react-cra/add-ons/shadcn/package.json @@ -2,7 +2,7 @@ "dependencies": { "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.544.0", + "lucide-react": "^0.561.0", "tailwind-merge": "^3.0.2", "tw-animate-css": "^1.3.6" } diff --git a/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs b/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs index de5ba674..ac930bd6 100644 --- a/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs +++ b/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs @@ -1,6 +1,13 @@ import { createRouter } from '@tanstack/react-router'<% if (addOnEnabled['tanstack-query']) { %> import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' import * as TanstackQuery from "./integrations/tanstack-query/root-provider"; +<% } %><% if (addOnEnabled['apollo-client']) { %> +import { + routerWithApolloClient, + ApolloClient, + InMemoryCache, +} from "@apollo/client-integration-tanstack-start"; +import { HttpLink } from "@apollo/client"; <% } %> <% if (addOnEnabled.sentry) { %> import * as Sentry from "@sentry/tanstackstart-react"; @@ -11,22 +18,39 @@ import { routeTree } from './routeTree.gen' // Create a new router instance export const getRouter = () => { +<% if (addOnEnabled['apollo-client']) { %> + // Configure Apollo Client + const apolloClient = new ApolloClient({ + cache: new InMemoryCache(), + link: new HttpLink({ + uri: import.meta.env.VITE_GRAPHQL_ENDPOINT || "https://your-graphql-api.example.com/graphql" + }), + }); +<% } %> <% if (addOnEnabled['tanstack-query']) { %> - const rqContext = TanstackQuery.getContext(); - - const router = createRouter({ - routeTree, - context: { ...rqContext }, - defaultPreload: "intent", - }) + const rqContext = TanstackQuery.getContext(); +<% } %> - setupRouterSsrQueryIntegration({router, queryClient: rqContext.queryClient}) -<% } else { %> const router = createRouter({ routeTree, + context: { +<% if (addOnEnabled['apollo-client']) { %> + ...routerWithApolloClient.defaultContext, +<% } %> +<% if (addOnEnabled['tanstack-query']) { %> + ...rqContext, +<% } %> + }, +<% if (addOnEnabled['tanstack-query'] || addOnEnabled['apollo-client']) { %> + defaultPreload: "intent", +<% } else { %> scrollRestoration: true, defaultPreloadStaleTime: 0, +<% } %> }) + +<% if (addOnEnabled['tanstack-query']) { %> + setupRouterSsrQueryIntegration({router, queryClient: rqContext.queryClient}) <% } %> <% if (addOnEnabled.sentry) { %> @@ -40,5 +64,5 @@ export const getRouter = () => { } <% } %> - return router; + return <% if (addOnEnabled['apollo-client']) { %>routerWithApolloClient(router, apolloClient)<% } else { %>router<% } %>; } diff --git a/frameworks/react-cra/add-ons/start/package.json b/frameworks/react-cra/add-ons/start/package.json index 73291fd7..ea89241c 100644 --- a/frameworks/react-cra/add-ons/start/package.json +++ b/frameworks/react-cra/add-ons/start/package.json @@ -6,7 +6,7 @@ "dependencies": { "@tanstack/react-router-ssr-query": "^1.131.7", "@tanstack/react-start": "^1.132.0", - "vite-tsconfig-paths": "^5.1.4", - "lucide-react": "^0.544.0" + "vite-tsconfig-paths": "^6.0.2", + "lucide-react": "^0.561.0" } } diff --git a/frameworks/react-cra/add-ons/store/package.json b/frameworks/react-cra/add-ons/store/package.json index da680558..417e063b 100644 --- a/frameworks/react-cra/add-ons/store/package.json +++ b/frameworks/react-cra/add-ons/store/package.json @@ -1,9 +1,9 @@ { "dependencies": { - "@tanstack/store": "^0.7.0", - "@tanstack/react-store": "^0.7.0" + "@tanstack/store": "^0.8.0", + "@tanstack/react-store": "^0.8.0" }, "devDependencies": { - "@tanstack/devtools-event-client": "^0.3.2" + "@tanstack/devtools-event-client": "^0.4.0" } } diff --git a/frameworks/react-cra/add-ons/storybook/package.json b/frameworks/react-cra/add-ons/storybook/package.json index 78959fdc..57aba90e 100644 --- a/frameworks/react-cra/add-ons/storybook/package.json +++ b/frameworks/react-cra/add-ons/storybook/package.json @@ -4,7 +4,7 @@ "build-storybook": "storybook build" }, "dependencies": { - "@storybook/react-vite": "^9.1.9", - "storybook": "^9.1.9" + "@storybook/react-vite": "^10.1.10", + "storybook": "^10.1.10" } } diff --git a/frameworks/react-cra/project/base/src/routes/__root.tsx.ejs b/frameworks/react-cra/project/base/src/routes/__root.tsx.ejs index 97f5922d..01a5e108 100644 --- a/frameworks/react-cra/project/base/src/routes/__root.tsx.ejs +++ b/frameworks/react-cra/project/base/src/routes/__root.tsx.ejs @@ -1,5 +1,6 @@ +<% let hasContext = addOnEnabled["apollo-client"] || addOnEnabled["tanstack-query"]; %> <% if (!fileRouter) { ignoreFile() } %>import { <% if (addOnEnabled.start) { %> - HeadContent<% } else { %>Outlet<% } %><% if (addOnEnabled.start) { %>, Scripts<% } %>, <% if (addOnEnabled["tanstack-query"]) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %> } from '@tanstack/react-router' + HeadContent<% } else { %>Outlet<% } %><% if (addOnEnabled.start) { %>, Scripts<% } %>, <% if (hasContext) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %> } from '@tanstack/react-router' import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; import { TanStackDevtools } from '@tanstack/react-devtools' <% if (addOns.length) { %> @@ -9,21 +10,28 @@ import <%= integration.jsName %> from '<%= relativePath(integration.path, true) <% } %> <% if (addOnEnabled.start) { %> import appCss from '../styles.css?url' -<% } %><% if (addOnEnabled["tanstack-query"]) { %> +<% } %> +<% if (addOnEnabled["apollo-client"]) { %> +import type { ApolloClientIntegration } from "@apollo/client-integration-tanstack-start"; +<% } %> +<% if (addOnEnabled["tanstack-query"]) { %> import type { QueryClient } from '@tanstack/react-query' <% if (addOnEnabled.tRPC) { %> import type { TRPCRouter } from '@/integrations/trpc/router' import type { TRPCOptionsProxy } from '@trpc/tanstack-react-query' <% } %> - -interface MyRouterContext { +<% } %> +<% if (hasContext) { %> +interface MyRouterContext <% if (addOnEnabled["apollo-client"]) {%> extends ApolloClientIntegration.RouterContext <%} %>{ +<% if (addOnEnabled["tanstack-query"]) { %> queryClient: QueryClient <% if (addOnEnabled.tRPC) { %> trpc: TRPCOptionsProxy <% } %> +<% } %> }<% } %> - -export const Route = <% if (addOnEnabled["tanstack-query"]) { %>createRootRouteWithContext()<% } else { %>createRootRoute<% } %>({ + +export const Route = <% if (hasContext) { %>createRootRouteWithContext()<% } else { %>createRootRoute<% } %>({ <% if (addOnEnabled.start) { %> head: () => ({ meta: [ diff --git a/frameworks/react-cra/src/checksum.ts b/frameworks/react-cra/src/checksum.ts index d8731b0a..204535f7 100644 --- a/frameworks/react-cra/src/checksum.ts +++ b/frameworks/react-cra/src/checksum.ts @@ -1,3 +1,3 @@ // This file is auto-generated. Do not edit manually. // Generated from add-ons, examples, hosts, project, and toolchains directories -export const contentChecksum = '91ab333689da4a55dac5572c70c66bf3cf8710caf4fe62ee5fd63d7fa924f8a2' +export const contentChecksum = '7ff3bc787de00e4714763406a620a93924317e403cd00fea192c57f61d7f4e25' diff --git a/frameworks/react-cra/tests/react-cra.test.ts b/frameworks/react-cra/tests/react-cra.test.ts index f9b14341..d9d6ff06 100644 --- a/frameworks/react-cra/tests/react-cra.test.ts +++ b/frameworks/react-cra/tests/react-cra.test.ts @@ -148,3 +148,17 @@ test('file router with add-on start on npm', async () => { './snapshots/react-cra/cr-ts-start-tanstack-query-npm.json', ) }) + +test('file router with add-on start and apollo-client on npm', async () => { + const { environment, output } = createMemoryEnvironment() + const options = { + ...(await createReactOptions(['start', 'apollo-client'])), + tailwind: true, + typescript: true, + } as Options + await createApp(environment, options) + const cleanedOutput = cleanupOutput(options, output) + await expect(JSON.stringify(cleanedOutput, null, 2)).toMatchFileSnapshot( + './snapshots/react-cra/cr-ts-start-apollo-client-npm.json', + ) +}) diff --git a/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json new file mode 100644 index 00000000..692c41de --- /dev/null +++ b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-apollo-client-npm.json @@ -0,0 +1,31 @@ +{ + "files": { + ".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}", + ".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", + "/.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", + "/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", + "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n", + "/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\n >({})\n\n return (\n <>\n
\n setIsOpen(true)}\n className=\"p-2 hover:bg-gray-700 rounded-lg transition-colors\"\n aria-label=\"Open menu\"\n >\n \n \n

\n \n \n \n

\n
\n\n \n
\n

Navigation

\n setIsOpen(false)}\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n aria-label=\"Close menu\"\n >\n \n \n
\n\n \n \n \n )\n}\n", + "/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", + "/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://your-graphql-api.example.com/graphql',\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", + "/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()({\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 \n \n \n \n \n
\n {children}\n ,\n },\n ]}\n />\n \n \n \n )\n}\n", + "/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 posts: { id: string; title: string; content: string }\n}> = gql`\n query ExampleQuery {\n posts {\n id\n title\n content\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
\n

Apollo Client Demo

\n
\n

Apollo Client is configured!

\n

\n This demo uses{' '}\n preloadQuery in the\n loader and{' '}\n useReadQuery in the\n component for optimal streaming SSR performance.\n

\n
\n
\n

Query Result:

\n
\n          {JSON.stringify(data, null, 2)}\n        
\n
\n
\n

📝 Next steps:

\n
    \n
  • \n Configure your GraphQL endpoint in{' '}\n src/router.tsx\n
  • \n
  • Replace the example query with your actual GraphQL schema
  • \n
  • \n Learn more:{' '}\n \n Apollo Client Docs\n \n
  • \n
\n
\n
\n )\n}\n", + "/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", + "/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)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n \n
\n

Start API Request Demo - Names List

\n
    \n {names.map((name) => (\n \n {name}\n \n ))}\n
\n
\n \n )\n}\n", + "/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 \n
\n

Start Server Functions - Todo Example

\n
    \n {todos?.map((t) => (\n \n {t.name}\n \n ))}\n
\n
\n 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 \n Add todo\n \n
\n
\n \n )\n}\n", + "/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 \n
\n

\n Data Only SSR - Punk Songs\n

\n
    \n {punkSongs.map((song) => (\n \n \n {song.name}\n \n - {song.artist}\n \n ))}\n
\n
\n \n )\n}\n", + "/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 \n
\n

\n Full SSR - Punk Songs\n

\n
    \n {punkSongs.map((song) => (\n \n \n {song.name}\n \n - {song.artist}\n \n ))}\n
\n
\n \n )\n}\n", + "/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 \n
\n

\n SSR Demos\n

\n
\n \n SPA Mode\n \n \n Full SSR\n \n \n Data Only\n \n
\n
\n \n )\n}\n", + "/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>\n >([])\n\n useEffect(() => {\n getPunkSongs().then(setPunkSongs)\n }, [])\n\n return (\n \n
\n

\n SPA Mode - Punk Songs\n

\n
    \n {punkSongs.map((song) => (\n \n \n {song.name}\n \n - {song.artist}\n \n ))}\n
\n
\n \n )\n}\n", + "/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: ,\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: ,\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: ,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: ,\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: ,\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: ,\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
\n
\n
\n
\n
\n \n

\n TANSTACK{' '}\n \n START\n \n

\n
\n

\n The framework for next generation AI applications\n

\n

\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

\n
\n \n Documentation\n \n

\n Begin your TanStack Start journey by editing{' '}\n \n /src/routes/index.tsx\n \n

\n
\n
\n
\n\n
\n
\n {features.map((feature, index) => (\n \n
{feature.icon}
\n

\n {feature.title}\n

\n

\n {feature.description}\n

\n
\n ))}\n
\n \n \n )\n}\n", + "/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", + "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
{/* render your data */}
\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
{/* render your data */}
\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
\n \n {/* render data */}\n
\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\nAbout\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 `` 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
\n \n
\n \n \n \n ),\n})\n```\n\nThe `` 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
    \n {data.results.map((person) => (\n
  • {person.name}
  • \n ))}\n
\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 \n \n \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 \n \n \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
\n
    \n {data.map((person) => (\n
  • {person.name}
  • \n ))}\n
\n
\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
\n \n
\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
\n \n
Doubled - {doubledCount}
\n
\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", + "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 \"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}", + "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", + "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" + }, + "commands": [ + "git init", + "npm install" + ] +} \ No newline at end of file diff --git a/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-npm.json b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-npm.json index 29610ba2..eb78b53e 100644 --- a/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-npm.json +++ b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-npm.json @@ -7,7 +7,7 @@ "/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n", "/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\n >({})\n\n return (\n <>\n
\n setIsOpen(true)}\n className=\"p-2 hover:bg-gray-700 rounded-lg transition-colors\"\n aria-label=\"Open menu\"\n >\n \n \n

\n \n \n \n

\n
\n\n \n
\n

Navigation

\n setIsOpen(false)}\n className=\"p-2 hover:bg-gray-800 rounded-lg transition-colors\"\n aria-label=\"Close menu\"\n >\n \n \n
\n\n \n \n \n )\n}\n", "/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", - "/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", + "/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", "/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 \n \n \n \n \n
\n {children}\n ,\n },\n ]}\n />\n \n \n \n )\n}\n", "/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", "/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)\n}\n\nexport const Route = createFileRoute('/demo/start/api-request')({\n component: Home,\n})\n\nfunction Home() {\n const [names, setNames] = useState>([])\n\n useEffect(() => {\n getNames().then(setNames)\n }, [])\n\n return (\n \n
\n

Start API Request Demo - Names List

\n
    \n {names.map((name) => (\n \n {name}\n \n ))}\n
\n
\n \n )\n}\n", @@ -19,7 +19,7 @@ "/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: ,\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: ,\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: ,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: ,\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: ,\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: ,\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
\n
\n
\n
\n
\n \n

\n TANSTACK{' '}\n \n START\n \n

\n
\n

\n The framework for next generation AI applications\n

\n

\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

\n
\n \n Documentation\n \n

\n Begin your TanStack Start journey by editing{' '}\n \n /src/routes/index.tsx\n \n

\n
\n
\n
\n\n
\n
\n {features.map((feature, index) => (\n \n
{feature.icon}
\n

\n {feature.title}\n

\n

\n {feature.description}\n

\n
\n ))}\n
\n \n \n )\n}\n", "/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", "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\nAbout\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 `` 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
\n \n
\n \n \n \n ),\n})\n```\n\nThe `` 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
    \n {data.results.map((person) => (\n
  • {person.name}
  • \n ))}\n
\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 \n \n \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 \n \n \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
\n
    \n {data.map((person) => (\n
  • {person.name}
  • \n ))}\n
\n
\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
\n \n
\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
\n \n
Doubled - {doubledCount}
\n
\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", - "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}", + "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}", "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", "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" }, diff --git a/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json index 1e40f451..da1da58e 100644 --- a/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json +++ b/frameworks/react-cra/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json @@ -9,7 +9,7 @@ "/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", "/src/integrations/tanstack-query/devtools.tsx": "import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'\n\nexport default {\n name: 'Tanstack Query',\n render: ,\n}\n", "/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 {children}\n )\n}\n", - "/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", + "/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", "/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()({\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 \n \n \n \n \n
\n {children}\n ,\n },\n TanStackQueryDevtools,\n ]}\n />\n \n \n \n )\n}\n", "/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", "/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 @@ "/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: ,\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: ,\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: ,\n title: 'API Routes',\n description:\n 'Build type-safe API endpoints alongside your application. No separate backend needed.',\n },\n {\n icon: ,\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: ,\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: ,\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
\n
\n
\n
\n
\n \n

\n TANSTACK{' '}\n \n START\n \n

\n
\n

\n The framework for next generation AI applications\n

\n

\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

\n
\n \n Documentation\n \n

\n Begin your TanStack Start journey by editing{' '}\n \n /src/routes/index.tsx\n \n

\n
\n
\n
\n\n
\n
\n {features.map((feature, index) => (\n \n
{feature.icon}
\n

\n {feature.title}\n

\n

\n {feature.description}\n

\n
\n ))}\n
\n \n \n )\n}\n", "/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", "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\nAbout\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 `` 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
\n \n
\n \n \n \n ),\n})\n```\n\nThe `` 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
    \n {data.results.map((person) => (\n
  • {person.name}
  • \n ))}\n
\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 \n \n \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 \n \n \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
\n
    \n {data.map((person) => (\n
  • {person.name}
  • \n ))}\n
\n
\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
\n \n
\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
\n \n
Doubled - {doubledCount}
\n
\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", - "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}", + "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}", "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", "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" }, diff --git a/frameworks/solid/src/checksum.ts b/frameworks/solid/src/checksum.ts index bc0f706b..35a4da1b 100644 --- a/frameworks/solid/src/checksum.ts +++ b/frameworks/solid/src/checksum.ts @@ -1,3 +1,3 @@ // This file is auto-generated. Do not edit manually. // Generated from add-ons, examples, hosts, project, and toolchains directories -export const contentChecksum = '97450d3bd15410ec0fb6553e0b2709464dbef2b643f509e73ff124a3230f44c5' +export const contentChecksum = '3e9cf8aa946ca4d59c413689bf5f02d778bcd23c95bc5e04956f47331261dac8' From 5e33769fcffc4ec4390d23cdccdf684689ef4493 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 17 Dec 2025 18:11:15 +0100 Subject: [PATCH 2/4] add rjxs --- frameworks/react-cra/add-ons/apollo-client/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frameworks/react-cra/add-ons/apollo-client/package.json b/frameworks/react-cra/add-ons/apollo-client/package.json index 91c27fa7..b7af8acd 100644 --- a/frameworks/react-cra/add-ons/apollo-client/package.json +++ b/frameworks/react-cra/add-ons/apollo-client/package.json @@ -2,6 +2,7 @@ "dependencies": { "@apollo/client": "^4.0.0", "@apollo/client-integration-tanstack-start": "^0.14.2-rc.0", - "graphql": "^16.10.0" + "graphql": "^16.10.0", + "rxjs": "^7.8.2" } } From c185e1db65c956894f87ddd36214e47797296b47 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 17 Dec 2025 18:11:35 +0100 Subject: [PATCH 3/4] use countries api --- .../assets/src/routes/demo.apollo-client.tsx | 9 ++++----- .../react-cra/add-ons/start/assets/src/router.tsx.ejs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx b/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx index 9f7d6699..c5619dc9 100644 --- a/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +++ b/frameworks/react-cra/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx @@ -5,13 +5,12 @@ import React from 'react' // Example GraphQL query - replace with your own schema const EXAMPLE_QUERY: TypedDocumentNode<{ - posts: { id: string; title: string; content: string } + continents: { __typename: string; code: string; name: string } }> = gql` query ExampleQuery { - posts { - id - title - content + continents { + code + name } } ` diff --git a/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs b/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs index ac930bd6..439b5059 100644 --- a/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs +++ b/frameworks/react-cra/add-ons/start/assets/src/router.tsx.ejs @@ -23,7 +23,7 @@ export const getRouter = () => { const apolloClient = new ApolloClient({ cache: new InMemoryCache(), link: new HttpLink({ - uri: import.meta.env.VITE_GRAPHQL_ENDPOINT || "https://your-graphql-api.example.com/graphql" + uri: import.meta.env.VITE_GRAPHQL_ENDPOINT || "https://countries.trevorblades.com/" }), }); <% } %> From 41695ef378b259b28072a94e5d36277f7cc14f29 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 18 Dec 2025 09:30:53 +0100 Subject: [PATCH 4/4] more checksums --- frameworks/react-cra/src/checksum.ts | 3 +-- frameworks/solid/src/checksum.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frameworks/react-cra/src/checksum.ts b/frameworks/react-cra/src/checksum.ts index c0c3e8c8..d7c6eed5 100644 --- a/frameworks/react-cra/src/checksum.ts +++ b/frameworks/react-cra/src/checksum.ts @@ -1,4 +1,3 @@ // This file is auto-generated. Do not edit manually. // Generated from add-ons, examples, hosts, project, and toolchains directories -export const contentChecksum = - '83cb054c1f9453daea6c56991d1a7db0155526786b85913eab02e678c4399618' +export const contentChecksum = 'a14f458b75f7daf33b73715e62d953e787c8b3ced88040b878eb3c24d6a51504' diff --git a/frameworks/solid/src/checksum.ts b/frameworks/solid/src/checksum.ts index ec340a43..7c050640 100644 --- a/frameworks/solid/src/checksum.ts +++ b/frameworks/solid/src/checksum.ts @@ -1,4 +1,3 @@ // This file is auto-generated. Do not edit manually. // Generated from add-ons, examples, hosts, project, and toolchains directories -export const contentChecksum = - '8d5d5394c68403b640e96cc9d2ee063fb60a2e1e84649644905934cad6226447' +export const contentChecksum = '8d5d5394c68403b640e96cc9d2ee063fb60a2e1e84649644905934cad6226447'