DEV Community

Cover image for Deploying a Next.js 14 App to AWS Amplify using CDK
Ilker Dagli
Ilker Dagli

Posted on • Edited on • Originally published at ilker.io

2

Deploying a Next.js 14 App to AWS Amplify using CDK

In this blog post, I'll guide you through deploying a Next.js 14 app to AWS Amplify using CDK.
Please note that as of writing this post, AWS Amplify does not officially support Next.js 14.

While I personally believe that Vercel is a better solution for now, I encountered challenges deploying my app to Amplify. This post aims to help others who might face similar issues.

Before we begin, ensure you have a GitHub access token obtained from the GitHub Settings Page. Store the token securely
in AWS Secrets Manager.

Let's start by creating an IAM role and a managed policy for use in the App construct of aws_amplify_alpha.

const role = new cdk.aws_iam.Role(this, 'AmplifyRole', {
    assumedBy: new cdk.aws_iam.ServicePrincipal('amplify.amazonaws.com'),
    description: 'CDK Amplify Role',
})

const managedPolicy = cdk.aws_iam.ManagedPolicy.fromAwsManagedPolicyName(
    'AdministratorAccess',
);

role.addManagedPolicy(managedPolicy)
Enter fullscreen mode Exit fullscreen mode

Now, let's create an Amplify App. Key details are explained below.

const amplifyApp = new aws_amplify_alpha.App(this, 'MyApp', {
    description: 'My App',
    sourceCodeProvider: new aws_amplify_alpha.GitHubSourceCodeProvider({
        owner: 'ilkerdagli',
        repository: 'myApp',
        oauthToken: cdk.SecretValue.secretsManager('GithubAccessToken'),
    }),
    customRules: [
        {
            source: '/<*>',
            target: '/index.html',
            status: aws_amplify_alpha.RedirectStatus.NOT_FOUND_REWRITE,
        },
    ],
    environmentVariables: {
        "AMPLIFY_MONOREPO_APP_ROOT": "frontend",
        "AMPLIFY_DIFF_DEPLOY": "false",
        "_CUSTOM_IMAGE": "public.ecr.aws/docker/library/node:20.11",
        "NEXT_PUBLIC_AWS_AMPLIFY_REGION": "eu-central-1",
    },
    buildSpec: cdk.aws_codebuild.BuildSpec.fromObjectToYaml({
        version: '1.0',
        applications: [
            {
                appRoot: 'frontend',
                frontend: {
                    phases: {
                        preBuild: {
                            commands: ['yarn install --frozen-lockfile'],
                        },
                        build: {
                            commands: ['env | grep -e NEXT_PUBLIC_ >> .env.production', 'yarn run build'],
                        },
                    },
                    artifacts: {
                        baseDirectory: '.next',
                        files: ['**/*'],
                    },
                    cache: {
                        paths: ['node_modules/**/*', '.next/cache/**/*'],

                    },
                },
            }
        ]
    }),
    role: role,
})

const devBranch = amplifyApp.addBranch('dev', {
    description: 'dev branch',
});
Enter fullscreen mode Exit fullscreen mode

My app was located in the frontend directory of my GitHub repository. Therefore, the environment variable AMPLIFY_MONOREPO_APP_ROOT_ is set to frontend,
which must match the buildSpec's applications appRoot definition.

Since Amplify's default build image doesn't support Next.js 14 due to an older node version, we use a custom image. Set the CUSTOM_IMAGE environment variable accordingly.

Additionally, we add a dev branch to the app for automatic redeployment upon each push.

To complete the setup, we need run the following commands to run the app on Amplify:

aws amplify update-app --app-id APPID --platform WEB_COMPUTE 
aws amplify update-branch --app-id APPID --branch-name dev --framework 'Next.js - SSR'
Enter fullscreen mode Exit fullscreen mode

However, for automation, consider using CDK custom resources as demonstrated below:

new cdk.custom_resources.AwsCustomResource(this, 'AmplifyExtraSettings', {
    onUpdate: {
        service: 'Amplify',
        action: 'updateApp',
        parameters: {
            appId: amplifyApp.appId,
            platform: 'WEB_COMPUTE',
        },
        physicalResourceId: cdk.custom_resources.PhysicalResourceId.of(Date.now().toString()),
    },

    policy: cdk.custom_resources.AwsCustomResourcePolicy.fromSdkCalls({
        resources: [amplifyApp.arn],
    }),

});

new cdk.custom_resources.AwsCustomResource(this, 'AmplifyUpdateDevBranch', {
    onUpdate: {
        service: 'Amplify',
        action: 'updateBranch',
        parameters: {
            appId: amplifyApp.appId,
            branchName: 'dev',
            framework: 'Next.js - SSR',
        },
        physicalResourceId: cdk.custom_resources.PhysicalResourceId.of(Date.now().toString()),
    },
    policy: cdk.custom_resources.AwsCustomResourcePolicy.fromSdkCalls({
        resources: [amplifyApp.arn, devBranch.arn],
    }),
});
Enter fullscreen mode Exit fullscreen mode

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs