DEV Community

Cover image for NextJs Codebase Analysis (2) - manifests
Jade Chou
Jade Chou

Posted on

NextJs Codebase Analysis (2) - manifests

Terminology

  • App Router → New routing system using /app (Next.js 13+)
  • Pages Router → Legacy routing using /pages
  • SSRServer-Side Rendering
  • SSGStatic Site Generation
  • ISRIncremental Static Regeneration
  • CSRClient-Side Rendering
  • RSCReact Server Components
  • SPASingle Page Application

What's the function of these manifest?

Next.js manifest files are runtime metadata maps generated at build time.

They tell Next.js exactly which files, module IDs, and extra metadata belong to each page or component. This allows the runtime to quickly resolve dependencies without re-scanning the project source during execution.

More specifically, these manifests allow the server and client runtimes to locate:

  • Correct JS/CSS chunks
  • RSC (React Server Components) client references
  • SRI hashes
  • Server Action metadata
  • Page/component dependency mappings

In short: manifests act as lookup tables that power the Next.js runtime.

They ensure that the framework can efficiently load the correct resources for a given request.


Take app-paths-manifest.json for example.

It is typically located at:

.next/dev/server
Enter fullscreen mode Exit fullscreen mode

This file maps application routes to their compiled output files, effectively describing:

  • Which paths exist in the application
  • Which compiled chunks belong to each path

So when a request arrives, Next.js doesn't need to discover routes dynamically — it simply consults this manifest.


Why do some manifests contain encryption keys?

If we inspect server-reference-manifest.json, we can see that it includes an encryptionKey field.

Let's examine a real manifest entry to better understand this.

In this example, I created a Server Action inside my DemoActionPage.

When Next.js compiles the project:

  • The page is registered as a node inside server-reference-manifest
  • Any exported server actions are recorded
  • Each action is assigned a stable identifier

Important: server-reference-manifest is generated by

packages\next\src\build\webpack\plugins\flight-client-entry-plugin.ts


How Server Actions are linked to the client

When the server sends HTML to the browser, Server Actions are embedded into the markup using a hidden action binding.

Each action is associated with a unique action ID, which corresponds exactly to the key stored in server-reference-manifest.json.


How Server Action encryption works

The encryption logic used for Server Actions actually comes from React itself.

You can see the implementation here:

https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-client/src/ReactFlightReplyClient.js#L1026

Every time a Server Action is invoked from the client:

  1. The browser sends a POST request containing the action payload.
  2. The payload includes encrypted action metadata and bound variables.
  3. The Next.js server validates and decrypts the payload before executing the action.

This validation happens inside:

packages\next\src\server\app-render\action-handler.ts
Enter fullscreen mode Exit fullscreen mode

The server checks the request against its local manifest map, ensuring that the action ID is valid.

This mechanism prevents action tampering or unauthorized invocation.


How the encryption key protects server variables

The Next.js documentation mentions that the encryption key is used to protect closure variables from being exposed to the client.

Let's reproduce this behavior locally to better understand it.

When a user clicks the element that triggers the Server Action:

  1. A request is sent to the Next.js server
  2. The request payload includes multiple encrypted parameters

These parameters originate from closure variables captured by the Server Action.

The lifecycle looks like this:

  1. Variables are generated on the server
  2. They are encrypted before being sent to the client
  3. The client later invokes the action
  4. The encrypted values are sent back to the server inside the request payload

What happens on the server during execution

If we inspect the compiled server bundle, we can see that Server Actions are transformed into a function wrapper.

This wrapper contains the same encryption key used during compilation.

During execution, the runtime calls:

decryptActionBoundArgs
Enter fullscreen mode Exit fullscreen mode

This function:

  • Uses the encryption key
  • Uses action_closure_bound data
  • Decrypts the original closure variables

After decryption, the real variable values are restored and the action is executed normally.

Because the action runs on the server, any logging will appear in the server terminal rather than the browser console.


Key takeaway

Next.js Server Action encryption exists to guarantee two things:

  1. Action integrity — preventing clients from forging or modifying action calls
  2. Closure protection — ensuring server-side variables captured by actions are never exposed in plaintext

Top comments (0)