My Portfolio: a Cloud Resume Challenge
Tags: aws, nextjs, tailwindcss, graphql
Published: 2022-01-11 15:04:53

## Part 0: Intro
I have taken [The Cloud Resume Challenge](https://cloudresumechallenge.dev/) and would like to share my take on the challenge. I didn’t follow the steps exactly as laid out in the book. You can see the finished website here: [my website](https://pleng-nakdee.com/) and examples of the code here: [github.](https://github.com/PlengNakdee/my-portfolio-public) 

Some background about me. I used to work in film and documentary, but I felt burned out and stagnated. So I tried to find something else to do. I learned about coding from online classes for 2 years, before I got my first developer job. Now, I’m working as a Cloud Engineer.


## Part 1: Next.js, Tailwind CSS
Instead of HTML and CSS, I'm using Next.js and Tailwind CSS. I’ll not go into how to set them up, you can search for their documentation for that. The upside I see from using Tailwind is that it’s easier and faster to write than CSS. I used to spend so much time and frustration trying to get the responsiveness right, but now I don’t.

I don't think too much about the design. I like dark mode, so my website is mostly white text on black background. I didn’t spend much time on the frontend, compared to the backend. This is because I just want a website that looks good, not perfect, and has functions that I want. These functions are: showing my resume, showing my projects, and sending a contact form. I will talk about the contact form later on.

![Homepage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqhojssnp7370dn05qqs.png)
![Resume page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d33w6zg83u8anhy5iarn.png)


## Part 2: CDK, S3, CloudFront, Route 53 
I’m using AWS, you can see the infrastructure diagram here:
![Infrastructure diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvms49vsaqmy1hcgqivz.png)
The frontend lives in a S3 bucket, which will be served through CloudFront. I use CDK to create AWS resources. This is because CDK helps me define my infrastructure as a code and deploy it through ClodFormation.
My S3 is looking like this:

```
    const siteBucket = new Bucket(this, "SiteBucket", {
      websiteIndexDocument: "index.html",
      websiteErrorDocument: "404.html",
      publicReadAccess: true,
      removalPolicy: RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });
```
My CloudFront is looking like this:

```
    const cloudDist = new Distribution(this, "myDist", {
      defaultBehavior: { origin: new S3Origin(siteBucket) },
    });
```
I use Route 53 as DNS web service. It took me sometime to figuring out about DNS record type and how to route traffic from CloudFront to my domain name.

## Part 3: GraphQL, AppSync, DynamoDB
At the time of doing The Cloud Resume Challenge, I also worked on a client project that used the combination of GraphQL, AppSync and DynamoDB. So I just used what I already know on this project. I used this combination for a contact form function for my website.
![Contact form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhsygtqbrre8oo97u2qa.png)
Here is the dataflow diagram:
![dataflow diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wuyxpsoollaiw3jvjzb.png)
As CDK, this is how I create AppSync api, datasource and resolver:
```
const api = new GraphqlApi(this, 'TestApi', {
      name: 'TestApi',
      schema: Schema.fromAsset(join(this.schemaDir, 'schema.graphql')),
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: AuthorizationType.API_KEY,
        },
      },
    });

    new CfnOutput(this, 'ApiUrl', {
      value: api.graphqlUrl,
    });

    const messagesTableDS = api.addDynamoDbDataSource('messagesDataSource', messagesTable);

    messagesTableDS.createResolver({
      typeName: 'Mutation',
      fieldName: 'addMessage',
      requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
        PrimaryKey.partition('id').auto(),
        Values.projecting('input'),
      ),
      responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
    });`
```


## Part 4: Jest, Cypress
coming soon...