Skip to content
Merged
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
40 changes: 21 additions & 19 deletions docs/start/framework/react/guide/server-entry-point.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@ title: Server Entry Point
> [!NOTE]
> The server entry point is **optional** out of the box. If not provided, TanStack Start will automatically handle the server entry point for you using the below as a default.

This is done via the `src/server.ts` file.
The Server Entry Point supports the universal fetch handler format, commonly used by [Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) and other WinterCG-compatible runtimes.

```tsx
// src/server.ts
import handler, { type ServerEntry } from '@tanstack/react-start/server-entry'
To ensure interoperability, the default export must conform to our `ServerEntry` interface:

```ts
export default {
fetch(request) {
return handler.fetch(request)
fetch(req: Request, opts?: RequestOptions): Response | Promise<Response> {
// ...
},
} satisfies ServerEntry
}
```

The default export must conform to the `ServerEntry` interface:
TanStack Start exposes a wrapper to make creation type-safe. This is done in the `src/server.ts` file.

```ts
export default {
fetch(req: Request, opts?: RequestOptions): Promise<Response> {
// ...
```tsx
// src/server.ts
import handler, { createServerEntry } from '@tanstack/react-start/server-entry'

export default createServerEntry({
fetch(request) {
return handler.fetch(request)
},
}
})
```

Whether we are statically generating our app or serving it dynamically, the `server.ts` file is the entry point for doing all SSR-related work as well as for handling server routes and server function requests.
Expand All @@ -44,7 +46,7 @@ import {
defaultStreamHandler,
defineHandlerCallback,
} from '@tanstack/react-start/server'
import type { ServerEntry } from '@tanstack/react-start/server-entry'
import { createServerEntry } from '@tanstack/react-start/server-entry'

const customHandler = defineHandlerCallback((ctx) => {
// add custom logic here
Expand All @@ -53,9 +55,9 @@ const customHandler = defineHandlerCallback((ctx) => {

const fetch = createStartHandler(customHandler)

export default {
export default createServerEntry({
fetch,
} satisfies ServerEntry
})
```

## Request context
Expand All @@ -65,7 +67,7 @@ When your server needs to pass additional, typed data into request handlers (for
To add types for your request context, augment the `Register` interface from `@tanstack/react-start` with a `server.requestContext` property. The runtime `context` you pass to `handler.fetch` will then match that type. Example:

```tsx
import handler, { type ServerEntry } from '@tanstack/react-start/server-entry'
import handler, { createServerEntry } from '@tanstack/react-start/server-entry'

type MyRequestContext = {
hello: string
Expand All @@ -80,11 +82,11 @@ declare module '@tanstack/react-start' {
}
}

export default {
export default createServerEntry({
async fetch(request) {
return handler.fetch(request, { context: { hello: 'world', foo: 123 } })
},
} satisfies ServerEntry
})
```

## Server Configuration
Expand Down
17 changes: 10 additions & 7 deletions packages/react-start/src/default-entry/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import type { RequestHandler } from '@tanstack/react-start/server'

const fetch = createStartHandler(defaultStreamHandler)

const serverEntry = {
// Providing `RequestHandler` from `@tanstack/react-start/server` is required so that the output types don't import it from `@tanstack/start-server-core`
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
fetch: fetch as RequestHandler<Register>,
} as const
// Providing `RequestHandler` from `@tanstack/react-start/server` is required so that the output types don't import it from `@tanstack/start-server-core`
export type ServerEntry = { fetch: RequestHandler<Register> }

export type ServerEntry = typeof serverEntry
export function createServerEntry(entry: ServerEntry): ServerEntry {
return {
async fetch(...args) {
return await entry.fetch(...args)
},
}
}

export default serverEntry
export default createServerEntry({ fetch })
17 changes: 10 additions & 7 deletions packages/solid-start/src/default-entry/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import type { RequestHandler } from '@tanstack/solid-start/server'

const fetch = createStartHandler(defaultStreamHandler)

const serverEntry = {
// Providing `RequestHandler` from `@tanstack/solid-start/server` is required so that the output types don't import it from `@tanstack/start-server-core`
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
fetch: fetch as RequestHandler<Register>,
} as const
// Providing `RequestHandler` from `@tanstack/solid-start/server` is required so that the output types don't import it from `@tanstack/start-server-core`
export type ServerEntry = { fetch: RequestHandler<Register> }

export type ServerEntry = typeof serverEntry
export function createServerEntry(entry: ServerEntry): ServerEntry {
return {
async fetch(...args) {
return await entry.fetch(...args)
},
}
}

export default serverEntry
export default createServerEntry({ fetch })
Loading