---
title: "Deploy Content SDK Angular apps to Vercel or Netlify"
slug: "deploy-content-sdk-angular-apps-to-vercel-or-netlify"
abstract: "Learn how to deploy Content SDK Angular apps with server-side rendering to Vercel or Netlify."
---
# Deploy Content SDK Angular apps to Vercel or Netlify

You can deploy a Content SDK Angular application to Vercel or Netlify with server-side rendering (SSR). The generated application uses an Express server to handle Angular rendering and Content SDK middleware. To run this server on either platform, create a serverless function that imports the compiled Angular request handler.

This topic describes how to:

1. [Prepare your application for deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#prepare-your-application-for-deployment).
2. [Deploy your application](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#deploy-your-application).
3. [Verify your deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#verify-your-deployment).

## Prepare your application for deployment

To prepare your application for deployment:

1. In `src/server.ts`, ensure that the request handler has the default export for the request handler:

    ```ts
    export default reqHandler;
    ```

2. Replace `<app-name>` in every example in this topic with your application's name set in `package.json`.

3. Prepare the environment variables that your application uses to connect to SitecoreAI:

    | Variable                               | Value                                                  |
    | -------------------------------------- | ------------------------------------------------------ |
    | `SITECORE_EDGE_CONTEXT_ID`             | The server context ID for your SitecoreAI environment. |
    | `CSDK_PUBLIC_SITECORE_EDGE_CONTEXT_ID` | The client context ID for browser operations.          |
    | `CSDK_PUBLIC_DEFAULT_SITE_NAME`        | The name of the Sitecore site.                         |
    | `CSDK_PUBLIC_DEFAULT_LANGUAGE`         | The default language, for example, `en`.               |

    Add any other variables required by your application. If you use the deployment as an editing host, configure `SITECORE_EDITING_SECRET` and the corresponding rendering host settings in SitecoreAI.

    For configuration details, see [The Sitecore configuration file](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/the-sitecore-configuration-file.html).

    > [!important]
    > The build includes variables prefixed with `CSDK_PUBLIC_` in the browser bundle. Use the client context ID for `CSDK_PUBLIC_SITECORE_EDGE_CONTEXT_ID` and keep the server context ID in `SITECORE_EDGE_CONTEXT_ID`.

## Deploy your application

See the following sections to deploy your application to Vercel and Netlify.

::::tabs
:::tab{title="Vercel"}

Create a Vercel Function that exports the compiled Angular request handler, then configure Vercel to route requests to it. This configuration uses the Node.js runtime.

To deploy your application to Vercel:

1. In the application's root folder, create `vercel/index.mjs` with the following content:

    ```js
    export { default } from '../dist/<app-name>/server/server.mjs';
    ```

2. In the application's root folder, create `vercel.json` with the following content:

    ```json
    {
      "$schema": "https://openapi.vercel.sh/vercel.json",
      "buildCommand": "npm run build",
      "outputDirectory": "dist/<your_app_name>/browser",
      "rewrites": [
        {
          "source": "/(.*)",
          "destination": "/vercel/index"
        }
      ],
      "functions": {
        "vercel/index.mjs": {
          "includeFiles": "dist/<your_app_name>/**"
        }
      }
    }
    ```

    The `framework` setting selects the **Other** preset for this custom deployment configuration. The `includeFiles` setting includes the Angular build output in the function so the server can access its runtime files.

3. Commit and push the application changes to your source control repository.
4. In the Vercel dashboard, create a project by importing the repository. Set the **Root Directory** to the application's root folder, which contains `package.json` and `vercel.json`.
5. Add the Content SDK environment variables from [Prepare your application for deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#prepare-your-application-for-deployment). Make them available in each Vercel deployment environment that you use.
6. Add the following Angular environment variables:

    ```bash
    NG_ALLOWED_HOSTS=*.vercel.app
    NG_TRUST_PROXY_HEADERS=X-FORWARDED-PORT,X-FORWARDED-PATH,X-FORWARDED-FOR,X-FORWARDED-HOST,X-FORWARDED-PROTO
    ```

    These settings allow Vercel URLs and prevent Vercel rendering from falling back to CSR.

7. Deploy the project, then [verify the deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#verify-your-deployment).

:::
:::tab{title="Netlify"}

Use a Netlify Functions v2 handler with the `.mts` extension to preserve the ECMAScript module (ESM) format required by the compiled Angular server. The handler uses `serverless-http` to adapt Netlify's web `Request` and `Response` objects to the Express request handler.

The named `handler` export in Netlify's [Express deployment example](https://docs.netlify.com/build/frameworks/framework-setup-guides/express/) uses the Lambda-compatible API. For this Angular deployment, use the default export shown below. See [Netlify function module formats](https://docs.netlify.com/build/functions/optional-configuration/#module-format).

To deploy your application to Netlify:

1. The `serverless-http` module provides the required bridge between Express and Netlify. You should install it alongside few additional dependencies that your Netlify function will use. In the application's root folder, install the function dependencies:

    ```shell
    npm install express serverless-http @netlify/functions @types/express
    ```

2. Create `netlify/functions/server.mts` with the following content:

    ```ts
    import serverless from 'serverless-http';
    import type { Context } from '@netlify/functions';
    import { default as app } from '../../dist/<your_app_name>/server/server.mjs';

    const handler = serverless(app);
    const FUNCTION_BASE = '/.netlify/functions/server';

    /** serverless-http's result for a Lambda Function URL ("2.0") event. */
    interface LambdaResult {
      statusCode: number;
      headers: Record<string, string>;
      cookies: string[];
      body: string;
      isBase64Encoded: boolean;
    }

    export default async (request: Request, context: Context) => {
      const url = new URL(request.url);
      // The netlify.toml rewrite passes the original path; direct invocations
      // arrive prefixed with the function base path — strip it.
      const path = url.pathname.startsWith(FUNCTION_BASE)
        ? url.pathname.slice(FUNCTION_BASE.length) || '/'
        : url.pathname;

      // Lambda Function URL ("2.0") event — the leanest shape serverless-http accepts
      const lambdaRequest = {
          version: '2.0',
          rawPath: path,
          rawQueryString: url.searchParams.toString(),
          headers: Object.fromEntries(request.headers),
          requestContext: { http: { method: request.method } },
          body: Buffer.from(await request.arrayBuffer()),
        };
      const result = (await handler(lambdaRequest, context)) as LambdaResult;

      // set-cookie comes back separately; `|| null` keeps 204/304 responses body-less.
      const headers = new Headers(result.headers);
      for (const cookie of result.cookies) headers.append('set-cookie', cookie);
      return new Response(
        result.isBase64Encoded ? Buffer.from(result.body, 'base64') : result.body || null,
        { status: result.statusCode, headers }
      );
    };
    ```

    The function imports Angular's SSR artifacts and transforms them to be used by `serverless-http` and v2 functions. These transformations are needed for the Netlify CLI to correctly identify the function as ESM-compatible. This example TypeScript function is assumed to be present inside the `netlify/functions/server.mts` file.

3. In the application's root folder, create `netlify.toml` with the following content:

    ```toml
    [build]
      command = "npm run build"
      publish = "dist/content-sdk-angular/browser"

    [functions.server]
      # Ship the full dist folder so express.static and any runtime file access work.
      included_files = ["dist/content-sdk-angular/**"]

    [[redirects]]
      from = "/*"
      status = 200
      to = "/.netlify/functions/server/:splat"
    ```

4. Commit and push the application changes, including the updated dependency files, to your source control repository.
5. In Netlify, create a project from the repository. If the application is in a subfolder, set the **Base directory** to the application's root folder. Confirm that Netlify uses the build, publish, and functions paths in `netlify.toml`.
6. Add the Content SDK environment variables from [Prepare your application for deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#prepare-your-application-for-deployment). Ensure that the connection variables are available during the build and to the deployed function. The build includes public variables in the browser bundle.
7. Add the following Angular environment variables for the deployed function:

    ```bash
    NG_ALLOWED_HOSTS=*.netlify.app
    NG_TRUST_PROXY_HEADERS=X-FORWARDED-PORT,X-FORWARDED-PATH,X-FORWARDED-FOR,X-FORWARDED-HOST,X-FORWARDED-PROTO
    ```

    These settings allow netlify URLs and ensure Angular SSR works correctly from behind the Netlify proxy.

8. Deploy the project, then [verify the deployment](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/deploy-content-sdk-angular-apps-to-vercel-or-netlify.html#verify-your-deployment).
:::
::::

## Verify your deployment

After the build and deployment complete:

1. Open the deployment URL and confirm that the application displays the published Sitecore content.
2. Open a nested page URL directly, then refresh the page to verify that the hosting configuration routes the request to the application.
3. Inspect the page source for a server-rendered route and confirm that the initial HTML contains the expected page content.
4. Navigate between pages and check that the `POST /_data` requests succeed and static assets load without errors.

If the application doesn't render correctly, check the hosting provider's build and function logs. Confirm that the build output paths match the function imports and configuration files, and that `NG_ALLOWED_HOSTS` includes the deployment hostname. Check `NG_TRUST_PROXY_HEADERS` if Angular doesn't resolve the request URL correctly behind the hosting proxy.

Rebuild and redeploy after changing public environment variables because the build includes their values in the browser bundle.

These deployments run the Express server as a serverless function. The hosting provider's function limits apply. See [Vercel Functions limits](https://vercel.com/docs/functions/limitations) and [Netlify function configuration and limits](https://docs.netlify.com/build/functions/optional-configuration/).
