How to create your own low cost website using CDK (part 1)
Photo by Johnson Wang / Unsplash
By Ali Tahiri -  3 min read

How to create your own low cost website using CDK (part 1)


An internet presence is crucial in our digitally defined age. While social media has helped many of us create this presence easily, your "existence" in the digital world is dependent on these platforms. Whether you are a developer, an artist, a writer or an entrepreneur ... , you will only benefit from having a personal website alongside your social media accounts.

This tutorial will help you, whether you are well versed in the IT subject or not, create your own personal website with a special focus on cost optimization. It will follow an exhaustive step by step explanation in order for to understand the different code snippets and their utility.

If you have no idea what a CLI is, then I will be inclined to ask you to refer to a future post where I will go through the same process using a beginner friendly approach.


Chapter I: The infrastructure

Target infrastructure

A normal flow would be a user who will send an HTTP request to your domain name, we will refer to it as Route 53 will resolve the DNS request to a CloudFront distribution that serves an S3 Bucket where our website is hosted. The TLS certificate for HTTPS is validated by ACM.

Chapter II: Preparing the environment

I assume you have all the prerequisites installed. You can follow this guide to create a new programmatic user in AWS to avoid using your root user. Next you can follow this guide to configure your AWS CLI to use your Access Key ID and Secret Access Key. The guides are succint and lucid.

Let's create a structure for our website project:

mkdir personal-website && cd personal-website
mkdir Infra
hugo new site website-source
cd Infra
cdk init app --language typescript
Commands to setup our project env

The result should be something like this:

tree personal-website -I 'node_modules'
├── Infra
│   ├──
│   ├── bin
│   │   └── infra.ts
│   ├── cdk.json
│   ├── jest.config.js
│   ├── lib
│   │   └── infra-stack.ts
│   ├── package-lock.json
│   ├── package.json
│   ├── test
│   │   └── infra.test.ts
│   └── tsconfig.json
└── website-source
    ├── archetypes
    │   └──
    ├── config.toml
    ├── content
    ├── data
    ├── layouts
    ├── static
    └── themes

11 directories, 11 files
The starting structure of our project

‌            ‌

Chapter III: Creating the S3 bucket

Change directory to Infra.

The approach we're going to use is that of incremental changes. First off we will create the S3 bucket.

import { Stack, StackProps, CfnOutput } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as s3Deploy from 'aws-cdk-lib/aws-s3-deployment';

class s3Stack extends Stack {
  public readonly webSiteBucket: s3.Bucket;
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    // Create a new S3 bucket to host our website files
    this.webSiteBucket = new s3.Bucket(this, 'myWebSiteBucket', {
      publicReadAccess: true,
      websiteIndexDocument: 'index.html',
    // Specify the origin of our website assets to upload directly to the bucket
    new s3Deploy.BucketDeployment(this, 'myWebsiteBucketDeployement', {
      sources: [s3Deploy.Source.asset('../website-source/public')],
      destinationBucket: this.webSiteBucket,
    new CfnOutput(this, 'Bucket', { value: this.webSiteBucket.bucketName });
    new CfnOutput(this, 'Bucket URL path', {
      value: this.webSiteBucket.bucketWebsiteUrl,

export class InfraStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    new s3Stack(this, 'S3Stack');

Before we can experience the magic of CDK, we need to bootstrap it first.

cdk bootstrap
Bootstrapping CDK

Now let's deploy our S3 bucket‌

cdk deploy --all
Deploying S3 stack

If everything went fine, you will be able to see two outputs along with other information BucketURLpath and Bucket.

You can access now your website following the resulted URL. However, our folder website is empty so you will be met by a 404 Error. Don't worry! It's actually a good thing since it proves that our S3 is deployed and works just fine.

Chapter IV: Setting up a HUGO website

I will not go into depth in this chapter. You can use whatever technology you feel comfortable with. For the sake of this tutorial, I will follow these instructions to install a new theme for my Hugo website.

After making the necessary changes, execute the following command in order to build static files for our website.

hugo -D
Build static website

The result of the build can be found in the public folder.


cdk deploy --all
Redeploy the S3 bucket with the new static files

Now you will have a beautiful website hosted on S3 instead of a 404 error. (This is not the best way to update your website. We will discuss this later.)

To be continued ...

Leave a comment by becoming a member
Already have an account? Sign in