DIY SvelteKit CDK adapter
Tags: svelte, sveltekit, aws, cdk
Published: 2021-04-05 23:52:09


> Update on 2021-10-30
>
> You should also check out [my SvelteKit-CDK adapter](https://github.com/juranki/sveltekit-cdk).
> It covers everything discussed in this article. While not even close to stable, it's cleaner and has better structure. And has a wrapper for Lambda@Edge, too. 


Below are notes of me putting together [sveltekit](https://kit.svelte.dev/) and [AWS CDK](https://aws.amazon.com/cdk/). Explanations are minimal. Familiarity with both SvelteKit and CDK is probably required to follow. 

At the moment [@sveltejs/kit](https://www.npmjs.com/package/@sveltejs/kit) version is 1.0.0-next.71, and the adapter interface is not stable, so this solution is likely to break as time passes.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2g8uj65ot7i8xgl7uzg3.png)

### 1. Init SvelteKit project

``` bash
~$ mkdir sveltekit-cdk
~$ cd sveltekit-cdk/
~/sveltekit-cdk$ npm init svelte@next
   ...
   (I chose typescript/CSS/no eslint/no prettier)
   ...
~/sveltekit-cdk$ npm install
~/sveltekit-cdk$ git init
~/sveltekit-cdk$ git add .
~/sveltekit-cdk$ git commit -m "init svelte"
```

### 2. Init CDK project for adapter

``` bash
~/sveltekit-cdk$ mkdir adapter
~/sveltekit-cdk$ cd adapter
~/sveltekit-cdk/adapter$ npx cdk init --language typescript
~/sveltekit-cdk/adapter$ git add .
~/sveltekit-cdk/adapter$ git commit -m "init CDK"
```

### 3. Replace node adapter with a dummy adapter

This is our dummy adapter ([adapter/adapter.ts](https://github.com/juranki/diy-sveltekit-cdk-adapter/blob/a73ce710cf25b6cc43d8b0e740df34d8c81f7e68/adapter))
```typescript
import type { Adapter } from '@sveltejs/kit'

export const adapter: Adapter = {
    name: 'MAGIC',
    async adapt(utils): Promise<void> {
        console.log('TODO...')
    }
}
```

To be able to use typescript for the adapter without extra compilation steps, lets add a little [ts-node](https://github.com/TypeStrong/ts-node) wrapper ([adapter/index.js](https://github.com/juranki/diy-sveltekit-cdk-adapter/blob/a73ce710cf25b6cc43d8b0e740df34d8c81f7e68/adapter/index.js))
```javascript
require('ts-node').register()
module.exports = require('./adapter.ts').adapter
```

Finally, node adapter is replaced in [svelte.config.js](https://github.com/juranki/diy-sveltekit-cdk-adapter/blob/a73ce710cf25b6cc43d8b0e740df34d8c81f7e68/svelte.config.cjs) with our adapter
```diff
- const node = require('@sveltejs/adapter-node');
+ const cdkAdapter = require('./adapter/index.js')


- 		// By default, `npm run build` will create a standard Node app.
- 		// You can create optimized builds for different platforms by
- 		// specifying a different adapter
- 		adapter: node(),
+ 		adapter: cdkAdapter,
```

To make ts-node wrapper work, I had to comment out `"module": "es2020",` from tsconfig.json. [Full commit here.](https://github.com/juranki/diy-sveltekit-cdk-adapter/commit/a73ce710cf25b6cc43d8b0e740df34d8c81f7e68)

And try it out
```bash
$ npm run build

> sveltekit-cdk@0.0.1 build /workspaces/sveltekit-cdk
> svelte-kit build

vite v2.1.5 building for production...
✓ 18 modules transformed.
.svelte/output/client/_app/manifest.json                            0.67kb
.svelte/output/client/_app/assets/start-d4cd1237.css                0.29kb / brotli: 0.18kb
.svelte/output/client/_app/assets/pages/index.svelte-27172613.css   0.69kb / brotli: 0.26kb
.svelte/output/client/_app/pages/index.svelte-f28bc36b.js           1.58kb / brotli: 0.68kb
.svelte/output/client/_app/chunks/vendor-57a96aae.js                5.14kb / brotli: 2.00kb
.svelte/output/client/_app/start-ff890ac9.js                        15.52kb / brotli: 5.29kb
vite v2.1.5 building SSR bundle for production...
✓ 16 modules transformed.
.svelte/output/server/app.js   70.57kb

Run npm start to try your app locally.

> Using MAGIC
TODO...
  ✔ done
```

### 4. Capture Svelte output

Svelte files are copied to a place that is easy to include to CDK stack.

```diff
export const adapter: Adapter = {
    name: 'MAGIC',
    async adapt(utils): Promise<void> {
-        console.log('TODO...')
+        const contentPath = path.join(__dirname, 'content')
+        rmRecursive(contentPath)
+        const serverPath = path.join(contentPath, 'server')
+        const staticPath = path.join(contentPath, 'static')
+        utils.copy_server_files(serverPath)
+        utils.copy_client_files(staticPath)
+        utils.copy_static_files(staticPath)
    }
}
```

Svelte kit provides nice utilities for storing the files to desired folders. Here, the SSR implementation is put to server folder, and will be later deployed to a lambda function. And client and static files are stored to static folder, and will be later deployed to S3.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m25qsjo69nfnfggcsgz2.png)

[Full commit](https://github.com/juranki/diy-sveltekit-cdk-adapter/commit/55090be4942ab3f01b56826d6bac88b0e4f3b869)

### 5. Create a Lambda wrapper for SSR

This lambda handler maps the [API gateway request and response](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) to what SSR implementation expects.

```javascript
import { URLSearchParams } from 'url';
import { render } from '../content/server/app.js'

export async function handler(event) {
    const { path, headers, multiValueQueryStringParameters } = event;

    const query = new URLSearchParams();
    if (multiValueQueryStringParameters) {
        Object.keys(multiValueQueryStringParameters).forEach(k => {
            const vs = multiValueQueryStringParameters[k]
            vs.forEach(v => {
                query.append(k, v)
            })
        })
    }

    const rendered = await render({
        host: event.requestContext.domainName,
        method: event.httpMethod,
        body: JSON.parse(event.body), // TODO: other payload types
        headers,
        query,
        path,
    })

    if (rendered) {
        const resp = {
            headers: {},
            multiValueHeaders: {},
            body: rendered.body,
            statusCode: rendered.status
        }
        Object.keys(rendered.headers).forEach(k => {
            const v = rendered.headers[k]
            if (v instanceof Array) {
                resp.multiValueHeaders[k] = v
            } else {
                resp.headers[k] = v
            }
        })
        return resp
    }
    return {
        statusCode: 404,
        body: 'Not found.'
    }
}
```

And it needs to be bundled for deployment to lambda

```diff

export const adapter: Adapter = {
    name: 'MAGIC',
    async adapt(utils): Promise<void> {
        const contentPath = path.join(__dirname, 'content')
        rmRecursive(contentPath)
        const serverPath = path.join(contentPath, 'server')
        const staticPath = path.join(contentPath, 'static')
        utils.copy_server_files(serverPath)
        utils.copy_client_files(staticPath)
        utils.copy_static_files(staticPath)
+  
+       const bundler = new ParcelBundler(
+            [path.join(__dirname, 'lambda', 'index.js')],
+            {
+                outDir: path.join(contentPath, 'server-bundle'),
+                bundleNodeModules: true,
+                target: 'node',
+                sourceMaps: false,
+                minify: false,
+            },
+        )
+        await bundler.bundle()

    }
}
```

[Full commit here.](https://github.com/juranki/diy-sveltekit-cdk-adapter/commit/442ee7cf89c1126415af4dcb3a877d376fa875c0)

### 6. Create CDK Stack

This is a barebones stack for deploying the site. The only non-trivial parts are the routing configuration that is generated from the contents of the static folder, and that I configured CDN to pass session cookies through to SSR handler.

```typescript
import * as cdk from '@aws-cdk/core'
import * as lambda  from '@aws-cdk/aws-lambda'
import * as gw from '@aws-cdk/aws-apigatewayv2'
import * as s3  from '@aws-cdk/aws-s3'
import * as s3depl from '@aws-cdk/aws-s3-deployment'
import { LambdaProxyIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'
import * as cdn from '@aws-cdk/aws-cloudfront'
import * as fs from 'fs';
import * as path from 'path';


interface AdapterProps extends cdk.StackProps {
  serverPath: string
  staticPath: string
}

export class AdapterStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props: AdapterProps) {
    super(scope, id, props);

    const handler = new lambda.Function(this, 'handler', {
      code: new lambda.AssetCode(props?.serverPath),
      handler: 'index.handler',
      runtime: lambda.Runtime.NODEJS_14_X,
    })
    
    const api = new gw.HttpApi(this, 'api')
    api.addRoutes({
      path: '/{proxy+}',
      methods: [gw.HttpMethod.ANY],
      integration: new LambdaProxyIntegration({
        handler,
        payloadFormatVersion: gw.PayloadFormatVersion.VERSION_1_0,
      })
    })

    const staticBucket = new s3.Bucket(this, 'staticBucket')
    const staticDeployment = new s3depl.BucketDeployment(this, 'staticDeployment', {
      destinationBucket: staticBucket,
      sources: [s3depl.Source.asset(props.staticPath)]
    })

    const staticID = new cdn.OriginAccessIdentity(this, 'staticID')
    staticBucket.grantRead(staticID)

    const distro = new cdn.CloudFrontWebDistribution(this, 'distro', {
      priceClass: cdn.PriceClass.PRICE_CLASS_100,
      defaultRootObject: '',
      originConfigs: [
        {
          customOriginSource: {
            domainName: cdk.Fn.select(1, cdk.Fn.split('://', api.apiEndpoint)),
            originProtocolPolicy: cdn.OriginProtocolPolicy.HTTPS_ONLY,
          },
          behaviors: [
            {
              allowedMethods: cdn.CloudFrontAllowedMethods.ALL,
              forwardedValues: {
                queryString: false,
                cookies: {
                  forward: 'whitelist',
                  whitelistedNames: ['sid', 'sid.sig']
                }
              },
              isDefaultBehavior: true
            }
          ]
        },
        {
          s3OriginSource: {
            s3BucketSource: staticBucket,
            originAccessIdentity: staticID,
          },
          behaviors: mkStaticRoutes(props.staticPath)
        }
      ]
    })

  }
}

function mkStaticRoutes(staticPath: string): cdn.Behavior[] {
  return fs.readdirSync(staticPath).map(f => {
    const fullPath = path.join(staticPath, f)
    const stat = fs.statSync(fullPath)
    if (stat.isDirectory()) {
      return {
        pathPattern: `/${f}/*`,
      }
    }
    return { pathPattern: `/${f}` }
  })
}
```
Check [full commit](https://github.com/juranki/diy-sveltekit-cdk-adapter/commit/43cb58e62f1c96d204e0e884b24b60ece470c46e) to see [how cdk deploy is invoked](https://github.com/juranki/diy-sveltekit-cdk-adapter/blob/43cb58e62f1c96d204e0e884b24b60ece470c46e/adapter/adapter.ts#L44-L57) and [parameters passed to the stack](https://github.com/juranki/diy-sveltekit-cdk-adapter/blob/43cb58e62f1c96d204e0e884b24b60ece470c46e/adapter/bin/adapter.ts#L8-L13)

```bash
$ export ACCOUNT=234......23
$ export REGION=eu-north-1
$ npm run build
> sveltekit-cdk@0.0.1 build /workspaces/sveltekit-cdk> svelte-kit build

vite v2.1.5 building for production...
✓ 18 modules transformed.
.svelte/output/client/_app/manifest.json                            0.67kb
.svelte/output/client/_app/assets/start-d4cd1237.css                0.29kb / brotli: 0.18kb
.svelte/output/client/_app/assets/pages/index.svelte-27172613.css   0.69kb / brotli: 0.26kb
.svelte/output/client/_app/pages/index.svelte-f28bc36b.js           1.58kb / brotli: 0.68kb
.svelte/output/client/_app/chunks/vendor-57a96aae.js                5.14kb / brotli: 2.00kb
.svelte/output/client/_app/start-ff890ac9.js                        15.52kb / brotli: 5.29kb
vite v2.1.5 building SSR bundle for production...
✓ 16 modules transformed.
.svelte/output/server/app.js   70.57kb

Run npm start to try your app locally.

> Using MAGIC
✨  Built in 1.45s.

adapter/content/server-bundle/index.js    83.97 KB    1.14s
  ✔ done
AdapterStack: deploying...
[0%] start: Publishing 77fee73b537c2786a56a5ae730eecc3d1121be2512b210c0ad7f92a87ba52125:current
[25%] success: Published 77fee73b537c2786a56a5ae730eecc3d1121be2512b210c0ad7f92a87ba52125:current
[25%] start: Publishing e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:current
[50%] success: Published e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:current
[50%] start: Publishing c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf:current
[75%] success: Published c24b999656e4fe6c609c31bae56a1cf4717a405619c3aa6ba1bc686b8c2c86cf:current
[75%] start: Publishing 9ab01d8ba7648b72beed50ec3fad310aef1e1af2bf56f3912d53a56e03579ece:current
[100%] success: Published 9ab01d8ba7648b72beed50ec3fad310aef1e1af2bf56f3912d53a56e03579ece:current
AdapterStack: creating CloudFormation changeset...
  0/18 | 11:07:37 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack                      | AdapterStack User Initiated
  0/18 | 11:07:43 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack                      | AdapterStack User Initiated
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                                  | handler/ServiceRole (handlerServiceRole187D5A5A) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::S3::Bucket                                 | staticBucket (staticBucket49CE0992) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                                  | handler/ServiceRole (handlerServiceRole187D5A5A) Resource creation Initiated
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::CloudFront::CloudFrontOriginAccessIdentity | staticID (staticID76F07208) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Api                          | api (apiC8550315) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                              | CDKMetadata/Default (CDKMetadata) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                                  | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265) 
  1/18 | 11:08:16 PM | CREATE_IN_PROGRESS   | AWS::Lambda::LayerVersion                       | staticDeployment/AwsCliLayer (staticDeploymentAwsCliLayerCF83B634) 
  1/18 | 11:08:17 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role                                  | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265) Resource creation Initiated
  1/18 | 11:08:17 PM | CREATE_IN_PROGRESS   | AWS::S3::Bucket                                 | staticBucket (staticBucket49CE0992) Resource creation Initiated
  1/18 | 11:08:18 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                              | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
  1/18 | 11:08:18 PM | CREATE_COMPLETE      | AWS::CDK::Metadata                              | CDKMetadata/Default (CDKMetadata) 
  1/18 | 11:08:18 PM | CREATE_IN_PROGRESS   | AWS::CloudFront::CloudFrontOriginAccessIdentity | staticID (staticID76F07208) Resource creation Initiated
  4/18 | 11:08:18 PM | CREATE_COMPLETE      | AWS::CloudFront::CloudFrontOriginAccessIdentity | staticID (staticID76F07208) 
  4/18 | 11:08:18 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Api                          | api (apiC8550315) Resource creation Initiated
  4/18 | 11:08:18 PM | CREATE_COMPLETE      | AWS::ApiGatewayV2::Api                          | api (apiC8550315) 
  4/18 | 11:08:20 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Stage                        | api/DefaultStage (apiDefaultStage04B80AC9) 
  4/18 | 11:08:22 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Stage                        | api/DefaultStage (apiDefaultStage04B80AC9) Resource creation Initiated
  4/18 | 11:08:22 PM | CREATE_COMPLETE      | AWS::ApiGatewayV2::Stage                        | api/DefaultStage (apiDefaultStage04B80AC9) 
  5/18 | 11:08:32 PM | CREATE_IN_PROGRESS   | AWS::Lambda::LayerVersion                       | staticDeployment/AwsCliLayer (staticDeploymentAwsCliLayerCF83B634) Resource creation Initiated
  5/18 | 11:08:33 PM | CREATE_COMPLETE      | AWS::Lambda::LayerVersion                       | staticDeployment/AwsCliLayer (staticDeploymentAwsCliLayerCF83B634) 
  9/18 | 11:08:34 PM | CREATE_COMPLETE      | AWS::IAM::Role                                  | handler/ServiceRole (handlerServiceRole187D5A5A) 
  9/18 | 11:08:35 PM | CREATE_COMPLETE      | AWS::IAM::Role                                  | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265) 
  9/18 | 11:08:37 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Function                           | handler (handlerE1533BD5) 
  9/18 | 11:08:37 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Function                           | handler (handlerE1533BD5) Resource creation Initiated
  9/18 | 11:08:37 PM | CREATE_COMPLETE      | AWS::Lambda::Function                           | handler (handlerE1533BD5) 
  9/18 | 11:08:38 PM | CREATE_COMPLETE      | AWS::S3::Bucket                                 | staticBucket (staticBucket49CE0992) 
 12/18 | 11:08:39 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Permission                         | api/ANY--{proxy+}/AdapterStackapiANYproxy1E757BCE-Permission (apiANYproxyAdapterStackapiANYproxy1E757BCEPermission4DD3BE97) 
 12/18 | 11:08:39 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Integration                  | api/ANY--{proxy+}/HttpIntegration-addabd80f5f992d479db94f5bda52ee5 (apiANYproxyHttpIntegrationaddabd80f5f992d479db94f5bda52ee5449897FD) 
 12/18 | 11:08:40 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy                                | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF) 
 12/18 | 11:08:40 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Permission                         | api/ANY--{proxy+}/AdapterStackapiANYproxy1E757BCE-Permission (apiANYproxyAdapterStackapiANYproxy1E757BCEPermission4DD3BE97) Resource creation Initiated
 12/18 | 11:08:40 PM | CREATE_IN_PROGRESS   | AWS::S3::BucketPolicy                           | staticBucket/Policy (staticBucketPolicyA47383C0) 
 12/18 | 11:08:41 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Integration                  | api/ANY--{proxy+}/HttpIntegration-addabd80f5f992d479db94f5bda52ee5 (apiANYproxyHttpIntegrationaddabd80f5f992d479db94f5bda52ee5449897FD) Resource creation Initiated
 12/18 | 11:08:41 PM | CREATE_COMPLETE      | AWS::ApiGatewayV2::Integration                  | api/ANY--{proxy+}/HttpIntegration-addabd80f5f992d479db94f5bda52ee5 (apiANYproxyHttpIntegrationaddabd80f5f992d479db94f5bda52ee5449897FD) 
 12/18 | 11:08:41 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy                                | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF) Resource creation Initiated
 12/18 | 11:08:41 PM | CREATE_IN_PROGRESS   | AWS::S3::BucketPolicy                           | staticBucket/Policy (staticBucketPolicyA47383C0) Resource creation Initiated
 12/18 | 11:08:41 PM | CREATE_COMPLETE      | AWS::S3::BucketPolicy                           | staticBucket/Policy (staticBucketPolicyA47383C0) 
 12/18 | 11:08:43 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Route                        | api/ANY--{proxy+} (apiANYproxy1413EA65) 
 12/18 | 11:08:43 PM | CREATE_IN_PROGRESS   | AWS::ApiGatewayV2::Route                        | api/ANY--{proxy+} (apiANYproxy1413EA65) Resource creation Initiated
 12/18 | 11:08:44 PM | CREATE_COMPLETE      | AWS::ApiGatewayV2::Route                        | api/ANY--{proxy+} (apiANYproxy1413EA65) 
 13/18 | 11:08:50 PM | CREATE_COMPLETE      | AWS::Lambda::Permission                         | api/ANY--{proxy+}/AdapterStackapiANYproxy1E757BCE-Permission (apiANYproxyAdapterStackapiANYproxy1E757BCEPermission4DD3BE97) 
 14/18 | 11:08:58 PM | CREATE_IN_PROGRESS   | AWS::CloudFront::Distribution                   | distro/CFDistribution (distroCFDistributionB272DD5C) 
 14/18 | 11:08:58 PM | CREATE_COMPLETE      | AWS::IAM::Policy                                | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF) 
 14/18 | 11:09:00 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Function                           | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536) 
 14/18 | 11:09:02 PM | CREATE_IN_PROGRESS   | AWS::CloudFront::Distribution                   | distro/CFDistribution (distroCFDistributionB272DD5C) Resource creation Initiated
 15/18 | 11:09:04 PM | CREATE_IN_PROGRESS   | AWS::Lambda::Function                           | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536) Resource creation Initiated
 15/18 | 11:09:05 PM | CREATE_COMPLETE      | AWS::Lambda::Function                           | Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536) 
 15/18 | 11:09:07 PM | CREATE_IN_PROGRESS   | Custom::CDKBucketDeployment                     | staticDeployment/CustomResource/Default (staticDeploymentCustomResource41B995BA) 
 16/18 | 11:09:39 PM | CREATE_IN_PROGRESS   | Custom::CDKBucketDeployment                     | staticDeployment/CustomResource/Default (staticDeploymentCustomResource41B995BA) Resource creation Initiated
 16/18 | 11:09:39 PM | CREATE_COMPLETE      | Custom::CDKBucketDeployment                     | staticDeployment/CustomResource/Default (staticDeploymentCustomResource41B995BA) 
16/18 Currently in progress: AdapterStack, distroCFDistributionB272DD5C
 18/18 | 11:11:19 PM | CREATE_COMPLETE      | AWS::CloudFront::Distribution                   | distro/CFDistribution (distroCFDistributionB272DD5C) 
 18/18 | 11:11:20 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack                      | AdapterStack 

 ✅  AdapterStack

Stack ARN:
arn:aws:cloudformation:eu-north-1:3123....123:stack/AdapterStack/b653b540-9663-11eb-b7b2-0eab76d49478
```

#### Hurrah!!

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfeadvedmdtc7pbd9lhj.png)
 

{% github https://github.com/juranki/diy-sveltekit-cdk-adapter no-readme %}

---

> Cover photo by <a href="https://unsplash.com/@alistairmacrobert?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Alistair MacRobert</a> on <a href="https://unsplash.com/s/photos/tangle?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>