Next.js App Router Transition
bundles ranks #2 in git co-change but #12 in the import graph. The infrastructure layer is more behaviorally active than the declared architecture suggests. The App Router transition introduced no hub shadow — the rewrite was clean.
What was measured
25 modules from the vercel/next.js monorepo. Three layers over the App Router transition window (2022–2025). 23,444 commits extracted from the public git history.
import_graphStatic TypeScript import/require edges between packages. Captures declared architecture — what each module explicitly depends on.
test_couplingModules that appear together in the same test files. A module heavily tested alongside another is structurally coupled to it in the test suite — independent of runtime import structure.
co_changeFiles modified together in the same commit, extracted from 23,444 commits. Language-agnostic. Captures actual developer coupling — what engineers touch together when making changes.
Cross-layer hub correlation
Strongest gradient to date across all OSS experiments: Δr = 0.35 between the structural pair and the behavioral pair.
import_graph ↔ test_couplingCONFIRMEDStrong agreement: modules that are structurally central in the import graph are also heavily tested together. The declared and derived structural pictures agree.
import_graph ↔ co_changepartialModerate correlation — most structural hubs are also behaviorally active, but the bundle/infrastructure modules diverge.
test_coupling ↔ co_changebaselineLow correlation. Being heavily tested does not mean being heavily co-changed. Test infrastructure is insulated from day-to-day behavioral coupling.
The infrastructure chameleon
bundles is mid-tier in the import graph (#12) and test coupling (#8) but ranks #2 in git co-change. It shows a different structural face depending on which layer you look at.
The bundler infrastructure is touched in almost every significant commit — it's the plumbing that every App Router feature passes through. But it doesn't import much and isn't co-tested heavily because its interface is stable. High behavioral centrality, low declared centrality. The opposite of a hub shadow: high co_change rank, low import rank.
The App Router rewrite was clean
Pre-registered hypothesis h3 predicted that server_app_render — the new App Router rendering module — would be a hub in co_change as teams migrated to it. It ranked #15. The prediction was wrong. The meaning is positive.
server_app_render co_change rank: #15. Predicted: ≤ #5. Top hub: build.
Mechanism: clean abstraction boundary. The App Router was built as a properly isolated module. When you introduce a new rendering path without co-modifying a large set of adjacent modules, IRDME sees low behavioral centrality — because the abstraction is working as intended. A hub shadow in a new module would have been the warning sign. Its absence is the confirmation. IRDME doesn't just find problems — it confirms when architecture is sound.
What this means
- ·r = 0.8995 between import structure and test coupling means the two independent structural layers agree on what's important. That's a signal the architecture is coherent — not a coincidence.
- ·
bundlesas a chameleon means: don't assess infrastructure coupling from the import graph alone. Its real risk is in co_change — it's touched in nearly every feature commit. - ·The clean
server_app_renderresult is the metric a rewrite team wants to see: new modules with low co_change rank confirm the abstraction boundary held.
The import graph is what your linter and bundler see. The test coupling layer is what your CI pipeline sees. They agree at r = 0.8995 — near-perfect correlation.
That agreement means: if a module becomes a hub in one structural view, it's almost certainly a hub in the other. The test suite is an independent validation of the architecture — and for Next.js, it validates. This is the Functional Proximity Law confirming a well-engineered codebase.
The same analysis runs on any monorepo with a TypeScript import graph and a public git history. Extraction time for 25 modules / 23k commits: under 5 minutes via irdme extract.
Hub ranking by layer
Selected modules. Rank = degree centrality position within each layer.
| module | import_graph | test_coupling | co_change | archetype |
|---|---|---|---|---|
build | #2 | #1 | #1 | universal_hub |
server_base | #1 | #2 | #11 | relay |
lib | #3 | #4 | #9 | relay |
shared | #4 | #3 | #12 | relay |
client | #5 | #5 | #4 | universal_hub |
bundles | #12 | #8 | #2 | chameleon |
cli | #9 | #9 | #3 | relay |
experimental | #13 | #6 | #5 | relay |
telemetry | #14 | #11 | #6 | chameleon |
server_app_render | #7 | #7 | #15 | relay |
10 selected rows. All 25 modules in the raw output file.
Pre-registered hypotheses
r(import_graph ↔ test_coupling) > r(import_graph ↔ co_change)
0.8995 > 0.5484 · Δr = 0.35
r(import_graph ↔ test_coupling) > 0.4, p < 0.05
Pearson r = 0.8995 · Spearman r = 0.7027 · p = 0.002 · effect_size = large
server_app_render ranks ≤ 5 in co_change (App Router migration hub)
rank #15. Top hub: build. Mechanism: clean abstraction — the rewrite was properly isolated.
lib ranks ≤ 2 in import_graph
rank #3. Top hub: server_base. Off-by-one — the utility library is the third hub, not the second.
Coherence score at or above 50th null percentile
31.2th percentile. Mechanism: power-law degree distributions inflate null coherence, making coherence non-discriminative for large skewed graphs.
Reproduce
Pre-registration hash cb0cf4a4… committed to github.com/vladi160/preregistrations before analysis ran.
Related case studies
post.php as a hub shadow. r = 0.5156, p = 0.012. 23,000+ commits.
PVCL/PVCR confirmed as primary command interneurons. r = 0.7774, p = 0.004.
Transformer confirmed as #1 structural hub from topology alone. r = 0.9147.