refactor(next)!: move templates and elements to @payloadcms/ui#16765
Merged
jacobsfletch merged 19 commits intoMay 29, 2026
Conversation
Adds server-side adapter passed into server functions (not React context), abstracting framework-specific APIs like cookies, headers, redirect, and forbidden/unauthorized/notFound boundaries. - Define ServerAdapter type and Next.js implementation - Wire ServerAdapter through plugin-multi-tenant entrypoints - Safely access req.server from optional contexts
Groups framework adapter implementations under packages/next/src/adapters/ instead of mixing them into elements/ (UI primitives) and utilities/ (misc helpers). The Next adapter is neither — it bridges next/navigation into the RouterAdapterContext contract from payload core. Sets up the structure for the upcoming ServerAdapter to live alongside as adapters/server.ts.
Co-locates the Next ServerAdapter impl with the RouterAdapter impl under packages/next/src/adapters/. Both are framework bridges, not utilities.
Separates router contracts from cookie contracts: - adapters/router.ts: RouterAdapterComponent, RouterAdapterRouter, LinkAdapterProps - adapters/cookies.ts: CookieStore, CookieOptions - adapters/index.ts: barrel re-export Makes room for ServerAdapter to land as adapters/server.ts on its own branch without re-mingling concerns in a single file.
…-abstraction Adopts the adapters/ folder split for payload core. Resolves the conflict on admin/adapters.ts by extracting ServerAdapter into adapters/server.ts and updating the two ServerAdapter consumers (config/types.ts, types/index.ts).
Moves DocumentHeader, FormHeader, HierarchyTypeField, Logo, Nav, and Default/Minimal templates out of @payloadcms/next and into @payloadcms/ui. The two client files that called next/navigation now use the ui RouterAdapter hooks, so the relocated code has zero next.js imports. @payloadcms/next exports re-export from @payloadcms/ui to keep the existing public API stable.
These three subpaths were thin re-exports of @payloadcms/ui after the admin element relocation. Removing them deletes the indirection and points all consumers at the canonical @payloadcms/ui (or @payloadcms/ui/rsc) entry points. Updates the affected example, test, and template importMap files accordingly.
…ms/ui
Component path strings in payload core (SlugField, CollectionCards,
HierarchyTypeFieldServer, QueryPresets cells/fields) still referenced
the removed @payloadcms/next/{client,rsc} subpaths. Updates them plus
two doc examples to point at the canonical @payloadcms/ui and
@payloadcms/ui/rsc entry points.
…xports + add codemod
Adds a v4 migration guide entry covering the removal of
@payloadcms/next/{client,rsc,templates} and a companion
@payloadcms/codemod transform (migrate-next-subpath-exports) that
rewrites both import declarations and string-literal component paths in
Payload config to point at the canonical @payloadcms/ui entry points.
The relocation PR shouldn't churn the bundled template projects. Their import maps will be regenerated by `payload generate:importmap` on each release flow, so the in-tree files revert to the main snapshot.
Contributor
📦 esbuild Bundle Analysis for payloadThis analysis was generated by esbuild-bundle-analyzer. 🤖
Largest pathsThese visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
DetailsNext to the size is how much the size has increased or decreased compared with the base branch of this PR.
|
The relocated DocumentHeader, DefaultNav, SidebarTabs, HierarchyTypeFieldServer, and DefaultTemplate server components were importing their `'use client'` collaborators via relative paths. In production bundles that splits the React context across server and client chunks, which surfaced as `useServerFunctions must be used within a ServerFunctionsProvider` when SidebarTabsClient mounted under a RootProvider tree. Routes each server→client edge through `@payloadcms/ui`'s `exports/client` barrel (with the standard `payload/no-imports-from-exports-dir` disable) so the bundler treats the client modules as the same instance the RootProvider populates.
# Conflicts: # docs/migration-guide/v4.mdx # packages/next/src/layouts/Root/index.tsx # packages/ui/src/elements/DocumentHeader/Tabs/Tab/index.css # packages/ui/src/elements/DocumentHeader/Tabs/Tab/index.scss # packages/ui/src/elements/DocumentHeader/Tabs/Tab/index.tsx # packages/ui/src/elements/DocumentHeader/Tabs/index.css # packages/ui/src/elements/DocumentHeader/Tabs/index.scss # packages/ui/src/elements/DocumentHeader/Tabs/tabs/VersionsPill/index.css # packages/ui/src/elements/DocumentHeader/Tabs/tabs/VersionsPill/index.scss # packages/ui/src/elements/DocumentHeader/Tabs/tabs/VersionsPill/index.tsx
perfectionist/sort-imports flagged the blank line between the local import group and the side-effect `./index.css` import in two relocated files. Squash the blank line so the imports form one contiguous group.
The relocated `tabs/index.tsx` server module was importing the `'use client'` VersionsPill via a relative path. In production bundles that splits the DocumentInfo context across server and client chunks, so useDocumentInfo() returns the default empty object, versionCount is undefined, and the pill renders null — causing version-count e2e tests to time out waiting for `.pill-version-count` to appear. Routes this server→client edge through `@payloadcms/ui`'s `exports/client` barrel (matching the pattern from fd020ea) so the bundler treats the client module as the same instance the DocumentInfoProvider populates.
86eb6bd to
866444a
Compare
paulpopus
previously approved these changes
May 28, 2026
paulpopus
approved these changes
May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requires #16763 and #16753.
Moves all elements and templates defined in the
@payloadcms/nextpackage to@payloadcms/ui. This is in effort to convert the@payloadcms/nextpackage into a framework adapter.Relocated exports — code physically moved from
@payloadcms/nextto@payloadcms/ui:DefaultTemplate@payloadcms/next/templates@payloadcms/ui/rscDefaultTemplateProps@payloadcms/next/templates@payloadcms/ui/rscMinimalTemplate@payloadcms/next/templates@payloadcms/ui/rscMinimalTemplateProps@payloadcms/next/templates@payloadcms/ui/rscDocumentHeader@payloadcms/next/rsc@payloadcms/ui/rscDefaultNav@payloadcms/next/rsc@payloadcms/ui/rscLogo@payloadcms/next/rsc@payloadcms/ui/rscHierarchyTypeFieldServer@payloadcms/next/rsc@payloadcms/ui/rscDefaultNavClient@payloadcms/next/client@payloadcms/uiHierarchyTypeField@payloadcms/next/client@payloadcms/uiNavSidebarToggle@payloadcms/next/client@payloadcms/uiNavWrapper@payloadcms/next/client@payloadcms/uiThis PR also removes the now unneeded export aliases. These were in place for backwards compatibility during v3. Now, we enforce that all imports point to its canonical source, not the aliased export.
CollectionCards@payloadcms/next/rsc@payloadcms/ui/rscSlugField@payloadcms/next/client@payloadcms/uiQueryPresetsAccessCell@payloadcms/next/client@payloadcms/uiQueryPresetsColumnField@payloadcms/next/client@payloadcms/uiQueryPresetsColumnsCell@payloadcms/next/client@payloadcms/uiQueryPresetsGroupByCell@payloadcms/next/client@payloadcms/uiQueryPresetsGroupByField@payloadcms/next/client@payloadcms/uiQueryPresetsWhereCell@payloadcms/next/client@payloadcms/uiQueryPresetsWhereField@payloadcms/next/client@payloadcms/uiThe
./client,./rsc, and./templatessubpath exports on@payloadcms/nextare removed entirely.Codemod
To migrate automatically, there's a codemod for this change available by running: