# apps/web-tanstack -- TanStack Start Reference App ## Purpose TanStack Start reference application using TanStack Router with file-based routing. Demonstrates how to consume `@repo/api-client` for tRPC data fetching and `@repo/ui` for components. Like `apps/web-next`, this is a thin app -- business logic lives in `@repo/core`, UI components live in `@repo/ui`. ## Port: 3002 ```bash pnpm dev --filter @repo/web-tanstack # http://localhost:3002 ``` ## Key Files | File | Purpose | |---|---| | `src/routes/__root.tsx` | Root layout -- creates the root route, wraps with `` and `` | | `src/routes/index.tsx` | Home page route (`/`) | ## File-Based Routing TanStack Router uses file-based routing where file paths in `src/routes/` map directly to URL paths: | File | URL | Description | |---|---|---| | `src/routes/__root.tsx` | (all routes) | Root layout, wraps all child routes | | `src/routes/index.tsx` | `/` | Home page | | `src/routes/about.tsx` | `/about` | Static page | | `src/routes/articles/index.tsx` | `/articles` | Article listing | | `src/routes/articles/$id.tsx` | `/articles/:id` | Single article (dynamic param) | ### Naming conventions: - `__root.tsx` -- special root layout file, always wraps all routes - `index.tsx` -- index route for its directory (e.g., `/articles/index.tsx` matches `/articles`) - `$paramName.tsx` -- dynamic route segment (e.g., `$id.tsx` captures `:id`) - Nested folders create nested URL segments ## Provider Setup The `` wraps the entire app in `__root.tsx`: ```tsx // src/routes/__root.tsx import { Outlet, createRootRoute } from "@tanstack/react-router"; import { ApiProvider } from "@repo/api-client"; export const Route = createRootRoute({ component: () => ( ), }); ``` Note: The `trpcUrl` points to the Next.js app's tRPC endpoint at `http://localhost:3000/api/trpc`. In production, this should be configured via environment variables. ## Recipe: Adding a New Route with Data Fetching This example adds an `/articles` route that lists published articles. ### Step 1: Create the route file Create `src/routes/articles/index.tsx`: ```tsx import { createFileRoute } from "@tanstack/react-router"; import { useTRPC } from "@repo/api-client"; import { useQuery } from "@tanstack/react-query"; import { Button } from "@repo/ui"; export const Route = createFileRoute("/articles/")({ component: ArticlesPage, }); function ArticlesPage() { const trpc = useTRPC(); const { data, isLoading, error } = useQuery( trpc.content.listArticles.queryOptions({ status: "published", limit: 20 }) ); if (isLoading) return

Loading articles...

; if (error) return

Error: {error.message}

; return (

Articles

    {data?.map((article) => (
  • {article.title}

  • ))}
); } ``` ### Step 2: Add a dynamic route for individual articles Create `src/routes/articles/$id.tsx`: ```tsx import { createFileRoute } from "@tanstack/react-router"; import { useTRPC } from "@repo/api-client"; import { useQuery } from "@tanstack/react-query"; export const Route = createFileRoute("/articles/$id")({ component: ArticlePage, }); function ArticlePage() { const { id } = Route.useParams(); const trpc = useTRPC(); // Use the article ID from the URL parameter // (Assuming a getArticle procedure exists on the content router) const { data, isLoading } = useQuery( trpc.content.listArticles.queryOptions({ limit: 1 }) ); if (isLoading) return

Loading...

; return (

Article {id}

); } ``` Key patterns: - Every route file exports a `Route` created via `createFileRoute(path)(...)` - The `component` property defines the React component for that route - Use `Route.useParams()` to access dynamic parameters (e.g., `$id`) - Data fetching uses the same `useTRPC()` + `useQuery()` pattern as Next.js - Import UI components from `@repo/ui`, never recreate them locally ## Dependencies | Dependency | Purpose | |---|---| | `@repo/api` | `AppRouter` type (transitive via `@repo/api-client`) | | `@repo/api-client` | `ApiProvider` + `useTRPC()` for client-side data fetching | | `@repo/ui` | Shared UI components | | `@tanstack/react-router` | TanStack Router for file-based routing | | `react` / `react-dom` | React 19 runtime | ## Cross-References - **tRPC routers:** `packages/api/` -- see `packages/api/AGENTS.md` - **tRPC client/hooks:** `packages/api-client/` -- see `packages/api-client/AGENTS.md` - **UI components:** `packages/ui/` -- see `packages/ui/AGENTS.md` - **Next.js app (serves the tRPC endpoint):** `apps/web-next/` -- see `apps/web-next/AGENTS.md`