* feat(release): reclassify commits via SHA-named changeset overrides
Auto-changesets are regenerated from commit subjects every push and never
committed to main, so a mislabeled commit can't be fixed by editing them, and a
hand-authored changeset can only raise a bump (max), never lower it.
Add a per-commit override: commit `.changeset/<sha>.md` and the release tooling
treats that commit as the bump declared in its frontmatter (patch->fix,
minor->feat, major->feat!, empty->chore/dropped), driving both the semver bump
and the changelog section. The file is a real changeset, so changesets/action
consumes it for the bump and deletes it on release -- overrides never accumulate.
Both create-changeset.mts (bump) and version.mts (changelog grouping) honor it,
keyed off the SHA in the filename.
* chore: reclassify #1804 as a fix
Override `feat(interception): sibling-style interception routes (#1804)`
(b4c829d6) to release as a patch-level fix instead of a minor feature.
* feat(release): use SHA-named override changeset body as the changelog message
The override changeset's body now becomes the reclassified commit's changelog
entry -- a plain bullet replacing the commit subject's description (scope and
all) -- in addition to overriding the bump and section. Leave the body empty to
keep the original subject and only reclassify the type.
Adds changesetBodyMessage(), threads an optional message through
rewriteSubjectType() and applyOverrides(), and captures it in loadOverrides().
* chore: set #1804 override changelog message
Now that the override body drives the changelog, give it a proper Bug Fixes
entry instead of a meta rationale.
Steer consumers toward the declarative `cache` option on the vinext()
plugin (with the @vinext/cloudflare builders kvDataAdapter/cdnAdapter)
instead of imperatively wiring cache handlers from a worker entry.
- Mark setDataCacheHandler, setCacheHandler, and setCdnCacheAdapter as
@deprecated with config-based migration examples. They remain functional
as the internal registration target used by virtual:vinext-cache-adapters.
- Mark the manually-instantiated handler exports MemoryCacheHandler and
KVCacheHandler as @deprecated for consumers.
- Update the next/cache type declarations in next-shims.d.ts to match.
- Fix stale AGENTS.md claim: the default data cache is in-memory
(MemoryCacheHandler) in all runtimes; KV is opt-in, not the default.
Changesets are auto-generated from Conventional Commits in CI, so agents
should write a proper commit message instead of hand-authoring
.changeset/*.md or running pnpm changeset.
* fix(assets): default assetsDir to _next/static (Next.js parity)
Closes#1337. Supersedes #1383.
vinext's default `assetsDir` was Vite's historical `assets/`, so URL emission
(`/_next/static/...` via `resolveAssetUrlPrefix("")`) and on-disk layout
(`dist/client/assets/...`) disagreed in the empty-`assetPrefix` case. The
`build.assetsDir` and `experimental.renderBuiltUrl` Vite overrides only
applied when `assetPrefix` was configured, leaving the no-prefix branch
serving from a different path than the URL contract Next.js's client
runtime and test harness assert against.
This commit flips the default to Next.js's canonical layout:
- `resolveAssetsDir("")` returns `_next/static` (was `assets`)
- `build.assetsDir` is now set unconditionally from `resolveAssetsDir`
- Vite's default `base + assetsDir` composition produces correct URLs
in the no-prefix case; `renderBuiltUrl` stays gated on `assetPrefix`
because it's only needed for the configured cases
- Drops the legacy `/assets/` branches in prod-server (3 sites) and
static-file-cache (hard cutover — see PR description for rationale)
- Updates `_headers` generation, precompress default, fonts plugin
`DEFAULT_ASSETS_DIR` to match the new default
With the layout aligned, invalid `_next/static/*` requests naturally
return plain-text `404 + "Not Found"` from the static-file layer instead
of falling through to the page renderer (which would produce an HTML
404 with bootstrap scripts and CSS). This replaces #1383's parity
short-circuit with the natural code path:
- Node prod-server (App + Pages branches): missing asset under
`resolveAppRouterAssetPath` returns `text/plain; charset=utf-8` 404
- Cloudflare worker entry: `isNextStaticPath` recognises asset-shape
after ASSETS-binding misses; returns `notFoundStaticAssetResponse`
Mirrors Next.js: packages/next/src/server/lib/router-server.ts.
Adds `tests/invalid-static-asset-404.test.ts` (3 App Router + 3 Pages
Router cases — no prefix / basePath / assetPrefix) ported from Next.js
e2e suites. Updates 11 source files + 12 test files; 914+ tests pass
in the touched suites (asset-prefix, app-router, pages-router, deploy,
font-google, static-file-cache, serve-static, precompress, features,
routing, isr-cache, build-optimization, app-rsc/ssr, standalone,
middleware, shims).
Ported from Next.js:
- test/e2e/invalid-static-asset-404-app/*.test.ts
- test/e2e/invalid-static-asset-404-pages/*.test.ts
* fix(e2e): update cloudflare-pages-router hydration spec for _next/static
* PR #1411 approved. Clean fix, 2 nits.
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
* refactor(assets): derive isHashed checks from ASSET_PREFIX_URL_DIR
Replace hardcoded '_next/static' string literals in runtime code paths
with the ASSET_PREFIX_URL_DIR constant so the asset URL convention has
a single source of truth.
- server/prod-server.ts isHashed: pathname.includes(`/${ASSET_PREFIX_URL_DIR}/`)
- server/prod-server.ts public-dir guard: startsWith(`/${ASSET_PREFIX_URL_DIR}/`)
- server/static-file-cache.ts isHashed: both startsWith + includes derived
- plugins/fonts.ts DEFAULT_ASSETS_DIR = ASSET_PREFIX_URL_DIR
Behavioural no-op — the constant is '_next/static' so the resolved
strings are identical. Centralises the URL contract so future changes
to ASSET_PREFIX_URL_DIR (or a refactor that derives it from build
config) flow through to every consumer.
Doc-comment references to '_next/static' left in place — they
describe the canonical value for human readers and are not code paths.
---------
Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
- Bump vite, vite-plus, vitest catalog entries to 0.1.21
- Refresh pnpm-lock.yaml
- Regenerate AGENTS.md via vp config postinstall
- Drop unused imports (PHASE_PRODUCTION_BUILD, patternToNextFormat) flagged by upgraded lint rules
- Move react-hooks/rules-of-hooks suppression in tests/e2e/fixtures.ts to the use(errors) call site
- Add react/no-children-prop and react/no-danger-with-children suppressions on the intentional precedence test in tests/head.test.ts
* chore(benchmarks): remove Vite 7 runner, update Next.js to 16.2.1
The vinext-rolldown benchmark runner was identical to the vinext runner
(both resolved to the same Vite version via catalog), producing
duplicate results on the dashboard. Remove it entirely and simplify
to a two-runner comparison: Next.js (Turbopack) vs vinext (Vite 8).
Also bump the Next.js benchmark dependency from 16.1.7 to 16.2.1 to
pick up recent performance improvements.
* fix: remove vinext-rolldown from pnpm-workspace.yaml, fix migration comment
Add mandatory Next.js behavior verification for all bug fixes and
security work, not just feature development. We repeatedly shipped
fixes that diverged from Next.js because this step was skipped
(config header execution order, javascript: URI blocking, ISR cache
key semantics).
Changes:
- Add local Next.js clone instructions (.nextjs-ref, gitignored)
for fast ripgrep searches of source and test suite
- Add 4-step verification checklist to Fixing Bugs section
- Require documenting what Next.js does in PRs and issue closures
- Update Looking at Next.js Source with clone instructions
- Add .nextjs-ref/ to .gitignore
* chore: migrate to vite plus
* Disable typeAware and typeCheck
* Update CI
* Fix CI
* Fix test
* Clean
* Run test with vp
* Try revert
* react: false In test
* Fix test
* Revert "Try revert"
This reverts commit 009da10473.
* Update
* Update
* Try revert ci changes
* revert
* Run vp migrate
* Disable typeAware and typeCheck for now
* Better resolve for test
* Use vp dev instead of vite
* Update expect
* Fix NormalizeManifestModuleId
* Try increase timeout
* Update to use vp
* Try new check
* Bring back npx vp
* Migrate CI
* Make next-intl resolvable
* Update
* Update
* Update
* add oxfmt formatter: config, scripts, CI, editor setup, docs
* rebuild lockfile
* fix: add Format to required checks list, remove dead ignore pattern
* run fmt
* add format to agents.md again
* refactor: delete app-dev-server.ts and update all references to entries/ directly
The file was already a pure re-export shim with no logic of its own.
Update every import/dynamic-import site to point straight at the
individual entry modules:
entries/app-rsc-entry.ts ← generateRscEntry, AppRouterConfig
entries/app-ssr-entry.ts ← generateSsrEntry
entries/app-browser-entry.ts ← generateBrowserEntry
Sites updated:
packages/vinext/src/index.ts
tests/entry-templates.test.ts
tests/app-router.test.ts
tests/shims.test.ts
Also update stale comments in:
server/middleware-codegen.ts, server/request-pipeline.ts,
server/instrumentation.ts, shims/metadata.tsx,
tests/rsc-streaming.test.ts, tests/nextjs-compat/rsc-context-lazy-stream.test.ts,
examples/app-router-cloudflare/instrumentation*.ts
* docs: update app-dev-server.ts references in markdown files to entries/
The full Vitest suite runs serially (~2 min) due to Vite deps optimizer
cache races between test files. Agents rarely need the full suite during
development. This adds a Running Tests section with a mapping from source
files to relevant test files, so agents run only what they need (seconds
instead of minutes).
* fix: throw on missing middleware/proxy exports instead of failing open
Middleware and proxy files that don't export the expected function
(e.g. misspelled export, wrong named export) were silently skipped,
letting requests through unprotected. This matches Next.js behavior
which throws a ProxyMissingExportError in the same scenario.
Changes:
- proxy.ts files now require 'proxy' or 'default' export
- middleware.ts files now require 'middleware' or 'default' export
- All 3 code paths updated (Pages dev, Pages prod, App Router)
- Added resolveMiddlewareHandler() with file-type-aware validation
- Ported test cases from Next.js proxy-missing-export test suite
- Updated AGENTS.md: added required step to search Next.js tests
Ported from Next.js: test/e2e/app-dir/proxy-missing-export/
https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/proxy-missing-export/proxy-missing-export.test.ts
* fix: update export precedence test to match Next.js behavior (named > default)
* fix: use ?? instead of || in generated middleware export resolution for consistency
Matches the shared resolveMiddlewareHandler() which uses nullish
coalescing. No behavioral difference since typeof check catches
all cases, but keeps the three code paths consistent.
* Skip deploy previews for fork PRs that lack Cloudflare secrets
Fork PRs don't have access to repository secrets (CLOUDFLARE_API_TOKEN,
CLOUDFLARE_ACCOUNT_ID), so deploy/smoke-test/comment steps always fail.
Add a fork detection condition to skip these steps gracefully. The build
steps still run, so example builds are still validated for fork PRs.
* Run safe CI for external contributors, add /deploy-preview slash command
Switch ci.yml from pull_request to pull_request_target so lint, typecheck,
vitest, and e2e run automatically for fork PRs without needing approval.
No secrets are used, so this is safe with untrusted code.
Add a /deploy-preview slash command workflow that lets maintainers trigger
deploy previews on fork PRs. Gated by author_association (org members,
collaborators, repo owners only).
Cloudflare employees who push branches to the main repo continue to get
automatic deploy previews via the existing deploy-examples.yml workflow.
* Revert ci.yml to pull_request, skip deploy-examples for fork PRs
Simpler approach: keep ci.yml on pull_request (first-time contributor
approval is fine, avoids cache poisoning concern with pull_request_target).
The actual fix: add a job-level if condition to deploy-examples.yml so the
entire workflow is skipped for fork PRs. This prevents the noisy
failed/skipped deploy checks on external contributor PRs.
Update docs in AGENTS.md and README.md to reflect the approach.
* feat(cli): load .env files with Next.js precedence
* fix(dotenv): address review feedback on .env loading
- Document Vite double-loading interaction in loadDotenv JSDoc
- Fix escaped dollar sign bug ($100 was not unescaped when $ wasn't
followed by a valid variable name)
- Add type cast for parseEnv return value
- Expand test coverage: loadedEnv assertions, production mode
precedence, ${VAR} expansion, escaped dollars, circular refs,
missing files, empty result
- Add getDotenvFiles unit tests for all three modes
- Add 'Prefer Node.js Built-in APIs' guideline to AGENTS.md
Co-authored-by: liuxiaopai-ai <liuxiaopai-ai@users.noreply.github.com>
* test(dotenv): add cross-file expansion and multi-line value tests
Address review suggestions: test that .env can reference vars from
higher-priority .env.development.local, and that parseEnv handles
quoted multi-line values correctly.
---------
Co-authored-by: root <root@localhost.localdomain>
Co-authored-by: liuxiaopai-ai <liuxiaopai-ai@users.noreply.github.com>