Building a Robust Web Platform on AWS: Deploy the website to AWS using the CDK.
Published: 2023-11-20 13:41:48

In my previous [post](https://dev.to/alex_pustovalov/building-a-robust-web-platform-on-aws-a-step-by-step-journey-through-aws-cli-and-iam-identity-center-40f7), I discussed adding a user to manage AWS resources via the command line. 

> This user can also manage resources using the AWS console.

At this stage of development, my plan was to create infrastructure for deploying a static webpage for a website on AWS.

## Basic setup

Now, I will discuss the basic structure of the project, which I intend to develop gradually.

> It's important to note that the code will be primarily written in TypeScript, with some JavaScript.

Since the project involves multiple modules, I chose the pnpm package manager, known for its efficiency in multi-module projects or monorepos.

Setting up pnpm is straightforward. First, create a `package.json` file, add the `workspaces` option, and list the directories containing your module code.

I placed all modules in the `platform` directory and thus specified it in `workspaces`:
```
“workspaces”: [
    "platform/*"
]
```

Additionally, I created a `pnpm-workspaces.yml` file, also specifying the module directory:
```
packages:
    - 'platform/*'
```

## Website module

Next, I started creating the modules. For the website module, I created `platform/web-app`. Despite the name, this directory will eventually host a web application on **remix.run**, not just a static site.

In `platform/web-app`, I added an `index.html` page for my website.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5n4yklp3n59qvvvmt2s.png)

## Infrastructure setup

Following this, I began creating the AWS infrastructure for the website.

I started by installing the AWS CDK Toolkit:
```
npm install -g aws-cdk
```

Then, I created `platform/infra`, inspired by the Astro aws-astro adapter library. I used the following command to generate CDK code:
```
cdk init sample-app --language typescript
```
Reference: [CDK Workshop](https://cdkworkshop.com/20-typescript/20-create-project/100-cdk-init.html)

I customized the generated code and file names, resulting in a specific directory structure.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl0un6tyoh1ewf9te355.png)

Let's briefly discuss how the CDK works. It's a toolset for defining AWS cloud infrastructure in code, like TypeScript. This code compiles into CloudFormation stacks, which AWS uses to create the required infrastructure.

CDK mainly deals with two objects: Construct and Stack. A Construct can contain several other Constructs, while a Stack, responsible for generating the CloudFormation stack, can also contain several Constructs.

This approach simplifies describing infrastructure as a tree.

## Infrastructure construction

Inside `src`, I created `constructs` for CDK Constructs and `stacks` for CDK Stacks. I then created a `PlatformStack` class in `src/platform-stack.ts` and a `WebsiteConstruct` class in `src/website-construct.ts` for the website's infrastructure.

`WebsiteConstruct` manages the S3 Bucket (without public access), access rights, a CloudFront distribution, and uploads the contents of `platform/web-app` to the bucket.

For deployment, I used `bin/infra.ts`, executed by the CDK Toolkit.

The `cdk.json` file specifies the path for `bin/infra.ts`:
```
"app": "npx ts-node --prefer-ts-exts bin/infra.ts"
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9texz9gi0nzjkmhblno7.png)

Deployment is initiated using:
```
cdk deploy
```

## Deployment specifics

For first-time AWS deployments, bootstrapping CDK resources in your account is required. This is a one-time process, with additional bootstrapping needed for new regions.

I aimed to integrate deployment commands into the project's build flow. To avoid writing OS-specific scripts, I created JavaScript files for bootstrapping, deploying, and destroying the AWS stack, and included them in `package.json`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ux281lfh8z6ejk7gj2vb.png)

## Run deployment

User authentication in AWS before running these commands is crucial. I developed a `run-command` module for authorization checks and setting AWS session credentials in `process.env`.

This module reads from a `.env` file at the project root, containing the AWS administrative user's name and deployment region.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xa3xxobawvfpzp9fp19o.png)

Scripts in `package.json` can now be executed through `run-command`:
```
run-command node ./scripts/deploy.js
```

To manage the build and launch various modules in sequence, I added the `turbo` tool to the project.

The entire project code at this stage is available at [PageMosaic GitHub](https://github.com/pagemosaic/pagemosaic-website-starter/tree/stage-1) in the `stage-1` branch.

While the setup may seem basic, it provides a fundamental understanding of AWS infrastructure deployment and programming simplicity, avoiding complex AWS console manipulations.

You can try deploying this single-page site on your AWS by following the instructions in the repository's [README.md](https://github.com/pagemosaic/pagemosaic-website-starter/blob/stage-1/README.md).

---

In my next post, I'll describe replacing the static webpage with a full-fledged web application on remix.run.

---