Public evidence: generated by OpenThunder’s keyless engine (no AI) from vercel/next.js@4dea35d on 2026-07-21. Reproduce it: openthunder lens generate --no-narrate && openthunder lens export. ← Evidence Gallery

next.js: Architecture

next.js · 4dea35dbd218 · generated 2026-07-21T00:12:44.625Z · static analysis

Architecture health: 30/100 (F)

Overview

next.js is a JavaScript/TypeScript pnpm monorepo, built with React, Next.js, and Express. It runs as 88 frontends (bundle-analyzer-ui, bench-app-router-server, module-cost, bench-nested-deps, bench-nested-deps-app-router, nested-deps-app-router-many-pages, agent-000-app-router-migration-simple, agent-021-avoid-fetch-in-effect, agent-022-prefer-server-actions, agent-023-avoid-getserversideprops, agent-024-avoid-redundant-usestate, agent-025-prefer-next-link, agent-026-no-serial-await, agent-027-prefer-next-image, agent-028-prefer-next-font, agent-029-use-cache-directive, agent-030-app-router-migration-hard, agent-031-proxy-middleware, agent-032-use-cache-directive, agent-033-forbidden-auth, agent-034-async-cookies, agent-035-connection-dynamic, agent-036-after-response, agent-037-updatetag-cache, agent-038-refresh-settings, agent-039-indirect-proxy, agent-040-instant, agent-041-optimize-ppr-shell, agent-042-enable-ppr, agent-043-view-transitions, active-class-name, api-routes-apollo-server, api-routes-apollo-server-and-client, api-routes-apollo-server-and-client-auth, api-routes-cors, api-routes-graphql, api-routes-middleware, api-routes-rest, auth, auth0, basic-css, blog, blog-starter, blog-with-comment, cache-handler-redis, cloudflare-turnstile, cms-agilitycms, cms-builder-io, cms-buttercms, cms-contentful, cms-cosmic, cms-datocms, cms-dotcms, cms-drupal, cms-enterspeed, cms-ghost, cms-graphcms, cms-kontent-ai, cms-makeswift, cms-payload, cms-plasmic, cms-prepr, cms-prismic, cms-sanity, cms-sitecore-xmcloud, cms-sitefinity, cms-storyblok, cms-takeshape, cms-tina, cms-umbraco, cms-umbraco-heartcore, cms-webiny, cms-wordpress, convex, custom-server, github-pages, hello-world, i18n-routing, i18n-routing-pages, image-component, image-secure-compute, inngest, markdoc, mdx, mdx-pages, next-forms, panda-css, prisma-postgres), backed by 2 shared packages. It stores data in PostgreSQL, Prisma, and Redis, calls OpenAI and Vercel AI SDK across an explicit AI provider boundary, and integrates with AWS S3, GitHub, and Vercel Blob. The main structural risks to watch: 15 oversized "god" files and 5 circular import chains. The file with the widest blast radius is bench/basic-app/app/ui/vendor-bulk.js: 24 files depend on it at runtime.

_This entire analysis runs on your machine with no AI required. Connect a model provider to also narrate the reasoning and recover decisions._

Where to start

  1. apps/bundle-analyzer/ Start here: the primary entry point of the system.
  2. bench/basic-app/app/ui/vendor-bulk.js Core module: 24 other modules depend on it, so it shapes much of the system.
  3. packages/eslint-plugin-next/src/utils/define-rule.ts Core module: 22 other modules depend on it, so it shapes much of the system.
  4. packages/next/src/bundles/webpack/packages/webpack.js Core module: 19 other modules depend on it, so it shapes much of the system.
  5. packages/next/src/client/components/router-reducer/router-reducer-types.ts Core module: 16 other modules depend on it, so it shapes much of the system.
  6. examples/with-sfcc/sfcc.js Key flow: Authentication, a high-risk path that enters at invoke sfcc.js (examples/with-sfcc/sfcc.js).
  7. bench/render-pipeline/analyze-profiles.ts Key flow: Mission execution, a high-risk path that enters at invoke analyze-profiles.ts (bench/render-pipeline/analyze-profiles.ts).
  8. examples/with-fela/FelaProvider.js Key flow: AI provider call, a high-risk path that enters at invoke FelaProvider.js (examples/with-fela/FelaProvider.js).
  9. bench/recursive-delete/nodejs-rm.js Key flow: File changes / writes, a high-risk path that enters at invoke nodejs-rm.js (bench/recursive-delete/nodejs-rm.js).

System map

flowchart TD
  subgraph sys_boundary["next.js"]
    bundle_analyzer_ui["bundle-analyzer-ui"]
    blog_with_comment["blog-with-comment"]
    cms_payload["cms-payload"]
    prisma_postgres["prisma-postgres"]
    store_prisma[("Prisma")]
    store_redis[("Redis")]
    collapsed_units["87 more units, no cross-unit imports: bench-app-router-server, module-cost, bench-nested-deps +84"]
  end
  subgraph ai_boundary["AI Provider Boundary"]
    ai_openai{{"OpenAI"}}
    ai_vercel_ai_sdk{{"Vercel AI SDK"}}
  end
  ext_aws_s3{{"AWS S3"}}
  ext_github{{"GitHub"}}
  ext_vercel_blob{{"Vercel Blob"}}
  prisma_postgres -->|reads / writes| store_prisma
  blog_with_comment -->|reads / writes| store_redis
  bundle_analyzer_ui -->|LLM calls| ai_vercel_ai_sdk
  cms_payload -->|API calls| ext_aws_s3
  class bundle_analyzer_ui frontend
  class blog_with_comment frontend
  class cms_payload frontend
  class prisma_postgres frontend
  class store_prisma store
  class store_redis store
  class ai_openai aiprovider
  class ai_vercel_ai_sdk aiprovider
  class ext_aws_s3 external
  class ext_github external
  class ext_vercel_blob external
  class collapsed_units muted
  %% collapsed (no cross-unit imports): bench-app-router-server, module-cost, bench-nested-deps, bench-nested-deps-app-router, nested-deps-app-router-many-pages, bench-rendering, stats-app, agent-000-app-router-migration-simple, agent-021-avoid-fetch-in-effect, agent-022-prefer-server-actions, agent-023-avoid-getserversideprops, agent-024-avoid-redundant-usestate, agent-025-prefer-next-link, agent-026-no-serial-await, agent-027-prefer-next-image, agent-028-prefer-next-font, agent-029-use-cache-directive, agent-030-app-router-migration-hard, agent-031-proxy-middleware, agent-032-use-cache-directive, agent-033-forbidden-auth, agent-034-async-cookies, agent-035-connection-dynamic, agent-036-after-response, agent-037-updatetag-cache, agent-038-refresh-settings, agent-039-indirect-proxy, agent-040-instant, agent-041-optimize-ppr-shell, agent-042-enable-ppr, agent-043-view-transitions, active-class-name, api-routes-apollo-server, api-routes-apollo-server-and-client, api-routes-apollo-server-and-client-auth, api-routes-cors, api-routes-graphql, api-routes-middleware, api-routes-rest, auth, auth0, basic-css, blog, blog-starter, cache-handler-redis, cloudflare-turnstile, cms-agilitycms, cms-builder-io, cms-buttercms, cms-contentful, cms-cosmic, cms-datocms, cms-dotcms, cms-drupal, cms-enterspeed, cms-ghost, cms-graphcms, cms-kontent-ai, cms-makeswift, cms-plasmic, cms-prepr, cms-prismic, cms-sanity, cms-sitecore-xmcloud, cms-sitefinity, cms-storyblok, cms-takeshape, cms-tina, cms-umbraco, cms-umbraco-heartcore, cms-webiny, cms-wordpress, convex, custom-server, github-pages, hello-world, i18n-routing, i18n-routing-pages, image-component, image-secure-compute, inngest, markdoc, mdx, mdx-pages, next-forms, panda-css, PostgreSQL
  classDef frontend fill:#2563eb,stroke:#93c5fd,color:#fff,stroke-width:2px;
  classDef service fill:#059669,stroke:#6ee7b7,color:#fff,stroke-width:2px;
  classDef store fill:#d97706,stroke:#fcd34d,color:#fff,stroke-width:2px;
  classDef queue fill:#9333ea,stroke:#d8b4fe,color:#fff,stroke-width:2px;
  classDef job fill:#4f46e5,stroke:#a5b4fc,color:#fff,stroke-width:2px;
  classDef external fill:#475569,stroke:#cbd5e1,color:#fff,stroke-width:2px;
  classDef aiprovider fill:#e11d48,stroke:#fda4af,color:#fff,stroke-width:2px;
  classDef library fill:#0891b2,stroke:#67e8f9,color:#fff,stroke-width:2px;
  classDef cli fill:#0d9488,stroke:#5eead4,color:#fff,stroke-width:2px;
  classDef user fill:#64748b,stroke:#e2e8f0,color:#fff,stroke-width:2px;
  classDef muted fill:#334155,stroke:#64748b,color:#cbd5e1,stroke-width:1px;

Critical flows

Authentication high risk

Entry: invoke sfcc.js (examples/with-sfcc/sfcc.js)

returns a response to the caller (client)

Authentication guards every protected resource; a regression here can expose data or grant unauthorized access.

sequenceDiagram
  actor C0 as Caller
  participant F0 as sfcc.js
  participant F1 as tokenize.js
  participant F2 as api-token.js
  participant F3 as vendor-auth.js
  participant F4 as route.ts
  participant F5 as uploadToken.ts
  C0->>F0: invoke sfcc.js
  F5-->>C0: returns a response to the caller

Mission execution high risk

Entry: invoke analyze-profiles.ts (bench/render-pipeline/analyze-profiles.ts)

writes files to the working tree (disk); calls an external service (external API)

Mission execution drives autonomous code changes; errors here corrupt runs or the target repository.

sequenceDiagram
  actor C0 as Caller
  participant F0 as analyze-profiles.ts
  participant F1 as benchmark.ts
  participant F2 as LatestMissionName.tsx
  participant F3 as workflows.ts
  participant F4 as test-runner.ts
  participant Disk as disk
  participant External as external API
  C0->>F0: invoke analyze-profiles.ts
  F1->>Disk: writes files to the working tree
  F1->>External: calls an external service

AI provider call high risk

Entry: invoke FelaProvider.js (examples/with-fela/FelaProvider.js)

Provider calls cost money and shape model output; mistakes leak prompts, burn budget, or route to the wrong model.

sequenceDiagram
  actor C0 as Caller
  participant F0 as FelaProvider.js
  participant F1 as analytics-provider.js
  participant F2 as theme-provider.js
  participant F3 as ably-client-provider.tsx
  participant F4 as ApolloClientProvider.tsx
  participant F5 as InMemoryCache.tsx
  C0->>F0: invoke FelaProvider.js

File changes / writes high risk

Entry: invoke nodejs-rm.js (bench/recursive-delete/nodejs-rm.js)

writes files to the working tree (disk); calls an external service (external API); returns a response to the caller (client)

Direct writes to the working tree are hard to reverse; an unguarded write can clobber user code.

sequenceDiagram
  actor C0 as Caller
  participant F0 as nodejs-rm.js
  participant F1 as index.ts
  participant F2 as constants.js
  participant F3 as index.js
  participant F4 as collect-diffs.js
  participant F5 as collect-stats.js
  participant Disk as disk
  participant External as external API
  C0->>F0: invoke nodejs-rm.js
  F0->>Disk: writes files to the working tree
  F1->>Disk: writes files to the working tree
  F1->>External: calls an external service
  F1-->>C0: returns a response to the caller
  F2->>Disk: writes files to the working tree
  F3->>Disk: writes files to the working tree
  F5->>Disk: writes files to the working tree
  F5->>External: calls an external service
  F5-->>C0: returns a response to the caller

Billing high risk

Entry: invoke layout.tsx (examples/with-stripe-typescript/app/layout.tsx)

calls an external service (external API)

Billing touches money and the ledger; errors here are financially material and may be irreversible.

sequenceDiagram
  actor C0 as Caller
  participant F0 as layout.tsx
  participant F1 as billing-meter.js
  participant F2 as stripe.ts
  participant F3 as route.ts
  participant F4 as CheckoutForm.tsx
  participant F5 as CustomDonationInput.tsx
  participant External as external API
  C0->>F0: invoke layout.tsx
  F2->>External: calls an external service
  F3->>External: calls an external service
  F4->>External: calls an external service

Background jobs high risk

Entry: scheduled trigger (examples/with-apollo/next.config.mjs)

Background jobs run unattended; failures are silent and can pile up unnoticed. It also passes through a fragile zone (page.js), widening the blast radius.

sequenceDiagram
  actor C0 as Scheduler
  participant F0 as next.config.mjs
  participant F1 as page.js
  participant F2 as data.js
  participant F3 as Clock.js
  participant F4 as Counter.js
  participant F5 as ErrorMessage.js
  C0->>F0: scheduled trigger

Fragile zones

Architecture rules

blocking Route all AI provider calls through a single provider abstraction; do not scatter direct SDK calls (OpenAI, Vercel AI SDK) across feature modules.

A single provider boundary keeps the system model-agnostic, makes routing/failover/cost-tracking possible, and is the core differentiator of this product.

blocking Change bench/basic-app/app/ui/vendor-bulk.js with care: 24 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 24, fan-out 0, risk score 48); a careless edit ripples through many dependents.

blocking Change packages/eslint-plugin-next/src/utils/define-rule.ts with care: 22 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 22, fan-out 0, risk score 44); a careless edit ripples through many dependents.

blocking Change packages/next/src/bundles/webpack/packages/webpack.js with care: 19 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 19, fan-out 0, risk score 38); a careless edit ripples through many dependents.

blocking Change packages/next/src/client/components/segment-cache/cache.ts with care: 10 files depend on it at runtime; part of an import cycle; oversized and doing too much. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 13, fan-out 19, risk score 36.8); a careless edit ripples through many dependents.

blocking Change packages/next/src/client/components/router-reducer/ppr-navigations.ts with care: 10 files depend on it at runtime; part of an import cycle; oversized and doing too much. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 11, fan-out 16, risk score 33.8); a careless edit ripples through many dependents.

blocking Change packages/eslint-config-next/src/core-web-vitals.ts with care: 16 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 16, fan-out 2, risk score 32.5); a careless edit ripples through many dependents.

warning Do not add imports that deepen existing import cycles (e.g. packages/next/src/client/components/links.ts → packages/next/src/client/components/segment-cache/scheduler.ts → packages/next/src/client/components/segment-cache/cache.ts → …). Break cycles when you touch the files involved.

Circular dependencies make modules impossible to reason about or test in isolation and cause load-order bugs.

advisory Do not add new responsibilities to oversized files (packages/next/src/client/components/segment-cache/cache.ts, bench/basic-app/app/dashboard/page.js, packages/next/src/client/components/router-reducer/ppr-navigations.ts, packages/next/src/client/components/segment-cache/scheduler.ts, packages/next/src/client/components/segment-cache/navigation.ts); extract new logic into focused modules instead.

Large multi-purpose files are change magnets that accumulate coupling and resist testing; keeping them from growing limits the damage.

warning Respect package boundaries: import across packages via their published entry (e.g. the package name), not deep relative paths reaching into another package's internals.

Deep cross-package imports defeat the module boundary, make refactors brittle, and create hidden coupling the build graph cannot see.