Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ This repository contains the packages, docs and examples for uploadthing
A simple example using the Next.js pages directory
- [SolidStart SSR](https://github.com/pingdotgg/uploadthing/tree/main/examples/minimal-solidstart) -
A simple example using SSR with SolidStart
- [Tanstack Start](https://github.com/pingdotgg/uploadthing/tree/main/examples/minimal-tanstack-start) -
A simple example using Tanstack start
- [Docs Site](https://github.com/pingdotgg/uploadthing/tree/main/docs) - Source
for docs.uploadthing.com
- [React Package](https://github.com/pingdotgg/uploadthing/tree/main/packages/react) -
Expand Down
31 changes: 20 additions & 11 deletions docs/src/app/(docs)/getting-started/tanstack-start/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ UPLOADTHING_TOKEN=... # A token for interacting with the SDK

<Note>
Tanstack Start is currently in beta, this guide works at the time of writing
(`v1.95.0`) but there might be some breaking changes introduced in the
(`v1.158.0`) but there might be some breaking changes introduced in the
framework that we have not kept up to date with.
</Note>

Expand Down Expand Up @@ -106,23 +106,32 @@ export type UploadRouter = typeof uploadRouter;
</Note>

<Warning>
Make sure to configure API entry handler in `app/api.ts`. For more
information, please refer to the [@tanstack/start
docs](https://tanstack.com/router/latest/docs/framework/react/start/api-routes#setting-up-the-entry-handler).
Server routes can be defined in the same directory as app routes,
`/routes/api/uploadthing.ts` will create an api route at `/api/uploadthing`.
For more information, please refer to the [@tanstack/start
docs](https://tanstack.com/start/latest/docs/framework/react/guide/server-routes).
</Warning>

```ts {{ title: "app/routes/api/uploadthing.ts" }}
import { createAPIFileRoute } from "@tanstack/start/api";
import { createFileRoute } from "@tanstack/react-router";

import { createRouteHandler } from "uploadthing/server";

import { uploadRouter } from "../../server/uploadthing";

const handlers = createRouteHandler({ router: uploadRouter });

export const Route = createAPIFileRoute("/api/uploadthing")({
GET: handlers,
POST: handlers,
const handler = createRouteHandler({ router: uploadRouter });

export const Route = createFileRoute("/api/uploadthing")({
server: {
handlers: {
GET: async ({ request }) => {
return handler(request);
},
POST: async ({ request }) => {
return handler(request);
},
},
},
});
```

Expand Down Expand Up @@ -209,7 +218,7 @@ import { createFileRoute } from "@tanstack/react-router";

import { UploadButton } from "../utils/uploadthing";

export const APIRoute = createFileRoute("/")({
export const Route = createFileRoute("/")({
component: Home,
});

Expand Down
8 changes: 5 additions & 3 deletions examples/minimal-tanstack-start/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@tanstack/react-router": "^1.121.27",
"@tanstack/react-start": "^1.121.32",
"@tanstack/react-router": "^1.158.0",
"@tanstack/react-start": "^1.158.0",
"@uploadthing/react": "7.3.3",
"react": "19.2.2",
"react-dom": "19.2.2",
Expand All @@ -19,7 +19,9 @@
"devDependencies": {
"@types/react": "19.2.7",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "^5.1.3",
"typescript": "5.8.3",
"vite": "^6.3.4"
"vite": "^6.3.4",
"vite-tsconfig-paths": "^5.1.4"
}
}
63 changes: 21 additions & 42 deletions examples/minimal-tanstack-start/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,66 +8,45 @@
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.

import { createServerRootRoute } from '@tanstack/react-start/server'

import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './routes/index'
import { ServerRoute as ApiUploadthingServerRouteImport } from './routes/api.uploadthing'

const rootServerRouteImport = createServerRootRoute()
import { Route as ApiUploadthingRouteImport } from './routes/api/uploadthing'

const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const ApiUploadthingServerRoute = ApiUploadthingServerRouteImport.update({
const ApiUploadthingRoute = ApiUploadthingRouteImport.update({
id: '/api/uploadthing',
path: '/api/uploadthing',
getParentRoute: () => rootServerRouteImport,
getParentRoute: () => rootRouteImport,
} as any)

export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/api/uploadthing': typeof ApiUploadthingRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/api/uploadthing': typeof ApiUploadthingRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/api/uploadthing': typeof ApiUploadthingRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/'
fullPaths: '/' | '/api/uploadthing'
fileRoutesByTo: FileRoutesByTo
to: '/'
id: '__root__' | '/'
to: '/' | '/api/uploadthing'
id: '__root__' | '/' | '/api/uploadthing'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
}
export interface FileServerRoutesByFullPath {
'/api/uploadthing': typeof ApiUploadthingServerRoute
}
export interface FileServerRoutesByTo {
'/api/uploadthing': typeof ApiUploadthingServerRoute
}
export interface FileServerRoutesById {
__root__: typeof rootServerRouteImport
'/api/uploadthing': typeof ApiUploadthingServerRoute
}
export interface FileServerRouteTypes {
fileServerRoutesByFullPath: FileServerRoutesByFullPath
fullPaths: '/api/uploadthing'
fileServerRoutesByTo: FileServerRoutesByTo
to: '/api/uploadthing'
id: '__root__' | '/api/uploadthing'
fileServerRoutesById: FileServerRoutesById
}
export interface RootServerRouteChildren {
ApiUploadthingServerRoute: typeof ApiUploadthingServerRoute
ApiUploadthingRoute: typeof ApiUploadthingRoute
}

declare module '@tanstack/react-router' {
Expand All @@ -79,29 +58,29 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
}
}
declare module '@tanstack/react-start/server' {
interface ServerFileRoutesByPath {
'/api/uploadthing': {
id: '/api/uploadthing'
path: '/api/uploadthing'
fullPath: '/api/uploadthing'
preLoaderRoute: typeof ApiUploadthingServerRouteImport
parentRoute: typeof rootServerRouteImport
preLoaderRoute: typeof ApiUploadthingRouteImport
parentRoute: typeof rootRouteImport
}
}
}

const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
ApiUploadthingRoute: ApiUploadthingRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()
const rootServerRouteChildren: RootServerRouteChildren = {
ApiUploadthingServerRoute: ApiUploadthingServerRoute,

import type { getRouter } from './router.tsx'
import type { createStart } from '@tanstack/react-start'
declare module '@tanstack/react-start' {
interface Register {
ssr: true
router: Awaited<ReturnType<typeof getRouter>>
}
}
export const serverRouteTree = rootServerRouteImport
._addFileChildren(rootServerRouteChildren)
._addFileTypes<FileServerRouteTypes>()
12 changes: 3 additions & 9 deletions examples/minimal-tanstack-start/src/router.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { createRouter as createTanStackRouter } from "@tanstack/react-router";
import { createRouter } from "@tanstack/react-router";

import { routeTree } from "./routeTree.gen";

export function createRouter() {
const router = createTanStackRouter({
export function getRouter() {
const router = createRouter({
routeTree,
scrollRestoration: true,
});

return router;
}

declare module "@tanstack/react-router" {
interface Register {
router: ReturnType<typeof createRouter>;
}
}
34 changes: 26 additions & 8 deletions examples/minimal-tanstack-start/src/routes/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
import * as React from "react";
import * as TSR from "@tanstack/react-router";
/// <reference types="vite/client" />
import type { ReactNode } from "react";
import {
createRootRoute,
HeadContent,
Outlet,
Scripts,
} from "@tanstack/react-router";

import uploadthingCss from "@uploadthing/react/styles.css?url";

export const Route = TSR.createRootRoute({
component: RootComponent,
export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
},
{
title: "TanStack Start Starter",
},
],
links: [{ rel: "stylesheet", href: uploadthingCss }],
}),
Comment on lines 13 to 27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UploadThing CSS styles are missing. The documentation shows CSS should be imported for proper component styling, but the import was removed from this file and not replaced anywhere else.

The old code had:

import uploadthingCss from "@uploadthing/react/styles.css?url";

export const Route = createRootRoute({
  head: () => ({
    links: [{ rel: "stylesheet", href: uploadthingCss }],
  }),
});

According to the documentation at docs/src/app/(docs)/getting-started/tanstack-start/page.mdx, you should add:

import uploadthingCss from "@uploadthing/react/styles.css?url";

export const Route = createRootRoute({
  head: () => ({
    meta: [
      {
        charSet: "utf-8",
      },
      {
        name: "viewport",
        content: "width=device-width, initial-scale=1",
      },
      {
        title: "TanStack Start Starter",
      },
    ],
    links: [{ rel: "stylesheet", href: uploadthingCss }],
  }),
  component: RootComponent,
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/minimal-tanstack-start/src/routes/__root.tsx
Line: 11:24

Comment:
UploadThing CSS styles are missing. The documentation shows CSS should be imported for proper component styling, but the import was removed from this file and not replaced anywhere else.

The old code had:
```typescript
import uploadthingCss from "@uploadthing/react/styles.css?url";

export const Route = createRootRoute({
  head: () => ({
    links: [{ rel: "stylesheet", href: uploadthingCss }],
  }),
});
```

According to the documentation at `docs/src/app/(docs)/getting-started/tanstack-start/page.mdx`, you should add:

```typescript
import uploadthingCss from "@uploadthing/react/styles.css?url";

export const Route = createRootRoute({
  head: () => ({
    meta: [
      {
        charSet: "utf-8",
      },
      {
        name: "viewport",
        content: "width=device-width, initial-scale=1",
      },
      {
        title: "TanStack Start Starter",
      },
    ],
    links: [{ rel: "stylesheet", href: uploadthingCss }],
  }),
  component: RootComponent,
});
```

How can I resolve this? If you propose a fix, please make it concise.

component: RootComponent,
});

function RootComponent() {
return (
<RootDocument>
<TSR.Outlet />
<Outlet />
</RootDocument>
);
}

function RootDocument({ children }: { children: React.ReactNode }) {
function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
return (
<html>
<head>
<TSR.HeadContent />
<HeadContent />
</head>
<body>
{children}
<TSR.Scripts />
<Scripts />
</body>
</html>
);
Expand Down
12 changes: 0 additions & 12 deletions examples/minimal-tanstack-start/src/routes/api.uploadthing.ts

This file was deleted.

20 changes: 20 additions & 0 deletions examples/minimal-tanstack-start/src/routes/api/uploadthing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createFileRoute } from "@tanstack/react-router";

import { createRouteHandler } from "uploadthing/server";

import { uploadRouter } from "../../server/uploadthing";

const handler = createRouteHandler({ router: uploadRouter });

export const Route = createFileRoute("/api/uploadthing")({
server: {
handlers: {
GET: async ({ request }: { request: Request }) => {
return handler(request);
},
POST: ({ request }: { request: Request }) => {
return handler(request);
},
},
},
});
4 changes: 2 additions & 2 deletions examples/minimal-tanstack-start/src/server/uploadthing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createUploadthing } from "uploadthing/next";
import type { FileRouter } from "uploadthing/next";
import { createUploadthing, UploadThingError } from "uploadthing/server";
import type { FileRouter } from "uploadthing/server";

const f = createUploadthing({
/**
Expand Down
11 changes: 9 additions & 2 deletions examples/minimal-tanstack-start/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true,
"types": ["vite/client"]
}
"types": ["vite/client"],
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"allowImportingTsExtensions": true,
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"resolveJsonModule": true
},
"include": ["src"]
}
9 changes: 8 additions & 1 deletion examples/minimal-tanstack-start/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import viteReact from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import tsConfigPaths from "vite-tsconfig-paths";

export default defineConfig({
server: {
port: 3000,
},
plugins: [tanstackStart()],
plugins: [
tsConfigPaths(),
tanstackStart(),
// react's vite plugin must come after start's vite plugin
viteReact(),
],
});
Loading
Loading