payloadcms / payloadcms/payload

withPayload: scope the client-hint header injection to the admin route instead of '/:path*'

Open
#17,906 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

withPayload adds Accept-CH / Vary / Critical-CH: Sec-CH-Prefers-Color-Scheme on source: '/:path*' — every route of the host app (observed in @payloadcms/next@3.88.0, dist/withPayload/withPayload.js). The injection exists so the admin panel can server-render the correct theme without a flash (getRequestTheme reads the hint), which is right — but Critical-CH on public routes makes every cold Chromium navigation discard the response and retry it (an internal 307 to the same URL). For sites that pin a colour scheme and never read the preference, that is a wasted document round trip on every visitor's first page view, and it silently corrupts headless-browser TTFB measurement (the retried response is served from local cache, so the final hop reads ~0 ms).

Since withPayload doesn't currently know the admin route, could the entry be scoped via an option — e.g. accept the admin base path, or a clientHintHeaders: 'admin-only' | 'all' | false — defaulting to today's behaviour for compatibility?

Workaround we ship today: post-process the returned config, moving the injected entry from '/:path*' to '/:path(admin|admin/.*)':

const payloadConfig = withPayload(nextConfig, options)

export default {
  ...payloadConfig,
  headers: async () => scopeClientHintHeadersToAdmin((await payloadConfig.headers?.()) ?? []),
}

Happy to PR the option if the approach is agreeable.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in dist/withPayload/withPayload.js, tracing how withPayload creates the headers entry for '/:path*' and how the admin route is represented. Done means the client-hint injection can be scoped to the admin route without breaking the existing compatibility behavior; the issue does not name a test file.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, typescript
Domain
backend, web-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.