mirror of
https://github.com/payloadcms/payload.git
synced 2026-09-14 20:07:19 +08:00
feat: add TanStack Start framework adapter (#16139)
Adds `@payloadcms/tanstack-start` — the first non-Next.js framework adapter for Payload's admin panel. ## Background The framework adapter pattern already landed across four PRs: - [Server adapter](#16753) - [Router adapter](#16763) - [View adapter](#16803) - [Layout adapter](#16840) This pushed every Next-specific concern (routing, request init, server functions, HMR) behind typed contracts in `payload` and made `@payloadcms/ui` framework-agnostic. This PR is the payoff: a working adapter built entirely on that abstraction, proving the admin panel renders on a non-Next stack with no forks of the UI. ## Motivation - **Prove the abstraction.** The adapter contracts are only as good as a second implementation. TanStack Start exercises every seam — a different renderer, a different server-function transport, a different build tool — and validates that `@payloadcms/ui` carries no hidden Next.js assumptions. - **Meet users where they are.** Not every project is on Next.js. Decoupling the admin panel opens Payload to the broader React SSR ecosystem, with TanStack Start as the first proof point. - **Keep one UI.** Both adapters render the same `@payloadcms/ui` components and data fetchers. There is no TanStack fork of the admin panel — only a thin adapter package that satisfies the contracts. ## How it differs from the Next.js adapter Same UI, different plumbing behind the contracts: | | Next.js | TanStack Start | | ---------------- | -------------------------- | --------------------------------- | | Server rendering | RSC flight payloads | SSR + route loaders | | Server functions | `'use server'` actions | `createServerFn` | | Request init | `next/headers` | `@tanstack/react-start/server` | | Build / HMR | Webpack / Turbopack | Vite | ## Integration touch points Wiring Payload into a TanStack Start app is a handful of file routes, similar to the Next.js app dir shipped since Payload v3: ``` app/ ├── __root.tsx # root shell — withPayloadRoot swaps in the admin document on /admin ├── _frontend.tsx # your app's layout route ├── _frontend/ # your app's routes ├── _payload.tsx # admin layout route — mounts Payload providers └── _payload/ ├── admin.index.tsx # /admin ├── admin.$.tsx # /admin/* (splat) ├── api.$.ts # /api/* — Payload REST handlers └── server.functions.ts # config + importMap injection; server functions ``` **Root shell** — This is the highest level touchpoint that affects your app. In your root route file, add the `withPayloadRoot` shell component: ```tsx // app/__root.tsx import { withPayloadRoot } from "@payloadcms/tanstack-start/client"; export const Route = createRootRoute({ shellComponent: withPayloadRoot(MarketingRoot), }); ``` For all other file contents, see the `app-tanstack` directory in the monorepo (subject to change). Docs to be provided in the future. ## Status Experimental. Ships as a new package alongside the Next.js adapter; nothing in the existing Next path changes at runtime. --------- Co-authored-by: Jake Fletcher <jacobsfletch@gmail.com>
This commit is contained in:
@@ -80,6 +80,7 @@
|
||||
"dev:generate-types": "pnpm runts ./test/generateTypes.ts",
|
||||
"dev:postgres": "cross-env PAYLOAD_DATABASE=postgres pnpm runts ./test/dev.ts",
|
||||
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --prod",
|
||||
"dev:tanstack": "cross-env PAYLOAD_FRAMEWORK=tanstack-start NODE_OPTIONS=\"--no-deprecation --max-old-space-size=16384\" tsx ./test/dev.ts",
|
||||
"dev:vercel-postgres": "cross-env PAYLOAD_DATABASE=vercel-postgres pnpm runts ./test/dev.ts",
|
||||
"devsafe": "node ./scripts/delete-recursively.js '**/.next' && pnpm dev",
|
||||
"docker:clean": "node ./scripts/docker-clean.ts",
|
||||
@@ -121,6 +122,8 @@
|
||||
"test:e2e:prod:ci:noturbo": "pnpm prepare-run-test-against-prod:ci && pnpm test:e2e:prod:run:noturbo",
|
||||
"test:e2e:prod:run": "pnpm runts ./test/runE2E.ts --prod",
|
||||
"test:e2e:prod:run:noturbo": "pnpm runts ./test/runE2E.ts --prod --no-turbo",
|
||||
"test:e2e:tanstack": "cross-env PAYLOAD_FRAMEWORK=tanstack-start pnpm runts ./test/runE2E.ts",
|
||||
"test:e2e:tanstack:headed": "cross-env PAYLOAD_FRAMEWORK=tanstack-start NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true playwright test --headed",
|
||||
"test:eval": "node ./test/evals/cli.ts",
|
||||
"test:eval:report": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" NODE_NO_WARNINGS=1 vitest --run --project eval --reporter=default --reporter=html --outputFile.html=test/evals/eval-results/report.html",
|
||||
"test:int": "cross-env NODE_OPTIONS=\"--no-deprecation --no-experimental-strip-types\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true vitest --project int --no-cache",
|
||||
@@ -199,6 +202,7 @@
|
||||
"tsx": "4.22.4",
|
||||
"turbo": "^2.5.4",
|
||||
"typescript": "catalog:",
|
||||
"vite": "~7.3.2",
|
||||
"vitest": "4.1.6",
|
||||
"wrangler": "~4.61.1",
|
||||
"zod": "4.3.6"
|
||||
|
||||
Reference in New Issue
Block a user