---
title: "Server-Side Rendering"
section: "frontend"
platforms: ["angular", "javascript", "nextjs", "react", "react-native", "vue"]
gen: 2
last-updated: "2026-03-25T17:40:00.000Z"
url: "https://docs.amplify.aws/react/frontend/server-side-rendering/"
---

This guide walks through how to use Amplify Auth and Data APIs from Next.js server-side runtimes.

<!-- Platform: nextjs, javascript -->
Before you begin:

- [Follow the Next.js App Router tutorial](/[platform]/frontend/server-side-rendering/nextjs-app-router-server-components)
<!-- /Platform -->

## Install the Amplify Next.js adapter

> **Warning:** **Note:** Amplify JS v6 supports Next.js with the version range: `>=13.5.0 <16.0.0`.
> Ensure you have the correct version to integrate with Amplify.

To use Amplify APIs server-side, you need to install the Amplify Next.js adapter in addition to the Amplify libraries:

```bash title="Terminal" showLineNumbers={false}
npm add aws-amplify @aws-amplify/adapter-nextjs
```

## Configure Amplify in Next.js

#### [Configure Amplify for server-side usage]

You will need to create a `runWithAmplifyServerContext` function to use Amplify APIs on the server-side of your Next.js app.

You can create an `amplifyServerUtils.ts` file under a `utils` folder in your codebase. In this file, you will import the Amplify backend outputs from the `amplify_outputs.json` file that is generated by the Amplify CLI, and use the `createServerRunner` function to create the `runWithAmplifyServerContext` function.

For example, the `utils/amplifyServerUtils.ts` file may contain the following content:

```typescript title="src/utils/amplifyServerUtils.ts"
import { createServerRunner } from '@aws-amplify/adapter-nextjs';
import outputs from '@/amplify_outputs.json';

export const { runWithAmplifyServerContext } = createServerRunner({
  config: outputs
});
```

You can use the exported `runWithAmplifyServerContext` function to call Amplify APIs within isolated request contexts. You can review examples under the [Calling Amplify category APIs on the server side](#calling-amplify-category-apis-on-the-server-side) section.

<Callout>
**Tip:** You only need to call the `createServerRunner` function once and reuse the `runWithAmplifyServerContext` function throughout.
</Callout>

#### [Configure Amplify for client-side usage]

<Callout>
**Tip**: You only need do this step if you are using Amplify APIs on the client side of your Next.js app, for example, calling Amplify Auth `signIn` API to sign in a user, or use GraphQL subscriptions on the client side.
</Callout>

When you use the Amplify library on the client-side of your Next.js app, you will need to configure Amplify by calling the `Amplify.configure` as you would to use Amplify in a single-page application.

<Callout>

**Note:** To use the Amplify library on the client side in a Next.js app, you will need to set `ssr` to `true` when calling `Amplify.configure`. This instructs the Amplify library to store tokens in the cookie store of a browser. Cookies will be sent along with requests to your Next.js server for authentication.

</Callout>

```typescript
'use client';

import outputs from '@/amplify_outputs.json';
import { Amplify } from 'aws-amplify';

Amplify.configure(outputs, {
  ssr: true // required when using Amplify with Next.js
});

export default function RootLayoutThatConfiguresAmplifyOnTheClient({
  children
}: {
  children: React.ReactNode;
}) {
  return children;
}
```

> **Warning:** Make sure you call `Amplify.configure` as early as possible in your application’s life-cycle. A missing configuration or `NoCredentials` error is thrown if `Amplify.configure` has not been called before other Amplify JavaScript APIs. Review the [Library Not Configured Troubleshooting guide](/gen1/[platform]/build-a-backend/troubleshooting/library-not-configured/) for possible causes of this issue.

<Callout>

To avoid repetitive calls to `Amplify.configure`, you can call it once in a top-level client-side rendered layout component.

</Callout>

<Accordion title='Configure Amplify in a Next.js App Router application' headingLevel='4' eyebrow='Learn more'>

If you're using the Next.js App Router, you can create a client component to configure Amplify and import it into your root layout.

`ConfigureAmplifyClientSide.ts`:

```tsx title="src/components/ConfigureAmplifyClientSide.tsx"
'use client';

import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';

Amplify.configure(outputs, { ssr: true });

export default function ConfigureAmplifyClientSide() {
  return null;
}
```

`layout.tsx`:

```tsx title="src/app/layout.tsx"
import ConfigureAmplifyClientSide from '@/components/ConfigureAmplifyClientSide';
import './globals.css';

import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className="container pb-6">
        <>
          <ConfigureAmplifyClientSide />
          {children}
        </>
      </body>
    </html>
  );
}
```

</details>

## Authentication with Next.js server-side runtime

### (Experimental) Perform authentication on the server side and enable HttpOnly cookies

> **Warning:** **Warning:** This feature is experimental and may change in future releases.
> 
> Once you enable the server-side sign-in feature, auth tokens are stored in HttpOnly cookies and you may not change the HttpOnly attribute. Since these cookies are inaccessible from client-side scripts, you won’t be able to use any Amplify JS APIs on the client side. Therefore, you don’t need to configure Amplify on the client side. You can keep using [these Amplify JS server-side APIs](/[platform]/frontend/server-side-rendering/#supported-apis-for-nextjs-server-side-usage) on the server side.

Additional setup is required to enable server-side authentication flows in your Next.js app. 

#### Step 1 - Specify the origin of your app in environment variables

Add the following environment variable to your Next.js app. For example in a `.env` file:

```shell title=".env" showLineNumbers={false}
AMPLIFY_APP_ORIGIN=https://myapp.com
```

Ensure this environment variable is accessible in your Next.js app's server runtime.

> **Info:** **Note:** Token cookies are transmitted via server-side authentication flows. In production environments, it is recommended to use HTTPS as the origin for enhanced security.

#### Step 2 - Export the `createAuthRouteHandlers` function

The `createAuthRouteHandlers` function is created by the `createServerRunner` function call when you configure Amplify for server-side usage. You can export this function from your `amplifyServerUtils.ts` file. You can also configure cookie attributes with the `runtimeOptions` parameter.

```typescript title="src/utils/amplifyServerUtils.ts"
import { createServerRunner } from '@aws-amplify/adapter-nextjs';
import outputs from '@/amplify_outputs.json';

export const {
  runWithAmplifyServerContext,
  // highlight-start
  createAuthRouteHandlers,
  // highlight-end
} = createServerRunner({
  config: outputs,
  // highlight-start
  runtimeOptions: {
    cookies: {
      domain: '.myapp.com', // making cookies available to all subdomains
      sameSite: 'strict',
      maxAge: 60 * 60 * 24 * 7 // 7 days
    }
  }
  // highlight-end
});
```

#### Step 3 - Set up the Auth API routes

Create an API route using the `createAuthRouteHandlers` function. For example:

#### [App router]
```typescript title="src/app/api/auth/[slug]/route.ts"
import { createAuthRouteHandlers } from "@/utils/amplifyServerUtils";

export const GET = createAuthRouteHandlers({
  redirectOnSignInComplete: "/home",
  redirectOnSignOutComplete: "/sign-in",
});
```

#### [Pages router]
```typescript title="src/pages/api/auth/[slug].ts"
import { createAuthRouteHandlers } from "@/utils/amplifyServerUtils";

export default createAuthRouteHandlers({
  redirectOnSignInComplete: "/home",
  redirectOnSignOutComplete: "/sign-in",
});
```

With the above example, Amplify generates the following API routes:

| API Routes                                          | What it does                                                 |
| --------------------------------------------------- | ------------------------------------------------------------ |
| `/api/auth/sign-up`                                 | Upon navigating an end user to this route, they’ll be redirected to the Amazon Cognito Managed Login sign-up form. After sign-up and sign-in, they’ll be redirected back to the route `/api/auth/sign-in-callback`. |
| `/api/auth/sign-in`                                 | Upon navigating an end user to this route, they’ll be redirected to the Amazon Cognito Managed Login sign-in form. After sign-in, they’ll be redirected back to the route `/api/auth/sign-in-callback`. |
| `/api/auth/sign-in?provider=<social-provider-name>` | Upon navigating an end user to this route, they’ll be redirected first to the Amazon Cognito Managed Login and then the specified social provider sign-in page. After sign-in, they’ll be redirected back to the route `/api/auth/sign-in-callback`. |
| `/api/auth/sign-out`                                | Upon navigating an end user to this route, the end user will be signed out and redirected to the route `/api/auth/sign-out-callback`. |
| `/api/auth/sign-in-callback`                        | Amazon Cognito Managed Login redirects an end user back to this route after signing in. Amplify exchanges auth tokens and stores them as HttpOnly cookies in the browser cookie store, then redirects the end user back to the route specified by the `redirectOnSignInComplete` parameter. |
| `/api/auth/sign-out-callback`                       | Amazon Cognito Managed Login redirects an end user back to this route after signing out, Amplify revokes access token and refresh token and removes token cookies from browser cookie store, then redirects the end user back to the route specified by the `redirectOnSignOutComplete` parameter. |

To customize the language of the Amazon Cognito Managed Login pages, you can add the `lang` query parameter to the `/api/auth/sign-in` and `/api/auth/sign-up` routes. For example, `/api/auth/sign-in?lang=fr`. Refer to the [Managed login localization documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-managed-login.html#managed-login-localization) for more information on the supported languages.

> **Info:** **Note:** A signing-out call involves multiple steps, including signing out from Amazon Cognito Managed Login, revoking tokens, and removing cookies. If the user closes the browser during the process, the following may occur:
> 
> 1. auth token have not been revoked - user remains signed in
> 2. auth token have been revoked but cookies have not been removed - cookies will be removed when the user visits the app again

#### Step 4 - Provide the redirect URLs to the Auth Resource in Amplify

You can provide the callback API routes as the redirect URLs in the Auth resource configuration. For example:

```ts title="amplify/auth/resource.ts"
export const auth = defineAuth({
  loginWith: {
    email: true,
    // highlight-start
    externalProviders: {
      callbackUrls: ["https://myapp.com/api/auth/sign-in-callback"],
      logoutUrls: ["https://myapp.com/api/auth/sign-out-callback"],
    },
    // highlight-end
  },
});
```

This enables Amazon Cognito Hosted UI to support the server-side authentication flows. You may upgrade to the latest Amazon Cognito Managed Login Branding to customize the sign-in and sign-up pages. See [Amazon Cognito user pool managed login](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-managed-login.html) for more information.

#### Step 5 - Use Anchor link for initiating server-side authentication flows

Use HTML anchor links to navigate users to the sign-in and sign-up routes. For example:

#### [Sign in button]
```tsx title="src/components/SignInButton.tsx"
export default function SignInButton() {
  return (
    <a href="/api/auth/sign-in">
      Sign In
    </a>
  );
}
```

#### [Sign in with Google button]
```tsx title="src/components/SignInWithGoogleButton.tsx"
export default function SignInWithGoogleButton() {
  return (
    <a href="/api/auth/sign-in?provider=Google">
      Sign In with Google
    </a>
  );
}
```

#### [Sign up button]
```tsx title="src/components/SignUpButton.tsx"
export default function SignUpButton() {
  return (
    <a href="/api/auth/sign-up">
      Sign Up
    </a>
  );
}
```

#### [Sign out button]
```tsx title="src/components/SignOutButton.tsx"
export default function SignOutButton() {
  return (
    <a href="/api/auth/sign-out">
      Sign Out
    </a>
  );
}
```

When an end user clicks on the buttons above, a corresponding server-side authentication flow will be initiated.

### Validate user session with the Next.js Middleware

You can use the `fetchAuthSession` API to check the auth sessions that are attached to the incoming requests in the middleware of your Next.js app to protect your routes. For example:

```typescript title="src/middleware.ts"
import { fetchAuthSession } from 'aws-amplify/auth/server';
import { NextRequest, NextResponse } from 'next/server';
import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';

export async function middleware(request: NextRequest) {
  const response = NextResponse.next();

  const authenticated = await runWithAmplifyServerContext({
    nextServerContext: { request, response },
    operation: async (contextSpec) => {
      try {
        const session = await fetchAuthSession(contextSpec);
        return (
          session.tokens?.accessToken !== undefined &&
          session.tokens?.idToken !== undefined
        );
      } catch (error) {
        console.log(error);
        return false;
      }
    }
  });

  if (authenticated) {
    return response;
  }

  return NextResponse.redirect(new URL('/sign-in', request.url));
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|_next/image|favicon.ico|sign-in).*)'
  ]
};
```

In this example, if the incoming request is not associated with a valid user session the request will be redirected to the `/sign-in` route.

<Callout>

**Note:** When calling `fetchAuthSession` with a `response` context, it will send the refreshed tokens (if any) back to the client via the `Set-Cookie` header in the response.

</Callout>

## Calling Amplify category APIs on the server side

For the **Auth** categories to use Amplify APIs on the server in your Next.js app, you will need to:

1. Import the API from the `/server` sub path.
2. Use the `runWithAmplifyServerContext` helper function created by calling the `createServerRunner` function exported from `@aws-amplify/adapter-nextjs` to call the Amplify API in an isolated server context.

For the **GraphQL API** category, review [Connect to data from Server-side Runtimes](/[platform]/frontend/data/connect-from-server-runtime/).

<Callout>

**Note:** A subset of Amplify APIs can now be called on the server side of a Next.js app. These APIs are exported from the `/server` sub paths. See [the full list](#supported-apis-for-nextjs-server-side-usage) of supported APIs.

</Callout>

<Callout>

**Note:** If you use the Amplify server-side APIs in a [server action](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations) and encounter the following error running `next build`:

> ./node_modules/@aws-amplify/core/node_modules/@aws-crypto/sha256-js/build/module/index.js + 12 modules

> Cannot get final name for export 'fromUtf8' of ./node_modules/@smithy/util-utf8/dist-es/index.js

You can add the following to your `next.config.js`:

```ts title="next.config.js"
/** @type {import('next').NextConfig} */
const nextConfig = {
  // highlight-start
    serverComponentsPackages: ['@aws-crypto'],
  // highlight-end
};
```

See Next.js documentation on [`serverComponentsPackages`](https://nextjs.org/docs/app/api-reference/config/next-config-js/serverExternalPackages) for more details.
</Callout>

### With Next.js App Router

#### Dynamic rendering in React server component

Dynamic rendering is based on a user session extracted from an incoming request.

```jsx
import { cookies } from 'next/headers';
import { getCurrentUser } from 'aws-amplify/auth/server';
import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';

// This page always dynamically renders per request
export const dynamic = 'force-dynamic';

export default async function AuthGetCurrentUserServer() {
  try {
    const currentUser = await runWithAmplifyServerContext({
      nextServerContext: { cookies },
      operation: (contextSpec) => getCurrentUser(contextSpec)
    });

    return (
      <p>{`Hello, ${currentUser.username}`}</p>
    );
  } catch (error) {
    console.error(error);
    return <p>Something went wrong...</p>;
  }
}
```

#### Static rendering in React server component

Static rendering does not require a user session, so you can specify the `nextServerContext` parameter as `null`. This is useful for some use cases; for example, when you are using the Storage API with guest access (if you have enabled it in your backend).

```jsx
import { getUrl } from 'aws-amplify/storage/server';
import Image from 'next/image';
import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';

// Re-render this page every 60 minutes
export const revalidate = 60 * 60; // in seconds

export default async function StaticallyRenderedPage() {
  try {
    const splashUrl = await runWithAmplifyServerContext({
      nextServerContext: null,
      operation: (contextSpec) =>
        getUrl(contextSpec, {
          key: 'splash.png'
        })
    });

    return (
      <Image
        src={splashUrl.url.toString()}
        alt="Splash Image"
        width={500}
        height={500}
      />
    );
  } catch (error) {
    console.error(error);
    return <p>Something went wrong...</p>;
  }
}
```

<Callout>

**Note:** The URL returned by the `getUrl` API expires in the above example. You may want to specify the `revalidate` parameter to rerender the page as required to ensure the URL gets regenerated.

</Callout>

#### In Route Handlers

In route handlers require implementing an API route that enables `GET /apis/get-current-user`.

```typescript
import { getCurrentUser } from 'aws-amplify/auth/server';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';

export async function GET() {
  const user = await runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: (contextSpec) => getCurrentUser(contextSpec)
  });

  return NextResponse.json({ user });
}
```

When you call `fetch('/apis/get-current-user')` it returns a payload that contains the `user` data for the current signed-in user.

### With Next.js Pages Router

#### In `getServerSideProps`

The following example extracts current user data from the request and provides them to a page react component via its props.

```typescript
export const getServerSideProps: GetServerSideProps = async ({ req, res }) => {
  const currentUser = await runWithAmplifyServerContext({
    nextServerContext: { request: req, response: res },
    operation: (contextSpec) => getCurrentUser(contextSpec)
  });

  return { props: { currentUser } };
};
```

#### In `getStaticProps`

Similar to static rendering with the App Router, you can pass `null` as the value of the `nextServerContext` parameter to use the Amplify Storage API with guest access.

```typescript
export async function getStaticProps() {
  const splashUrl = await runWithAmplifyServerContext({
    nextServerContext: null,
    operation: (contextSpec) => getUrl(contextSpec, { key: 'splash.png' })
  });

  return {
    props: { imageUrl: splashUrl.url.toString() },
    revalidate: (splashUrl.expiresAt.getTime() - Date.now()) / 1000 // in seconds
  };
}
```

## Supported APIs for Next.js server-side usage

All APIs that support use on the server are exported from the `aws-amplify/<category>/server` sub paths. You **must** use these APIs for any server-side use cases.

| Category | APIs | Server (Node.js) Amplify Hosting/Vercel | Vercel Edge Runtime (middleware) |
| --- | --- | --- | --- |
| Auth | `fetchAuthSession` | ✅ | ✅ |
| Auth | `fetchUserAttributes` | ✅ | ✅ |
| Auth | `getCurrentUser` | ✅ | ✅ |
| Data | `generateServerClientUsingCookies` | ✅ |  |
| Data | `generateServerClientUsingReqRes` | ✅ |  |
| Storage | `getUrl` | ✅ |  |
| Storage | `getProperties` | ✅ |  |
| Storage | `list` | ✅ |  |
| Storage | `remove` | ✅ |  |
| Storage | `copy` | ✅ |  |

> **Info:** Have a server-side use case that isn't currently supported in Amplify JS? Consider using the [AWS SDK for JavaScript](https://aws.amazon.com/sdk-for-javascript/).
