Skip to main content
Frameworks

Next.js on Easel

Deploy App Router and Pages Router applications to Easel with support for server rendering, streaming, Server Actions, route handlers, middleware, image optimization, and framework-native caching.

At a glance

Support levelProduction-ready
RoutersApp Router and Pages Router
RenderingStatic, SSR, streaming, ISR, and Partial Prerendering
Server runtimeNode.js
Adapter requiredNo
Automatic detectionYes
Most recently tested withNext.js 16.2.x

Deploy a Next.js application

Easel detects Next.js projects automatically. In most cases, an existing application can be deployed without changing its framework configuration.

Create a project and connect the project’s Git repository, or deploy with the CLI:

easel deploy

Easel detects the package manager, installs dependencies, runs the Next.js production build, and provisions the infrastructure required by the build output.

The default build command is:

next build

You can override the install command, build command, root directory, Node.js version, and environment variables in your project settings.

Why run Next.js on Easel?

Easel provides a Vercel-compatible deployment path while keeping the underlying infrastructure visible and portable.

A Next.js deployment includes:

  • Immutable static assets served through the Easel CDN
  • Regional functions for dynamic rendering and server-side code
  • Distributed storage for the Next.js route and data caches
  • Path-based and tag-based cache revalidation
  • Image optimization for next/image
  • Preview deployments for every branch and pull request
  • Built-in logs, metrics, traces, WAF, and attack protection

You can inspect function execution, cache behavior, request routing, and resource usage from the Easel dashboard.

What Easel deploys

Easel analyzes the Next.js build output and maps each part of the application to the appropriate platform resource.

Next.js outputEasel resource
Static pagesCDN assets
JavaScript, CSS, fonts, and other static filesCDN assets
Server Components and SSR routesEasel Functions
Route Handlers and API RoutesEasel Functions
Server ActionsEasel Functions
MiddlewareEdge request pipeline
ISR and cached route outputRuntime Cache and CDN
next/image requestsImage optimization service
OpenTelemetry instrumentationEasel observability pipeline

Static assets are deployed immutably and can remain available across deployments. Dynamic application code runs in functions and scales independently from the CDN.

Supported features

FeatureSupportNotes
App RouterSupportedIncludes layouts, Server Components, loading states, and error boundaries
Pages RouterSupportedIncludes pages, API Routes, and data-fetching methods
Static Site GenerationSupportedGenerated pages are deployed to the CDN
Server-Side RenderingSupportedDynamic routes run in Easel Functions
React Server ComponentsSupportedSupported through the App Router
StreamingSupportedDynamic responses are streamed without waiting for the complete render
Server ActionsSupportedExecuted by the application’s server function
Route HandlersSupportedIncludes standard and streaming responses
API RoutesSupportedPages Router API Routes run in functions
Incremental Static RegenerationSupportedIncludes time-based and on-demand revalidation
Cache ComponentsSupportedBacked by Easel’s distributed Runtime Cache
Partial PrerenderingSupportedStatic shells and dynamic regions are deployed together
revalidatePathSupportedInvalidates matching route-cache entries
revalidateTagSupportedInvalidates data by cache tag
updateTagSupportedExpires tagged data for read-your-own-writes behavior
after()SupportedWork may continue after the response within the function duration limit
MiddlewareSupportedRuns in Easel’s request pipeline before the application route
Node.js runtimeSupportedUsed for server-rendered routes and server code
Edge runtime APIsSupportedAPI compatibility does not imply execution at every CDN location
next/imageSupportedRequests use Easel’s image optimization service
Redirects, rewrites, and headersSupportedIncludes rules defined in next.config
Internationalized routingSupportedIncludes domain and subpath routing
Draft ModeSupportedPreview cookies are forwarded to the application runtime
OpenTelemetrySupportedFramework telemetry can be exported through Easel
Turbopack buildsSupportedUsed when enabled by the selected Next.js version
Static exportSupportedDeploys the exported application as a static site
WebSocketsNot supportedFunction requests must use HTTP request-response semantics

Experimental Next.js features may require additional platform work when their deployment contract changes. Test experimental features in a preview deployment before promoting them to production.

Rendering

Static rendering

Routes generated during next build are deployed as immutable CDN assets. Requests for these routes do not invoke a function unless Next.js requires runtime revalidation or dynamic behavior.

This includes:

  • App Router routes rendered statically
  • Pages Router routes using getStaticProps
  • Dynamic routes generated with generateStaticParams
  • Fully static metadata and assets

Server rendering

Routes that require request-time data run in Easel Functions.

This includes routes that use request APIs such as:

await cookies()
await headers()

It also includes Pages Router routes using getServerSideProps, dynamic Route Handlers, API Routes, and uncached server-side data access.

Server Components and streaming responses run through Easel’s Next.js production runtime. Response chunks are forwarded as they are produced rather than buffered until rendering finishes.

Partial Prerendering

Partial Prerendering combines a static application shell with dynamic content behind Suspense boundaries.

Easel deploys the generated static shell to its caching layer and retains the postponed rendering state required by Next.js. On a request, Easel can begin returning the shell while the application function resumes and streams the dynamic portions of the route.

The shell and its corresponding rendering state are updated together when the route is revalidated.

Caching and revalidation

Easel provides shared cache storage for Next.js applications running across multiple function instances.

The integration supports:

  • Full Route Cache
  • Data Cache
  • Cache Components
  • Time-based revalidation
  • Path-based revalidation
  • Tag-based revalidation
  • Background cache regeneration

Cached data is not limited to the local filesystem of a single function instance.

See Store and expire data in Runtime Cache and Invalidate and revalidate cached content.

Time-based revalidation

Use the standard Next.js APIs:

const products = await fetch("https://api.example.com/products", {
  next: {
    revalidate: 300,
  },
});

The cached response can be reused for five minutes before Next.js regenerates it.

You can also configure a route-level revalidation interval:

export const revalidate = 300;

Tag-based revalidation

Attach tags to cached data:

const products = await fetch("https://api.example.com/products", {
  next: {
    tags: ["products"],
  },
});

Invalidate the data from a Server Action or Route Handler:

import { revalidateTag } from "next/cache";

export async function POST() {
  revalidateTag("products");

  return Response.json({
    revalidated: true,
  });
}

Easel coordinates invalidation across active CDN and function instances.

Path-based revalidation

Invalidate a route with revalidatePath:

"use server";

import { revalidatePath } from "next/cache";

export async function updateProduct() {
  await saveProduct();

  revalidatePath("/products");
}

Work after the response

Next.js supports scheduling work with after():

import { after } from "next/server";

export async function POST(request: Request) {
  const event = await request.json();

  after(async () => {
    await recordAnalyticsEvent(event);
  });

  return Response.json({
    accepted: true,
  });
}

Easel keeps the invocation active while registered work is running.

The response can be returned before that work finishes, but the invocation continues consuming function duration until the work completes or the route reaches its maximum duration. Use a durable background-work system for jobs that must survive function termination, require retries, or may exceed the request’s execution limit.

Middleware

Next.js middleware runs in Easel’s edge request pipeline before the matching application route.

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  if (!request.cookies.has("session")) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*"],
};

Middleware can perform rewrites, redirects, authentication checks, header changes, and other request-routing logic.

Middleware compatibility describes the Next.js runtime APIs available to your code. It does not mean that every middleware request executes inside every CDN point of presence. See Functions for execution-location details.

Image optimization

The Next.js <Image> component works without additional configuration:

import Image from "next/image";

export default function Page() {
  return (
    <Image
      src="/mountains.jpg"
      alt="Mountains"
      width={1200}
      height={800}
    />
  );
}

Image transformation requests are handled by Easel’s image optimization service and cached through the CDN.

For remote images, configure the allowed sources in next.config.ts:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "images.example.com",
      },
    ],
  },
};

export default nextConfig;

Environment variables

Configure environment variables in the Easel dashboard or CLI.

Variables without a NEXT_PUBLIC_ prefix are available only during the build and in server-side code:

const databaseUrl = process.env.DATABASE_URL;

Variables prefixed with NEXT_PUBLIC_ can be included in browser bundles:

const apiOrigin = process.env.NEXT_PUBLIC_API_ORIGIN;

Public variables are embedded during the build. Changing one requires a new deployment.

Use separate values for production, preview, and development environments when a variable differs between deployment contexts.

OpenTelemetry

Next.js instrumentation hooks can export telemetry through Easel’s observability pipeline.

Create instrumentation.ts in the project root or src directory:

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    await import("./instrumentation.node");
  }
}

Use standard OpenTelemetry SDKs and instrumentation packages inside your Node.js registration module. Easel can collect application traces alongside request logs, function metrics, and platform spans.

See OpenTelemetry for how Easel collects application spans into request Traces.

Project configuration

Easel detects the conventional Next.js settings automatically:

SettingDefault
Install commandDetected from the package manager
Build commandPackage script or next build
Output directoryDetected from the Next.js build
Development commandPackage script or next dev
Node.js versionProject or platform default

For monorepos, set the project root to the directory containing the Next.js application’s package.json.

Do not set output: "export" unless the application is intentionally static. Easel supports the standard Next.js server output and deploys its dynamic routes automatically.

Route duration

Set per-route maximum duration with Next.js route segment config:

export const maxDuration = 60;

Easel reads maxDuration from the build output. The default is 30s when unset. The maximum is 800s. See Function limits.

Local development

Continue using the framework’s normal development server:

npm run dev

This provides the fastest development loop for framework behavior.

Use Easel preview deployments to validate platform-specific behavior, including:

  • Production builds
  • Function execution
  • Middleware routing
  • Distributed caching
  • Image optimization
  • Environment variables
  • Function duration and resource limits
  • WAF and security rules

A preview deployment uses the same deployment path as production and receives its own immutable URL.

Known limitations

WebSockets

Next.js routes deployed to Easel Functions cannot accept long-lived WebSocket connections. Use an external WebSocket service or a dedicated persistent service for bidirectional connections.

Standard streaming HTTP responses and Server-Sent Events remain separate from WebSockets and can be supported within function execution limits.

Local filesystem

Function filesystems are ephemeral. Files written during an invocation are not guaranteed to exist in later invocations or on another instance.

Use object storage, a database, or another durable service for persistent application data.

Experimental features

Next.js experimental APIs can change without preserving their deployment contracts. A feature available in the framework may require an Easel runtime or adapter update before all of its semantics are supported.

The compatibility table reflects the most recently verified stable framework release.

Troubleshooting

The project deploys as a static site

Confirm that the application is running next build and that output: "export" is not set in next.config unless you intend to create a fully static deployment.

A server environment variable is undefined

Confirm that the variable is configured for the current deployment environment. Preview and production deployments can use different values.

Variables added after a build require a new deployment.

A public environment variable has the old value

Variables beginning with NEXT_PUBLIC_ are embedded into the browser bundle during the build. Redeploy the application after changing them.

A remote image is rejected

Add the image host to images.remotePatterns in next.config.

Cached content does not update

Confirm that the cached request or function has the expected path, tag, or revalidation interval. Also verify that the invalidation call runs successfully before the response completes.

Code works locally but fails in production

Run a preview deployment and inspect the build output and function logs. Production builds can expose differences involving environment variables, case-sensitive paths, native dependencies, dynamic route behavior, and access to the local filesystem.

Compatibility policy

Easel tests its Next.js integration against representative applications covering the App Router, Pages Router, server rendering, Server Components, Server Actions, streaming, middleware, caching, revalidation, images, and route handlers.

Stable Next.js releases may work beyond the version listed at the top of this page, but the listed version is the most recently verified baseline.

For an experimental Next.js feature or a newly released framework version, deploy a preview before upgrading the production application.

Next steps