mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #992] [MERGED] fix(headers): align draft mode cookie attributes with Next.js #1007
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#1007
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/992
Author: @NathanDrake2406
Created: 4/30/2026
Status: ✅ Merged
Merged: 4/30/2026
Merged by: @james-elicx
Base:
main← Head:nathan/fix-draft-mode-cookie-attrs📝 Commits (1)
4b1da5dfix(headers): align draft mode cookie attributes with Next.js📊 Changes
3 files changed (+64 additions, -7 deletions)
View changed files
📝
packages/vinext/src/shims/headers.ts(+10 -6)📝
tests/nextjs-compat/draft-mode.test.ts(+52 -0)📝
tests/shims.test.ts(+2 -1)📄 Description
What this changes
Vinext draft-mode cookies now match Next.js production cookie semantics.
draftMode().enable()emitsSameSite=None; Secureoutside development, anddraftMode().disable()clears the bypass cookie with an expired date while preserving the same production attributes.Why
The existing shim always emitted
SameSite=Laxand cleared withMax-Age=0. That diverges from Next.js and can prevent production preview flows from receiving the__prerender_bypasscookie in cross-site contexts, leavingdraftMode().isEnabledfalse even after enabling draft mode.Next.js references:
DraftModeProvider.enable()usessameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax'andsecure: process.env.NODE_ENV !== 'development': draft-mode-provider.ts#L68-L75DraftModeProvider.disable()clears viaexpires: new Date(0)with the same cookie attributes: draft-mode-provider.ts#L80-L92sameSiteandsecurepolicy: api-resolver.ts#L131-L160Approach
The draft-mode cookie behavior stays in the normal
next/headersshim module. Generated entries still only ask the shim for the pending draft-mode cookie header, so codegen remains app-shape wiring rather than owning cookie policy.The implementation adds a small helper for draft-mode cookie attributes:
Path=/; HttpOnly; SameSite=LaxPath=/; HttpOnly; SameSite=None; SecureDisable now emits
Expires=Thu, 01 Jan 1970 00:00:00 GMTinstead ofMax-Age=0, matching Next.js's documented source comment and avoiding a cookie-clear form Next.js explicitly does not use.Validation
vp test run tests/nextjs-compat/draft-mode.test.ts -t "cross-site|Next.js production cookie attributes"failed before the fix withSameSite=LaxandMax-Age=0.vp test run tests/nextjs-compat/draft-mode.test.tsvp test run tests/shims.test.ts -t "draftMode"vp lintvp fmtvp checkRisks / follow-ups
This intentionally changes only draft-mode cookie serialization. Request parsing, secret validation, generated entry wiring, and route-handler response plumbing are unchanged.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.