Skip to content

refactor(tanstack-start)!: use React Flight for RSC responses - #18787

Open
jacobsfletch wants to merge 5 commits into
mainfrom
codex/tanstack-flight-responses
Open

jacobsfletch wants to merge 5 commits into
mainfrom
codex/tanstack-flight-responses

Conversation

@jacobsfletch

@jacobsfletch jacobsfletch commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Removes serializeForRSC for TanStack server-function responses in favor of native React Flight.

Previously, we recursively walked each response and wrapped React components individually. Now, the entire response goes through Flight once, keeping components and data together.

Breaking Changes

Update the dispatcher in app-tanstack/app/_payload/server.functions.ts to return the native Flight response directly:

-return (await handleServerFunctions({
+return handleServerFunctions({
   args: data.args,
   config: await getConfig(),
   importMap: await getImportMap(),
   name: data.name,
-})) as any
+})

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: payloadcms/payload/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c3b772b3-8609-44f0-a981-9951abf7200c
📥 Commits

Reviewing files that changed from the base of the PR and between 76abf10 and d1aeeb7.

⛔ Files ignored due to path filters: 1
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing: 15
  • app-tanstack/app/_payload/server.functions.ts
  • package.json
  • packages/tanstack-start/src/adapters/handleServerFunctions.ts
  • packages/tanstack-start/src/exports/server.ts
  • packages/tanstack-start/src/utilities/serializeForRsc.ts
  • packages/tanstack-start/src/utilities/serializers.spec.ts
  • packages/tanstack-start/src/utilities/serverFunctionClient.ts
  • packages/tanstack-start/src/utilities/toSerializable.ts
  • packages/ui/src/utilities/handleServerFunctions.ts
  • packages/ui/src/utilities/serverFunctionRegistry.ts
  • templates/blank-tanstack/src/app/_payload/server.functions.ts
  • test/admin-bar/app-tanstack/app/_payload/server.functions.ts
  • test/app-tanstack/app/_payload/server.functions.ts
  • test/form-state/e2e.spec.ts
  • test/live-preview/app-tanstack/app/_payload/server.functions.ts
💤 Files with no reviewable changes: 3
  • packages/tanstack-start/src/exports/server.ts
  • packages/tanstack-start/src/utilities/toSerializable.ts
  • packages/tanstack-start/src/utilities/serializeForRsc.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

TanStack Start server functions now return React Flight responses, which the client validates and decodes. The shared handler returns results without a transformation hook. Payload route functions return handler results directly, and the form-state end-to-end test covers both Next.js and TanStack Start.

Changes: Server-function transport

Layer / File(s) Summary
Handler and Flight response
packages/ui/src/utilities/handleServerFunctions.ts, packages/tanstack-start/src/adapters/handleServerFunctions.ts, packages/tanstack-start/src/utilities/serverFunctionClient.ts, packages/tanstack-start/src/exports/server.ts, packages/tanstack-start/src/utilities/serializeForRsc.ts, packages/tanstack-start/src/utilities/serializers.spec.ts, packages/tanstack-start/src/utilities/toSerializable.ts, packages/ui/src/utilities/serverFunctionRegistry.ts
The shared handler returns results without a transformResult hook. The TanStack Start adapter renders results into a text/x-component response. The client checks the response status, media type, and body before decoding it. The serializeForRsc utility and export were removed, along with related comments and test coverage.
Payload route return values
app-tanstack/app/_payload/server.functions.ts, templates/blank-tanstack/src/app/_payload/server.functions.ts, test/admin-bar/app-tanstack/app/_payload/server.functions.ts, test/app-tanstack/app/_payload/server.functions.ts, test/live-preview/app-tanstack/app/_payload/server.functions.ts
The payload route functions return handleServerFunctions results directly, without any casts or the removed explanatory comments.
Cross-framework form-state test
test/form-state/e2e.spec.ts, package.json
The form-state test now checks Next.js and TanStack Start request formats, rendered fields, row counts, and successful RSC responses. The root development dependencies add seroval for decoding TanStack Start request data.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Sequence Diagram(s)

sequenceDiagram
  participant createServerFunctionClient
  participant runServerFn
  participant handleServerFunctions
  participant createServerFunctionHandler
  participant FlightDecoder
  createServerFunctionClient->>runServerFn: sanitized server-function input
  runServerFn->>handleServerFunctions: invoke adapter handler
  handleServerFunctions->>createServerFunctionHandler: execute server function
  createServerFunctionHandler-->>handleServerFunctions: server-function result
  handleServerFunctions-->>createServerFunctionClient: text/x-component Response
  createServerFunctionClient->>FlightDecoder: response body
  FlightDecoder-->>createServerFunctionClient: decoded result
Loading
Merge Risk: ⚪ Minimal · up to d1aee

No actionable issue is established for this change; it is mergeable after normal checks.

Security architecture risk: 🔵 Low · up to d1aee

The response format changes across the client/server boundary, but inspected paths preserve server-derived identity and existing authorization responsibilities. No introduced security issue was established. Authorization coverage for every callable handler and behavior during interrupted response streams remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The affected entry point is the application's existing server-function POST dispatcher. Its registry includes form and document rendering, document-copy operations, publishing-job operations, and language-cookie changes. Accessible assets remain dependent on each selected handler's controls and the application's Payload configuration.

Trust Boundaries and Controls

  • observed — The dispatcher propagates identity and permissions but does not centrally authorize every named operation. Representative privileged handlers retain explicit controls: schedule-publish checks admin access and document permissions, while recently-viewed requires a user and uses access-controlled queries. Complete authorization and sensitive-output coverage across the registry remains unresolved.
  • observed — The generated route does not forward a client-supplied serverFunctions map, and trusted identity fields override corresponding input arguments. Native Flight and the client's media-type checks are response-transport controls, not substitutes for handler authorization or output filtering.

Resilience and Maintainability Implications

  • inferred — Known document-copy, scheduling, and cookie mutations remain awaited before streaming begins. A committed operation can therefore outlive a lost response acknowledgment. The previous transport also serialized results after handler completion; the comparison does not establish a newly introduced retry, ordering, or authority defect. Stream-interruption behavior for all result shapes remains unverified.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 11 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description clearly explains the replacement of custom serialization with native React Flight and identifies the related breaking dispatcher change.
Title check Passed The title clearly and concisely identifies the main change: using React Flight for TanStack Start RSC responses.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 11 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use path_filters to narrow the review scope.

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

📦 esbuild Bundle Analysis for payload

This analysis was generated by esbuild-bundle-analyzer. 🤖
This PR introduced no changes to the esbuild bundle! 🙌

@jacobsfletch jacobsfletch changed the title refactor(tanstack-start)!: use native Flight responses refactor(tanstack-start)!: use React Flight for RSC responses Oct 16, 2026

// Flight accepts complete models; TanStack's non-RSC declaration only accepts ReactNode.
return new Response(renderToReadableStream(result as ReactNode), {
headers: { 'Content-Type': 'text/x-component' },

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Uses text/x-component because the response now contains a React Flight stream, matching Next.js.

@jacobsfletch
jacobsfletch added this pull request to stack #18794 October 16, 2026 20:16
@jacobsfletch
jacobsfletch marked this pull request as ready for review October 16, 2026 20:28
const result = await runServerFunction(args)

// Flight accepts complete models; TanStack's non-RSC declaration only accepts ReactNode.
return new Response(renderToReadableStream(result as ReactNode), {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is the React Flight protocol that TanStack exposes

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant