<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Raphael Americano</title>
    <description>The latest articles on DEV Community by Raphael Americano (@raphaamericano).</description>
    <link>https://dev.to/raphaamericano</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2571284%2Fede46edb-a964-42e5-b6f4-d9ebb9417800.jpg</url>
      <title>DEV Community: Raphael Americano</title>
      <link>https://dev.to/raphaamericano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raphaamericano"/>
    <language>en</language>
    <item>
      <title>Deploy de NextJS utilizando CDK</title>
      <dc:creator>Raphael Americano</dc:creator>
      <pubDate>Tue, 07 Jan 2025 12:55:42 +0000</pubDate>
      <link>https://dev.to/raphaamericano/deploy-de-nextjs-utilizando-cdk-10ob</link>
      <guid>https://dev.to/raphaamericano/deploy-de-nextjs-utilizando-cdk-10ob</guid>
      <description>&lt;p&gt;O objetivo é construir um pipeline para realizar o deploy de uma aplicação NextJS, com o código em um repositório do Github, em um bucket S3 da AWS.&lt;br&gt;
A ideia é utilizá-lo em aplicações que utilizam o Server Side Generation(SSG). Isso se torna útil para lançar landing pages e hotsides em que as páginas já possuem o conteúdo definido.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvepow2ilyrxz2tzpscv3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvepow2ilyrxz2tzpscv3.jpg" alt="Image description" width="553" height="283"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando os repositórios
&lt;/h2&gt;

&lt;p&gt;Vamos criar dois repositórios. O primeiro é a aplicação NextJS, e o segundo o código da infraestrutura.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Criando a aplicação
npx create-next-app@latest pipeline-nextjs-site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Iniciando a infraestrutura com CDK:
## Criar a pasta
mkdir pipeline-nextjs-infra &amp;amp;&amp;amp; cd pipeline-nextjs-infra
## Inciando o projeto
cdk init app --language typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configurando o output do NextJS
&lt;/h2&gt;

&lt;p&gt;No código do NextJS vamos apenas alterar a parte da configuração de exportação. Lembrando que esse tutorial não tem como objetivo realizar configurações avançadas ou otimizações do NextJS, apenas servir a exportação em um Bucket S3.&lt;br&gt;
Nosso arquivo next.config.ts deve ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  output: "export",
};

export default nextConfig;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Faça o commit e disponibilize o repositório na sua conta do Github. Pode ser um repositório privado. Tenho utilizado nos últimos meses a &lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;Github CLI&lt;/a&gt; e acho bastante prática. Sugiro dar uma olhada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurações iniciais
&lt;/h3&gt;

&lt;p&gt;Primeiro passo é criar um &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS_ACCOUNT=
AWS_REGION=
GITHUB_TOKEN=
GITHUB_USERNAME=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse &lt;code&gt;.env&lt;/code&gt; vamos guardar o código da conta AWS, a região que o serviço será disponibilizado, seu usuário do Github e um token para essa integração. Para gerar esse token, vá em sua conta do Github e siga esses passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clique em &lt;strong&gt;Settings&lt;/strong&gt; e em seguida &lt;strong&gt;Developer settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Personal access tokens&lt;/strong&gt;, em seguida &lt;strong&gt;Tokens (classic)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;No select box do canto direito, clique em &lt;strong&gt;Genereate new token(classic)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Conclua o processo de 2FA caso requisitado&lt;/li&gt;
&lt;li&gt;Nomeie o seu token, escolha uma data de expiração, selecione todas as opções &lt;strong&gt;repo&lt;/strong&gt;, a opção &lt;strong&gt;workflow&lt;/strong&gt; e clique em &lt;strong&gt;Generate token&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Com o token criado, cole-o no seu arquivo &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Será preciso instalar a biblioteca &lt;code&gt;dotenv&lt;/code&gt; para utilizarmos o arquivo que criamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando as stacks com CDK
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stack IAM
&lt;/h3&gt;

&lt;p&gt;O CDK trabalha com o conceito de stack para formar a infraestrutura que será disponibilizada na AWS. Para esse projeto, vamos criar três stacks: S3, IAM e Pipeline. Adotaremos a estratégia de separar os serviços da AWS por stack.&lt;br&gt;
Na raiz do repositório da infra, vamos criar um diretório chamado lib e dentro dele o primeiro arquivo de stack: &lt;code&gt;iam-stack.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nessa estarão as permissões para o CDK realizar tarefas como salvar arquivos em um bucket S3.&lt;br&gt;
Temos que criar uma classe estendendo a classe &lt;code&gt;Stack&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class IamStack extends cdk.Stack {
 constructor(scope: Construct, id: string, props?: cdk.StackProps){
   super(scope, id, props)
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, é preciso adicionar politicas de acesso. Vamos criar uma referência ao serviço, uma politica de acesso completo ao S3, acesso ao Code Build como administrador e por último criar o papel de build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class IamStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps){
        super(scope, id, props)
        const code_build_service = new iam.ServicePrincipal("codebuild.amazonaws.com")

        const s3_full_access = iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess")
        const codebuild_admin_access = iam.ManagedPolicy.fromAwsManagedPolicyName("AWSCodeBuildAdminAccess")

        this.build_role = new iam.Role(this, "BuildRole", {
            assumedBy: code_build_service,
            description: "Role for codebuild"
        })
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para concluir essa stack, adicionaremos as políticas de acesso ao papel que criamos e salvar o ARN do papel em uma propriedade da classe. O arquivo completo deve ficar dessa forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class IamStack extends cdk.Stack {

    private readonly build_role: iam.Role
    public readonly build_role_arn: string;
    constructor(scope: Construct, id: string, props?: cdk.StackProps){
        super(scope, id, props)
        const code_build_service = new iam.ServicePrincipal("codebuild.amazonaws.com")

        const s3_full_access = iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess")
        const codebuild_admin_access = iam.ManagedPolicy.fromAwsManagedPolicyName("AWSCodeBuildAdminAccess")

        this.build_role = new iam.Role(this, "BuildRole", {
            assumedBy: code_build_service,
            description: "Role for codebuild"
        })

        this.build_role.addManagedPolicy(s3_full_access)
        this.build_role.addManagedPolicy(codebuild_admin_access)

        this.build_role_arn = this.build_role.roleArn
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stack S3
&lt;/h3&gt;

&lt;p&gt;A próxima stack será do S3. Nesse caso, vamos precisar acrescentar informações na interface de propriedades dessa stack, portanto vamos estender dessa forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import { Construct } from 'constructs';
interface S3StackProps extends cdk.StackProps {
    build_role_arn: string
}
export class S3Stack extends cdk.Stack {
    public readonly bucket: s3.Bucket;
    public readonly build_role: iam.Role

    constructor(scope: Construct, id: string, props: S3StackProps){
        super(scope, id, props);


    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, precisamos recuperar o papel do IAM criado na outra Stack a partir do ARN que passado no construtor da classe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const build_role = iam.Role.fromRoleArn(this, "ImportBuildRole", props.build_role_arn)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, criaremos o recurso do Bucket em si, onde definiremos as propriedades para servir os arquivos da build realizada pelo NextJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.bucket = new s3.Bucket(this, "BucketNextJSSite", {
    websiteIndexDocument: "index.html",
    websiteErrorDocument: "404.html",
    publicReadAccess: true,
    blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    autoDeleteObjects: true
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Propriedade &lt;code&gt;websiteIndexDocument&lt;/code&gt; é referente ao arquivo html inicial do site, enquanto &lt;code&gt;websiteErrorDocument&lt;/code&gt; é o arquivo padrão para erro 404 caso alguma página não tenha sido encontrada. &lt;br&gt;
&lt;code&gt;removalPolicy&lt;/code&gt; e &lt;code&gt;autoDeleteObjects&lt;/code&gt; são propriedades para remover os arquivos do bucket, caso opte por destruir o projeto do CDK, removendo todos os recursos.&lt;br&gt;
Para conseguir expor o acesso do site aos usuários, as configurações de &lt;code&gt;publicReadAccess&lt;/code&gt; e &lt;code&gt;blockPublicAccess&lt;/code&gt; são responsáveis por isso.&lt;br&gt;
O ambiente da AWS é bastante robusto no requisito de autorizações. Praticamente para tudo que um recurso precise executar em outro recurso, será preciso algum tipo de autorização.&lt;br&gt;
Para finalizar a stack do S3, é preciso salvar a url do website criado pelo bucket para a utilização dentro de nosso ambiente. E também será preciso salvar o nome do bucket criado no serviço AWS Systems Manager(SSM) para utilizar mais a frente quando o pipeline for configurado. O código final será esse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class S3Stack extends cdk.Stack {
    public readonly bucket: s3.Bucket;
    public readonly build_role: iam.Role

    constructor(scope: Construct, id: string, props: S3StackProps){
        super(scope, id, props);
        const build_role = iam.Role.fromRoleArn(this, "ImportBuildRole", props.build_role_arn)
        this.bucket = new s3.Bucket(this, "BucketNextJSSite", {
            websiteIndexDocument: "index.html",
            websiteErrorDocument: "404.html",
            publicReadAccess: true,
            blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
            removalPolicy: cdk.RemovalPolicy.DESTROY,
            autoDeleteObjects: true
        })

        this.bucket.grantReadWrite(build_role)

        this.bucket.addToResourcePolicy(new iam.PolicyStatement({
            effect: iam.Effect.ALLOW,
            principals: [new iam.ArnPrincipal(build_role.roleArn)],
            actions: [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            resources: [
                this.bucket.bucketArn,
                this.bucket.arnForObjects("*")],
        }))

        new cdk.CfnOutput(this, "BucketNextJSSiteURL", {
            value: this.bucket.bucketWebsiteUrl,
            description: "URL do site hospedado no S3",
            exportName: "BucketNextJSSiteURL"
        })

        new ssm.StringParameter(this, 'BucketNextJSSiteNameSSM', {
            parameterName: 'BucketNextJSSiteName',
            stringValue: this.bucket.bucketName
        })

    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stack CodePipeline
&lt;/h3&gt;

&lt;p&gt;A última stack será responsável pelo pipeline que entregará a build do projeto. Aqui também é preciso uma interface para as propriedades, pois precisaremos receber o bucket e o ARN do papel criado anteriormente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PipelineStackProps extends cdk.StackProps {
    bucket: s3.Bucket;
    build_role_arn: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inciando a classe da stack, precisaremos recuperar o papel de build a partir da ARN injetada e utilizar iniciar um novo objeto referente ao projeto de pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class PipelineStack extends cdk.Stack {

    constructor(scope: Construct, id: string, props: PipelineStackProps) {
        super(scope, id, props);

        const build_role = iam.Role.fromRoleArn(this, "ImportBuildRole", props.build_role_arn)

        const buildProject = new codebuild.PipelineProject(this, "BuildNextJSSite", {
            projectName: "BuildNextJSSite",
            role: build_role,
            environment:{
                buildImage: codebuild.LinuxBuildImage.STANDARD_5_0,
                environmentVariables: {
                    BUCKET_NAME: {
                        value: props.bucket.bucketName
                    }
                },
            },
            buildSpec: codebuild.BuildSpec.fromObject({
                version: '0.2',
                phases:{
                    install: {
                        'runtime-versions': {
                            nodejs: 20
                        },
                        commands:[
                            'npm install'
                        ]
                    },
                    build: {
                        commands: [
                            'npm run build',
                            'aws s3 sync ./out s3://$BUCKET_NAME --delete'

                        ]
                    }
                },
                artifacts: {
                    files: [ '**/*' ],
                    'base-directory': 'out'
                }
            })
        })

    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nessa primeira etapa, utilizaremos o nome do bucket a partir da propriedade injetada para configurar o ambinete. Além disso, as configurações de linha de comando também são configuradas nesse objeto.&lt;br&gt;
Em seguida, vamos criar uma constante para o objeto do Pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const pipeline = new codepipeline.Pipeline(this, "PipelineNextJSSite", {
    pipelineName: "NextJSSitePipeline",
    crossAccountKeys: false,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um ponto de maior atenção aqui. O objetivo desse tutorial é mostrar um exemplo de fluxo para o deploy. Vou apresentar duas formas de buscar o token do Github. A primeira maneira é buscando pela variável de ambiente. Não é a recomendada pela AWS, mas a utilizaremos para poupar custo enquanto desenvolvemos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const githubToken = cdk.SecretValue.unsafePlainText(process.env.GITHUB_TOKEN!);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A AWS recomenda utilizarmos o serviço Secrets Manager para administrar chaves de api e informações sensíveis. Utilize a maneira a seguir quando for disponibilzar o seu site ou aplicação em produção:&lt;br&gt;
Entre no painel da sua conta na AWS. Em Secrets Menager, adicione um secret &lt;code&gt;github-token&lt;/code&gt; com seu token. Para buscá-lo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const githubToken = cdk.SecretValue.secretsManager('github-token');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basicamente, cada segredo no Secrets Manager custa 0.40 dólares por mês, o que pode ser um custo desnecessário durante o processo de desenvolvimento ou para uma simples POC.&lt;/p&gt;

&lt;p&gt;Com o token pronto, vamos criar um Artifact e em seguida adicionar um estágio ao pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipeline.addStage({
    stageName: "Source",
    actions: [
        new codepipeline_actions.GitHubSourceAction({
            actionName: "BuildAndDeployNextJSSite",
            owner: "RaphaAmericanoDev",
            repo: "next-js-website",
            branch: "deploy",
            oauthToken: githubToken,
            output: sourceOutput
        }),
    ],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse estágio selecionamos o owner, seu username do Github,  e o repositório do projeto NextJS em repo. Todos os commits na branch ´deploy´ irão disparar a build. Isso é especialmente útil para evitar builds desnecessárias e apenas quando de fato alguma funcionalidade nova precisa ser levada ao ambiente.&lt;br&gt;
Vamos adicionar o token do Github que recuperamos e o artefato onde a build será feita. &lt;/p&gt;

&lt;p&gt;Por último, vamos adicionar um segundo estágio do pipeline onde preenchemos com o projeto de Pipeline e o artefato:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; pipeline.addStage({
    stageName: 'Build',
    actions:[
        new codepipeline_actions.CodeBuildAction({
                actionName: "BuildAndDeployNextJSSite",
                project: buildProject,
                input: sourceOutput
            }),
        ]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reunindo as stacks e montando a infraestrutura
&lt;/h2&gt;

&lt;p&gt;Agora que concluímos todas as stacks, vamos criar um arquivo para montar tudo. O setup inicial do CDK cria uma pasta &lt;code&gt;bin&lt;/code&gt; na raiz do projeto com um arquivo de exemplo. Vamos limpá-lo, iniciar os dados do ´.env´, criar a constante de &lt;code&gt;Environment&lt;/code&gt; do CDK, uma constante de tags e iniciar o app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as dotenv from 'dotenv';
import * as cdk from 'aws-cdk-lib';
import { PipelineStack } from '../lib/pipeline-stack';
import { S3Stack } from '../lib/s3-stack';
import { IamStack } from '../lib/iam-stack';

dotenv.config();

const env:cdk.Environment = {
  account: process.env.AWS_ACCOUNT,
  region: process.env.AWS_REGION
}

const tags = {
  cost: "NextJSSite",
  region: "us-east-1",
}
const app = new cdk.App();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em todas as stacks, vamos adicionar o &lt;code&gt;env&lt;/code&gt; e &lt;code&gt;tags&lt;/code&gt;. &lt;br&gt;
A primeira stack instanciada deve ser a IamStack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const iamStack = new IamStack(app, 'NextJSSiteIamStack', {
  env: env,
  tags: tags,
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, ao criar stack do S3 será preciso adicionar &lt;code&gt;build_role_arn&lt;/code&gt; da instância de IamStack. Além disso, é preciso adicionar o &lt;code&gt;iamStack&lt;/code&gt; com dependência do stack do S3 já que não é possivel manipular dados no bucket sem a autorização criada previamente no IAM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const s3Stack = new S3Stack(app, 'NextJSSiteS3Stack', {
  build_role_arn: iamStack.build_role_arn,
  env: env,
  tags: tags,
});
s3Stack.addDependency(iamStack)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O próximo passo é instanciar um objeto do PipelineStack passando o bucket que criamos assim como o ARN do papel de build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const pipelineStack = new PipelineStack(app, 'NextJSSitePipelineStack', { 
  bucket: s3Stack.bucket,
  build_role_arn: iamStack.build_role_arn,
  env: env, 
  tags: tags, 
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui também precisamos adicionar as stacks de IAM e S3 como dependências da stack de pipeline pela mesma razão da stack anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipelineStack.addDependency(iamStack)
pipelineStack.addDependency(s3Stack)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegou a hora do deploy! Execute o comando de &lt;code&gt;synth&lt;/code&gt; para verificar se tudo está correto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk synth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso tudo esteja correto, execute o comando &lt;code&gt;deploy&lt;/code&gt;. O CLI vai pedir algumas autorizações e confirmações, aperte &lt;code&gt;y&lt;/code&gt; para ir seguindo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk deploy --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No painel da AWS, entre na parte do S3. Dentro de &lt;strong&gt;Buckets em geral&lt;/strong&gt;, procure o bucket que possui os arquivos do deploy e clique no &lt;code&gt;index.html&lt;/code&gt;. Na página do arquivo, clique no link  &lt;strong&gt;Url de objeto&lt;/strong&gt; e estará a primeira página da aplicação NextJS.&lt;/p&gt;

&lt;p&gt;Esse pipeline pode ser útil para apresentar sites para clientes, criar ambientes de validação ou mesmo criação de POCs. Cada pipeline ativo tem um custo mensal de 1USD.&lt;/p&gt;

&lt;p&gt;Caso seja necessário avançar para uma entrega mais completa, elegante e pronta para produção, o próximo passo seria configurar o Route 53 para ter uma url amigável e apropriada. Mas isso é assunto para um pŕoximo artigo. Até lá!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>nextjs</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
