Tim Neutkens
90d · built 2026-09-08
Performance
What Tim Neutkens shipped in the selected window, measured in ETV, and how it compares with the 90 days before it.
Effective capacity
+3.1engineers
delivers like 4.1 (4.1x pre-AI)
Output (ETV)
17.2ETV
+67.2% vs 10.3 prior
Features share
41.8%
+7.8 pp vs prior window
Fixes share
15.4%
+6.0 pp vs prior window
Work mix
41.8% Features5.6% Maintenance32.9% Tests4.4% Docs15.4% Fixes
52 commits over 90 days, ending 2026-09-08.
Daily performance
Daily ETV, stacked by Features, Maintenance, Tests, Docs and Fixes.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 10 by ETV in the last 90 days.
- 2.1ETVRemove server route matcher stack (#94157) ### What? Remove the legacy server route matcher managers, route matcher providers, and server route matcher classes. Move route definition and params metadata into fsChecker output and request metadata instead. ### Why? The filesystem checker already owns the normalized route lookup path in production. Keeping a separate matcher manager stack duplicates route inventory, adds reload plumbing, and makes dev and production behavior harder to keep aligned. ### How? - Build pages and app route definitions in fsChecker from production manifests and from the dev route inventory. - Thread matched route definitions and params through resolve-routes and router-server request metadata into base-server and next-server. - Remove reloadMatchers propagation and delete the legacy matcher manager, provider, and matcher implementations and tests. - Preserve dev ensurePage behavior, including legacy custom-server render methods, and Pages API loading by using matched route definitions while loading compiled dev modules where needed. ### Verification - `pnpm test-start-webpack test/e2e/custom-routes/custom-routes.test.ts` - `pnpm test-start-turbo test/e2e/custom-routes/custom-routes.test.ts` - `pnpm test-dev-webpack test/e2e/custom-routes/custom-routes.test.ts` - `pnpm test-dev-turbo test/e2e/custom-routes/custom-routes.test.ts` - `pnpm test-dev-webpack test/e2e/on-request-error/dynamic-routes/dynamic-routes.test.ts` - `pnpm test-dev-turbo test/e2e/on-request-error/dynamic-routes/dynamic-routes.test.ts` - `pnpm test-start-webpack test/e2e/app-dir/app-routes/app-custom-routes.test.ts` - `pnpm test-start-webpack test/e2e/app-dir/edge-route-rewrite/edge-route-rewrite.test.ts` - `pnpm test-start-webpack test/e2e/middleware-rewrites/test/index.test.ts` - `pnpm test-start-webpack test/e2e/middleware-matcher/index.test.ts test/e2e/middleware-custom-matchers-basepath/test/index.test.ts test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts` - `pnpm test-start-webpack test/e2e/api-catch-all/api-catch-all.test.ts test/e2e/basepath-root-catch-all/basepath-root-catch-all.test.ts test/production/root-catchall-cache/root-catchall-cache.test.ts` - `pnpm test-start-webpack test/e2e/i18n-beforefiles-rewrite/i18n-beforefiles-rewrite.test.ts` - `pnpm test-start-webpack test/e2e/basepath/redirect-and-rewrite.test.ts` - `pnpm test-dev-webpack test/e2e/custom-server/custom-server.test.ts` - `pnpm test-start-webpack test/e2e/custom-server/custom-server.test.ts` - `pnpm --filter=next types` - `pnpm --filter=next build` - `git diff --check` <!-- NEXT_JS_LLM_PR -->github.com-vercel-next.js · 6b900193 · 2026-08-15
- 1.6ETVrequest insights: add DevTools request panel (5/5) (#93978) ## What? Adds the experimental Request Insights panel to the Next.js DevTools overlay. The panel provides: - A retained request list with stable selection as new requests arrive. - A “Page load” marker for the exact initial document request. - An end-to-end trace timeline that follows the recorded span hierarchy. - A focused default view of high-level spans and a verbose view for deeper investigation. - Fetch, cache, request, status, duration, and span-count details. - Readable sub-millisecond durations and consistent right-aligned request metrics. This PR is intentionally limited to the Request Insights UI. Additional OpenTelemetry coverage, span display names, and Server Action tracing are split into the dependent PRs below. ## Why? The Request Insights data was already available to tools, but inspecting it required consuming the development endpoint or CLI output. The DevTools panel makes the same request, fetch, cache, and timing information directly inspectable while developing an application. The focused/verbose split keeps the default trace useful for understanding the request lifecycle without hiding the lower-level spans needed for investigation. ## How? - Adds a Request Insights panel and request list to the DevTools overlay. - Builds timeline rows from recorded parent/child relationships instead of assigning synthetic sections. - Uses the request’s full duration as the timeline range and clips outlier spans to that range. - Merges recorded fetch metrics with their corresponding fetch spans. - Preserves the selected request ID until that request is no longer retained. - Compares `request.requestId` with `self.__next_r` to identify only the initial document request. ## Stack The first four Request Insights foundation PRs have already merged. The remaining review stack is: 1. **#93978 — Request Insights UI (this PR)** 2. #95765 — Missing OpenTelemetry spans 3. #95766 — Human-readable OpenTelemetry span names 4. #95767 — Server Action tracing and resolution ## Verification - `pnpm --filter=next build` - `pnpm exec jest packages/next/src/next-devtools/dev-overlay/components/request-insights/trace-viewer.test.ts --runInBand` <!-- NEXT_JS_LLM --> --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl>github.com-vercel-next.js · c427adf4 · 2026-07-14
- 1.5ETVrequest insights: record local framework spans (1/5) (#93974) ## What Adds a dev-only local recorder for framework OTEL spans. This lets Next mirror span data into an in-memory store when local span capture is enabled, without requiring a user to run an OTEL provider. Stack: 1. request insights: record local framework spans (1/5) ← current 2. request insights: derive request history and fetch data (2/5) 3. request insights: expose dev snapshots to tools and HMR (3/5) 4. request insights: add agent diagnosis access (4/5) 5. request insights: add DevTools request panel (5/5) ## Review Focus - Local recorder behavior when no OTEL provider is installed. - Preserving existing OTEL span API behavior when a provider is installed. - Request identity propagation through existing app render async storage. ## Proof In This PR - `pnpm jest packages/next/src/server/lib/trace/tracer.test.ts packages/next/src/server/lib/trace/span-store.test.ts --runInBand` - `pnpm --filter=next types` ## Deferred Coverage - Request-level aggregation, fetch enrichment, dev transport, CLI/MCP access, and the DevTools panel are later PRs in this stack. <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl>github.com-vercel-next.js · fab0afcb · 2026-07-12
- 1.2ETVFix Request Insights span collection (#95818) ## Summary Fix Request Insights collection so the dev server records all non-hidden Next.js spans locally, including non-vanilla trace and wrapped spans, while preserving the existing OpenTelemetry export allowlist unless verbose tracing is enabled. Keep reporting timelines correct by propagating request identity before work async storage exists, honoring explicit span timestamps, and anchoring request duration to the BaseServer request span. Standardize span categories on `next.span_category`, retain presentation-only UI filtering, and filter internal request identity headers at ingress. ## Verification - `pnpm test-dev-turbo test/development/app-dir/request-insights/request-insights.test.ts` <!-- NEXT_JS_LLM -->github.com-vercel-next.js · 491f7809 · 2026-07-16
- 0.8ETVRun Cache Components dev validation on a worker thread (#96153) This moves the dev-mode Cache Components validation renders off the dev server's main thread onto a worker thread, so rapid navigation no longer starves the event loop. The worker crosses into the app-page bundle exactly once, calling a new `ComponentMod.routeModule.runValidationInDev` entry that rebuilds the render context, work store, and request store from a serializable snapshot and runs the whole validation there, so the client prerender and the user's client components resolve the single app-page React instance rather than a second copy. A thin worker shell (`dev-validation-worker.ts`) plus a single-worker pool (`dev-validation-worker-pool.ts`) load the user bundle via `loadComponents`, install code-frame support for CLI output, and forward the validation errors back as Flight bytes; the main thread only delivers them to the overlay through `sendErrorsToBrowser`. The snapshot, the globalThis-symbol handoff, and the shared error-delivery helpers live in their own modules. The dev server installs the worker when `experimental.devValidationWorker` is not `false`, and `runDevValidationInBackground` uses it when present, falling back to the in-process path otherwise. A one-slot `SharedArrayBuffer` propagates a supersede abort into the worker so a newer navigation cancels an in-flight validation. The runtime bundle gains an `app-worker` entry for the worker with the `build/swc` boundary externalized for the code-frame native binding, and `patch-error-inspect.ts` now backs its code-frame renderer with a globalThis symbol so all copies of the module share it across the thread. The synthetic `bench/dev-validation` benchmark navigates back-to-back, so every click lands inside the validation window — the worst case for main-thread contention. Browser-observed navigation TTFB in that window, worker vs in-process: | Route | Worker (p50/p95/max) | In-process (p50/p95/max) | | ------ | -------------------- | ------------------------ | | client | 19 / 24 / 27 ms | 40 / 66 / 7762 ms | | server | 42 / 45 / 46 ms | 122 / 158 / 252 ms | | sprite | 109 / 117 / 169 ms | 196 / 208 / 299 ms | The steady-state difference is only tens of milliseconds; the effect that matters is the tail. In-process, a navigation that collides with an in-flight validation render can stall for seconds (this run peaked at ~7.8s on the client route, and the peak varies run to run) because a staged render does not yield until it finishes; off-thread the main thread stays free and that stall disappears. Read these as an upper bound, not a speedup that generalizes. The work moved off-thread is the validation render's CPU — bounded, route-dependent, and free of IO — so it does not grow with the main render's cost. In an app whose main render is dominated by IO the same absolute saving is a small fraction of the request, and it only appears when a navigation lands in the brief validation window; at ordinary click speed it is largely invisible. This is a dev-only responsiveness improvement whose benefit varies widely with the app and the navigation pattern. As a follow-up, the validation work that still runs on the main thread could move to the worker as well. When the main render can't be reused for validation (for example after a cache miss), the validation re-renders on the main thread to produce its inputs, resuming from the Resume Data Cache (RDC) the main render already filled, and only then hands the resulting Flight chunks to the worker. A later iteration could run those renders inside the worker too, transporting the (serializable) RDC so the worker can resume from the filled caches rather than reading them back on the main thread. closes NAR-895github.com-vercel-next.js · 3c4afc1a · 2026-07-25
- 0.8ETV(TypeScript 7 Support) Add experimental TypeScript CLI backend (#95639) ## Summary - add `experimental.useTypeScriptCli` so projects can explicitly run their local `tsc` during `next build`, including TypeScript 7 while the legacy JavaScript API is unavailable - preserve the TypeScript API backend as the default, with TypeScript 6-compatible dependency installation and actionable TypeScript 7 migration guidance - load effective compiler metadata through `tsc --showConfig`, preserve inherited path origins, stream native diagnostics, redirect incremental state, and forward worker termination to the compiler process tree - document the experimental behavior and cover TypeScript 6/7, both bundlers, raw diagnostics, full-project checking, dependency selection, and cleanup ## Demo ``` pnpm build > cna@0.1.0 build /Users/timneutkens/projects/sandbox/cna > next build ▲ Next.js 16.3.0-canary.81 (Turbopack) ✓ Running next.config.ts took 23ms - Cache Components enabled - Experiments (use with caution): ✓ useTypeScriptCli Creating an optimized production build ... ✓ Compiled successfully in 3.9s Running TypeScript ... app/page.tsx:8:3 - error TS2322: Type 'string' is not assignable to type 'number'. 8 return count++ + "abc"; ~~~~~~ Found 1 error in app/page.tsx:8 Failed to type check. Next.js build worker exited with code: 1 and signal: null ELIFECYCLE Command failed with exit code 1. ``` ## Verification - `pnpm test-start-turbo test/production/app-dir/typescript-cli/typescript-cli.test.ts` - `pnpm test-start-webpack test/production/app-dir/typescript-cli/typescript-cli.test.ts` - `pnpm test-start-turbo test/production/ci-missing-typescript-deps/index.test.ts` - `pnpm test-dev-turbo test/development/typescript-native-preview/index.test.ts` - `pnpm test-start-turbo test/production/typescript-basic/index.test.ts` <!-- NEXT_JS_LLM_PR -->github.com-vercel-next.js · a249dcbc · 2026-07-10
- 0.7ETVrequest insights: derive request history and fetch data (2/5) (#93975) ## What Builds the bounded request history store on top of local spans and fetch metrics. Request Insights now keeps the last 100 requests, dedupes fetch records, and preserves raw span details for later verbose consumers. Stack: 1. request insights: record local framework spans (1/5) 2. request insights: derive request history and fetch data (2/5) ← current 3. request insights: expose dev snapshots to tools and HMR (3/5) 4. request insights: add agent diagnosis access (4/5) 5. request insights: add DevTools request panel (5/5) ## Review Focus - The request insight schema shared by server, tools, and DevTools. - Fetch cache/status mapping from existing `AppRender.fetch` spans. - Dedupe between completed fetch spans and direct fetch metrics. ## Proof In This PR - `pnpm jest packages/next/src/server/lib/trace/request-insights.test.ts packages/next/src/server/lib/patch-fetch.test.ts --runInBand` - `pnpm --filter=next types` ## Deferred Coverage - Browser/HMR transport, CLI/MCP access, and the visual panel are later PRs. <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl>github.com-vercel-next.js · 510d00b5 · 2026-07-12
- 0.5ETVFix instant validation blocking navigations (#95939) ### What? - Run development instant validation only after the navigation response has finished. - Let a newer request supersede stale validation work and yield between validation render attempts. - Forward the cancellation signal into React validation prerenders so asynchronous validation work can stop promptly. - Add focused scheduler/response tests and assert that development validation starts after the response finishes. ### Why? Instant validation was detached from the response promise, but its additional React renders still ran on the same Node.js event loop. A subsequent navigation could therefore wait hundreds of milliseconds for stale diagnostic work from the previous request. Instant validation still runs when the server is idle. When another navigation arrives, foreground request work now takes priority and the obsolete validation is discarded. ### How? Each Cache Components development request receives a validation generation signal. Starting a newer request aborts the previous generation. Validation waits for the Node response `finish` event, yields through the event-loop poll phase between attempts, and combines the generation signal with React's existing prerender abort signals. Tests: - `pnpm --filter=next build` - `pnpm --filter=next types` - `pnpm exec jest --runTestsByPath packages/next/src/server/app-render/dev-validation-scheduler.test.ts packages/next/src/server/app-render/wait-for-response.test.ts` - `NEXT_SKIP_ISOLATE=1 NEXT_TEST_PREFER_OFFLINE=1 pnpm test-dev-turbo test/e2e/app-dir/instant-validation/suspense-boundaries.test.ts -t "valid - static prefetch - suspense around runtime and dynamic"` <!-- NEXT_JS_LLM_PR -->github.com-vercel-next.js · 81d0e851 · 2026-07-21
- 0.5ETVfeat(turbopack): support import.meta.env (#96225) ## Summary - add native Turbopack support for `import.meta.env.DEV`, `PROD`, `MODE`, `BASE_URL`, and `SSR` - statically analyze built-in values for dead-code elimination while exposing the complete runtime object - derive `BASE_URL` from the Next.js `basePath` and include Vite-compatible trailing-slash formatting - add TypeScript declarations, focused execution and Next.js integration coverage, and Vite migration documentation ## Verification - `cargo fmt --all -- --check` - `cargo nextest run -p turbopack-tests -E 'test(import_meta_env)'` - `pnpm build-all` - `pnpm --filter=next types` - `NEXT_TEST_PREFER_OFFLINE=1 pnpm test-dev-turbo test/e2e/import-meta-env/import-meta-env.test.ts` - `NEXT_TEST_PREFER_OFFLINE=1 pnpm test-start-turbo test/e2e/import-meta-env/import-meta-env.test.ts` <!-- NEXT_JS_LLM -->github.com-vercel-next.js · c23d1a94 · 2026-07-28
- 0.4ETVClassify Instant Insights as internal in Request Insights (#96147) ## Summary - Classifies Instant Insights records as internal and hides them by default. - Adds a persisted “Internal activity” toggle. - Nests internal records below their matching foreground request. - Preserves orphaned internal records exactly once. - Signals hidden internal errors without littering the main request list. - Raw endpoint and CLI data remain complete; filtering is UI-only. ## Verification ```bash pnpm build-all pnpm --filter=next types pnpm --filter=next build pnpm test-unit --runTestsByPath packages/next/src/next-devtools/dev-overlay/components/request-insights/trace-viewer.test.ts pnpm test-dev-turbo test/development/app-dir/request-insights/request-insights.test.ts pnpm test-dev-webpack test/development/app-dir/request-insights/request-insights.test.ts ``` <!-- NEXT_JS_LLM -->github.com-vercel-next.js · 925edc3d · 2026-07-28