Hosting a static site with AWS CDK

ShareShare on LinkedIn.Share on Facebook.Share on Twitter.Share via email.
December 4, 2020
<p>Amazon Web Services Cloud Development Kit (<a rel="noreferrer noopener" target="_blank" href="https://aws.amazon.com/cdk/">AWS CDK</a>) is an abstraction layer working to generate Cloud Formation templates. It is a programmatic interface that can be used in tandem with command line tools to compile (JavaScript, TypeScript, Python, and others) into cloud formation templates. </p> <p>This is incredibly powerful. You can code a Front End application (React, Vue, Angular) and also your ENTIRE AWS stack within the same language, same repository, creating and deploy it using the same cicd tools. This reduces code silos, as a Front End developer you no longer have a mysterious AWS environment, and as the person or team managing the Front End Stack you can standardize and implement your organization’s best practices. This is a big shift left for developers so let’s go through an example.</p> <h2 class="wp-block-heading">Static Website – S3 + CloudFront + Route 53</h2> <p>One common pattern we at H3 put in place is the hosting of a static website in an S3 bucket, content served through Cloud Front (CF), and DNS managed by Route 53. The diagram below shows a rough architectural diagram.</p> <div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://wordpress.highwaythreesolutions.com/wp-content/uploads/2021/07/Screen-Shot-2020-12-04-at-3.19.24-PM.png" alt="AWS architecture diagram showing Route53, CloudFront, and an S3 bucket." class="wp-image-164" width="551" height="344" srcset="https://wordpress.highwaythreesolutions.com/wp-content/uploads/2021/07/Screen-Shot-2020-12-04-at-3.19.24-PM.png 734w, https://wordpress.highwaythreesolutions.com/wp-content/uploads/2021/07/Screen-Shot-2020-12-04-at-3.19.24-PM-300x188.png 300w" sizes="(max-width: 551px) 100vw, 551px"></figure></div> <p>Following an http request’s path, it first hits the DNS provider, Route 53 in our case. Traffic is directed from Route 53 to the CloudFront distribution via an A record within a hosted zone (e.g., would be directed to&nbsp;<code>5kj22l3ksjas.cloudfront.net/index.html</code></p> <ul><li>CloudFront has a caching layer. So sometimes the S3 object wont be retrieved.</li><li>If the S3 bucket is a static website, then pages like would result in a 404 error. We implement a simple Lambda Edge functions to check if request paths without the extension are objects in our S3 bucket (i.e., is the object in out S3 bucket). If so then we return that object rather than the file&nbsp;<code>blog</code></li></ul> <p>Each of these constructs, Route 53, CloudFront, S3, Lambda can be defined within the CDK. We will be writing our example using TypeScript. We will also assume you have some basic knowledge about the CDK, its setup and how to use it so we can get right into creating our stack library. If you don’t have that background knowledge see the&nbsp;<a rel="noreferrer noopener" target="_blank" href="https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html">AWS docs</a>.</p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cdk <span class="token keyword">from</span> <span class="token string">'@aws-cdk/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> s3 <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-s3'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cloudfront <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-cloudfront'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> acm <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-certificatemanager'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> lambda <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-lambda'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">H3_CERTIFICATE_ARN</span> <span class="token operator">=</span> <span class="token string">'arn-for-your-certification'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">StaticSite</span> <span class="token keyword">extends</span> <span class="token class-name">cdk</span><span class="token punctuation">.</span>Stack <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>scope<span class="token operator">:</span> cdk<span class="token punctuation">.</span>Construct<span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> props<span class="token operator">?</span><span class="token operator">:</span> cdk<span class="token punctuation">.</span>StackProps<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Force stack to be created in us-east-1 (lambda and cf restriction) */</span> <span class="token keyword">super</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> id<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token punctuation">,</span> env<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token operator">?.</span>env<span class="token punctuation">,</span> region<span class="token operator">:</span> <span class="token string">'us-east-1'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ... stack definition</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> <p>Above is the basic stack definition. We will be using the S3, CloudFront, ACM, and Lambda constructs. Since we have already created a wildcard certification we don’t have to create one for this stack. It seems like the best way to handle certification may be to create them beforehand. Since you may not have Route 53 handle your DNS records and creating a certificate takes some time. If you are not using AWS to manage your DNS you will have to certify your domain with AWS Certification Manager. Then after the initial deployment add an A record to route traffic from your domain to the CloudFront instance.</p> <p>First let’s just create an S3 bucket with default and&nbsp;<code>index.html</code></p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cdk <span class="token keyword">from</span> <span class="token string">'@aws-cdk/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> s3 <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-s3'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cloudfront <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-cloudfront'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> acm <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-certificatemanager'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> lambda <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-lambda'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">H3_CERTIFICATE_ARN</span> <span class="token operator">=</span> <span class="token string">'arn-for-your-certification'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">StaticSite</span> <span class="token keyword">extends</span> <span class="token class-name">cdk</span><span class="token punctuation">.</span>Stack <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>scope<span class="token operator">:</span> cdk<span class="token punctuation">.</span>Construct<span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> props<span class="token operator">?</span><span class="token operator">:</span> cdk<span class="token punctuation">.</span>StackProps<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Force stack to be created in us-east-1 (lambda and cf restriction) */</span> <span class="token keyword">super</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> id<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token punctuation">,</span> env<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token operator">?.</span>env<span class="token punctuation">,</span> region<span class="token operator">:</span> <span class="token string">'us-east-1'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">URL</span> <span class="token operator">=</span> <span class="token string">'cdktest.example.com'</span> <span class="token keyword">const</span> bucket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">s3</span><span class="token punctuation">.</span><span class="token function">Bucket</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token constant">URL</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> websiteErrorDocument<span class="token operator">:</span> <span class="token string">'404.html'</span><span class="token punctuation">,</span> websiteIndexDocument<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> removalPolicy<span class="token operator">:</span> cdk<span class="token punctuation">.</span>RemovalPolicy<span class="token punctuation">.</span><span class="token constant">DESTROY</span><span class="token punctuation">,</span> publicReadAccess<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> cors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> allowedOrigins<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'*'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> <span class="token punctuation">[</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">GET</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">POST</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">PUT</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">DELETE</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">HEAD</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> <p>We can deploy this stack by running the command or&nbsp;<code>npx cdk deploy</code></p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cdk <span class="token keyword">from</span> <span class="token string">'@aws-cdk/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> s3 <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-s3'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cloudfront <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-cloudfront'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> acm <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-certificatemanager'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> lambda <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-lambda'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">H3_CERTIFICATE_ARN</span> <span class="token operator">=</span> <span class="token string">'arn-for-your-certification'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">StaticSite</span> <span class="token keyword">extends</span> <span class="token class-name">cdk</span><span class="token punctuation">.</span>Stack <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>scope<span class="token operator">:</span> cdk<span class="token punctuation">.</span>Construct<span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> props<span class="token operator">?</span><span class="token operator">:</span> cdk<span class="token punctuation">.</span>StackProps<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Force stack to be created in us-east-1 (lambda and cf restriction) */</span> <span class="token keyword">super</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> id<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token punctuation">,</span> env<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token operator">?.</span>env<span class="token punctuation">,</span> region<span class="token operator">:</span> <span class="token string">'us-east-1'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">URL</span> <span class="token operator">=</span> <span class="token string">'cdktest.example.com'</span> <span class="token keyword">const</span> bucket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">s3</span><span class="token punctuation">.</span><span class="token function">Bucket</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token constant">URL</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> websiteErrorDocument<span class="token operator">:</span> <span class="token string">'404.html'</span><span class="token punctuation">,</span> websiteIndexDocument<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> removalPolicy<span class="token operator">:</span> cdk<span class="token punctuation">.</span>RemovalPolicy<span class="token punctuation">.</span><span class="token constant">DESTROY</span><span class="token punctuation">,</span> publicReadAccess<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> cors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> allowedOrigins<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'*'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> <span class="token punctuation">[</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">GET</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">POST</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">PUT</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">DELETE</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">HEAD</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> cf <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">cloudfront</span><span class="token punctuation">.</span><span class="token function">CloudFrontWebDistribution</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">cf-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span> defaultRootObject<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> originConfigs<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> s3OriginSource<span class="token operator">:</span> <span class="token punctuation">{</span> s3BucketSource<span class="token operator">:</span> bucket <span class="token punctuation">}</span><span class="token punctuation">,</span> behaviors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> cachedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedCachedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> isDefaultBehavior<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> <p>This is a very simple CloudFront distribution. Let’s fill it out with some custom Behaviors for error pages (line 58-ish), and setup the certification (line 47 and line 91-ish).</p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cdk <span class="token keyword">from</span> <span class="token string">'@aws-cdk/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> s3 <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-s3'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cloudfront <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-cloudfront'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> acm <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-certificatemanager'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> lambda <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-lambda'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">H3_CERTIFICATE_ARN</span> <span class="token operator">=</span> <span class="token string">'arn-for-your-certification'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">StaticSite</span> <span class="token keyword">extends</span> <span class="token class-name">cdk</span><span class="token punctuation">.</span>Stack <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>scope<span class="token operator">:</span> cdk<span class="token punctuation">.</span>Construct<span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> props<span class="token operator">?</span><span class="token operator">:</span> cdk<span class="token punctuation">.</span>StackProps<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Force stack to be created in us-east-1 (lambda and cf restriction) */</span> <span class="token keyword">super</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> id<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token punctuation">,</span> env<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token operator">?.</span>env<span class="token punctuation">,</span> region<span class="token operator">:</span> <span class="token string">'us-east-1'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">URL</span> <span class="token operator">=</span> <span class="token string">'cdktest.highwaythreesolutions.com'</span> <span class="token keyword">const</span> bucket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">s3</span><span class="token punctuation">.</span><span class="token function">Bucket</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token constant">URL</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> websiteErrorDocument<span class="token operator">:</span> <span class="token string">'404.html'</span><span class="token punctuation">,</span> websiteIndexDocument<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> removalPolicy<span class="token operator">:</span> cdk<span class="token punctuation">.</span>RemovalPolicy<span class="token punctuation">.</span><span class="token constant">DESTROY</span><span class="token punctuation">,</span> publicReadAccess<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> cors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> allowedOrigins<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'*'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> <span class="token punctuation">[</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">GET</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">POST</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">PUT</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">DELETE</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">HEAD</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">/** * Load Site Certification object for association with Cloud Front instance */</span> <span class="token keyword">const</span> siteCertificate <span class="token operator">=</span> acm<span class="token punctuation">.</span>Certificate<span class="token punctuation">.</span><span class="token function">fromCertificateArn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'site-cert'</span><span class="token punctuation">,</span> <span class="token constant">H3_CERTIFICATE_ARN</span><span class="token punctuation">)</span> <span class="token comment">/** * Define Cloud Front Instance */</span> <span class="token keyword">const</span> cf <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">cloudfront</span><span class="token punctuation">.</span><span class="token function">CloudFrontWebDistribution</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">cf-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span> defaultRootObject<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> errorConfigurations<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">404</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">404</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">403</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">403</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">405</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">405</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">500</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">500</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> originConfigs<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> s3OriginSource<span class="token operator">:</span> <span class="token punctuation">{</span> s3BucketSource<span class="token operator">:</span> bucket <span class="token punctuation">}</span><span class="token punctuation">,</span> behaviors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> cachedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedCachedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> isDefaultBehavior<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> viewerCertificate<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>ViewerCertificate<span class="token punctuation">.</span><span class="token function">fromAcmCertificate</span><span class="token punctuation">(</span> siteCertificate<span class="token punctuation">,</span> <span class="token punctuation">{</span> aliases<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token constant">URL</span><span class="token punctuation">]</span><span class="token punctuation">,</span> securityPolicy<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>SecurityPolicyProtocol<span class="token punctuation">.</span><span class="token constant">TLS_V1</span><span class="token punctuation">,</span> sslMethod<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>SSLMethod<span class="token punctuation">.</span><span class="token constant">SNI</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> <p>Okay great! Now if this stack is deployed we’ll have a secured HTTP site, custom error messages, that serves a static site. In 100-ish lines of code! Now for some optional fun stuff. Since this is a static site, we should handle the request like a webserver would, directing traffic from to&nbsp;<code>/page.html</code></p> <p>The Lambda function is really simple, it just checks if the request URI for the absence of a&nbsp;<code>.html</code></p> <pre class="wp-block-code language-javascript"><code><span class="token string">'use strict'</span><span class="token punctuation">;</span> exports<span class="token punctuation">.</span><span class="token function-variable function">handler</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> request <span class="token operator">=</span> event<span class="token punctuation">.</span>Records<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>cf<span class="token punctuation">.</span>request<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">/</span><span class="token operator">^</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">+([dws+_-!@=#$%&amp;*]+))+$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span>uri<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> request<span class="token punctuation">.</span>uri <span class="token operator">=</span> request<span class="token punctuation">.</span>uri <span class="token operator">+</span> <span class="token string">'.html'</span><span class="token punctuation">;</span> <span class="token keyword">return</span> request<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> request<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre> <p>and the Stack definition will now look like the following (changes on line 52-56 and line 99-102)</p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cdk <span class="token keyword">from</span> <span class="token string">'@aws-cdk/core'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> s3 <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-s3'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> cloudfront <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-cloudfront'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> acm <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-certificatemanager'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> lambda <span class="token keyword">from</span> <span class="token string">'@aws-cdk/aws-lambda'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">H3_CERTIFICATE_ARN</span> <span class="token operator">=</span> <span class="token string">'arn-for-your-certification'</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">StaticSite</span> <span class="token keyword">extends</span> <span class="token class-name">cdk</span><span class="token punctuation">.</span>Stack <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>scope<span class="token operator">:</span> cdk<span class="token punctuation">.</span>Construct<span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> props<span class="token operator">?</span><span class="token operator">:</span> cdk<span class="token punctuation">.</span>StackProps<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Force stack to be created in us-east-1 (lambda and cf restriction) */</span> <span class="token keyword">super</span><span class="token punctuation">(</span>scope<span class="token punctuation">,</span> id<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token punctuation">,</span> env<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span>props<span class="token operator">?.</span>env<span class="token punctuation">,</span> region<span class="token operator">:</span> <span class="token string">'us-east-1'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">URL</span> <span class="token operator">=</span> <span class="token string">'cdktest.highwaythreesolutions.com'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> bucket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">s3</span><span class="token punctuation">.</span><span class="token function">Bucket</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token constant">URL</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> websiteErrorDocument<span class="token operator">:</span> <span class="token string">'404.html'</span><span class="token punctuation">,</span> websiteIndexDocument<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> removalPolicy<span class="token operator">:</span> cdk<span class="token punctuation">.</span>RemovalPolicy<span class="token punctuation">.</span><span class="token constant">DESTROY</span><span class="token punctuation">,</span> publicReadAccess<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> cors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> allowedOrigins<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'*'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> <span class="token punctuation">[</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">GET</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">POST</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">PUT</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">DELETE</span><span class="token punctuation">,</span> s3<span class="token punctuation">.</span>HttpMethods<span class="token punctuation">.</span><span class="token constant">HEAD</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/** * Load Site Certification object for association with Cloud Front instance */</span> <span class="token keyword">const</span> siteCertificate <span class="token operator">=</span> acm<span class="token punctuation">.</span>Certificate<span class="token punctuation">.</span><span class="token function">fromCertificateArn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'site-cert'</span><span class="token punctuation">,</span> <span class="token constant">H3_CERTIFICATE_ARN</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> nonHtmlRequestFunction <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">lambda</span><span class="token punctuation">.</span><span class="token function">Function</span><span class="token punctuation">(</span> <span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'LambdaEdgeRedirect'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> runtime<span class="token operator">:</span> lambda<span class="token punctuation">.</span>Runtime<span class="token punctuation">.</span><span class="token constant">NODEJS_12_X</span><span class="token punctuation">,</span> handler<span class="token operator">:</span> <span class="token string">'index.handler'</span><span class="token punctuation">,</span> code<span class="token operator">:</span> lambda<span class="token punctuation">.</span>Code<span class="token punctuation">.</span><span class="token function">fromAsset</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'lambdas'</span><span class="token punctuation">,</span> <span class="token string">'static-web-hosting'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/** * Define Cloud Front Instance */</span> <span class="token keyword">const</span> cf <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">cloudfront</span><span class="token punctuation">.</span><span class="token function">CloudFrontWebDistribution</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">cf-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{</span> defaultRootObject<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span> errorConfigurations<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">404</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">403</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">405</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> errorCode<span class="token operator">:</span> <span class="token number">500</span><span class="token punctuation">,</span> errorCachingMinTtl<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> responseCode<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> responsePagePath<span class="token operator">:</span> <span class="token string">'/404.html'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> originConfigs<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> s3OriginSource<span class="token operator">:</span> <span class="token punctuation">{</span> s3BucketSource<span class="token operator">:</span> bucket <span class="token punctuation">}</span><span class="token punctuation">,</span> behaviors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> cachedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedCachedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> isDefaultBehavior<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> allowedMethods<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>CloudFrontAllowedMethods<span class="token punctuation">.</span><span class="token constant">GET_HEAD_OPTIONS</span><span class="token punctuation">,</span> lambdaFunctionAssociations<span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span> eventType<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>LambdaEdgeEventType<span class="token punctuation">.</span><span class="token constant">ORIGIN_REQUEST</span><span class="token punctuation">,</span> lambdaFunction<span class="token operator">:</span> nonHtmlRequestFunction<span class="token punctuation">.</span>currentVersion <span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> viewerCertificate<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>ViewerCertificate<span class="token punctuation">.</span><span class="token function">fromAcmCertificate</span><span class="token punctuation">(</span>siteCertificate<span class="token punctuation">,</span> <span class="token punctuation">{</span> aliases<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token constant">URL</span><span class="token punctuation">]</span><span class="token punctuation">,</span> securityPolicy<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>SecurityPolicyProtocol<span class="token punctuation">.</span><span class="token constant">TLS_V1</span><span class="token punctuation">,</span> sslMethod<span class="token operator">:</span> cloudfront<span class="token punctuation">.</span>SSLMethod<span class="token punctuation">.</span><span class="token constant">SNI</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre> <h2 class="wp-block-heading">Adding A Record to Route 53</h2> <p>If your DNS provider is AWS (Route 53), then we can create the A record with the following lines of code:</p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">const</span> zone <span class="token operator">=</span> r53<span class="token punctuation">.</span>HostedZone<span class="token punctuation">.</span><span class="token function">fromLookup</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'H3-SiteZones'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> domainName<span class="token operator">:</span> <span class="token constant">DOMAIN_NAME</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">new</span> <span class="token class-name">r53</span><span class="token punctuation">.</span><span class="token function">ARecord</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'DistributionRecord'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> recordName<span class="token operator">:</span> <span class="token constant">URL</span><span class="token punctuation">,</span> zone<span class="token operator">:</span> zone<span class="token punctuation">,</span> target<span class="token operator">:</span> r53<span class="token punctuation">.</span>RecordTarget<span class="token punctuation">.</span><span class="token function">fromAlias</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token function-variable function">bind</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> hostedZoneId<span class="token operator">:</span> r53T<span class="token punctuation">.</span>CloudFrontTarget<span class="token punctuation">.</span><span class="token function">getHostedZoneId</span><span class="token punctuation">(</span>cf<span class="token punctuation">)</span><span class="token punctuation">,</span> dnsName<span class="token operator">:</span> cf<span class="token punctuation">.</span>distributionDomainName <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> <p>where is defined from the import&nbsp;<code>import * as r53 from '@aws-cdk/aws-route53'</code></p> <h2 class="wp-block-heading">Deployment options</h2> <p>By adding the following code snippet you can deploy a folder as your static site.</p> <pre class="wp-block-code language-typescript"><code><span class="token keyword">new</span> <span class="token class-name">s3deploy</span><span class="token punctuation">.</span><span class="token function">BucketDeployment</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">'DeployWebsite'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> sources<span class="token operator">:</span> <span class="token punctuation">[</span>s3deploy<span class="token punctuation">.</span>Source<span class="token punctuation">.</span><span class="token function">asset</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'..'</span><span class="token punctuation">,</span> <span class="token string">'website-dist'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">,</span> destinationBucket<span class="token operator">:</span> bucket<span class="token punctuation">,</span> retainOnDelete<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> <p>The example stack has been updated with some quality of life/reusability improvements to in the&nbsp;<a rel="noreferrer noopener" target="_blank" href="https://github.com/HighwayThree/aws-cdk-static-site-stack">Github Repo</a>. I encourage you to check out the updates.</p> <div class="wp-block-buttons is-content-justification-center is-layout-flex wp-block-buttons-is-layout-flex"> <div class="wp-block-button is-style-h3-cta-button"><a class="wp-block-button__link" href="/contact?subject=Hosting%20A%20Static%20Website%20With%20AWS%20CDK" target="_blank" rel="noopener">Contact us for more information on anything DevOps</a></div> </div>