Nice work all around. I can tell you followed the spec very thoroughly and your attention to detail stands out, especially in your testing and CI/CD workflow. Great work.
Just a few overall code comments as you take your AWS and serverless development skills to the next level:
Your front end website looks lovely, only thing that jumps out to me at first glance is make sure you add a favicon!
Consider using structured JSON objects as logs in your Lambda function -- this makes them easier to search and filter in log analysis platforms. (Very important if you have lots of users hitting your Lambdas!) Here is a great post with some ideas on how to structure Lambda logs: https://theburningmonk.com/2018/01/you-need-to-use-structured-logging-with-aws-lambda/
I believe there may be a subtle bug in your DynamoDB UpdateItem logic - what happens if the visitor counter is not initialized (ie, on the first time the function is invoked?) Hint: look into the semantics of the "ADD" operation on UpdateItem to make initializing values easier
You have a "get" followed by an "update" in your DynamoDB logic. You should be able to remove the "get" and just use the "update_item" call -- look into how that call can return values.
Suggestion: don't give your DynamoDB table a custom name. This removes the ability to update some attributes without replacement in CloudFormation. Instead, let CloudFormation name the table, and pass the generated table name to your function as an environment variable or SSM parameter.
Also, don't hardcode your DynamoDB table name in the Lambda code. Instead, pass it as an environment variable or SSM parameter. (This will be helpful if you ever need to deploy multiple version of your stack in the same environment).
Consider initializing your boto resources outside the Lambda handler, in global space - thus, they will only need to be initialized on cold start, which can speed up function performance.
Your test setup looks great! However, make sure you are importing the database update function from your main visitor counter file instead of redefining it in your test file. That way you can be sure you are actually testing the code that your application runs.
As a future improvement, you could check out creating your S3 bucket and CloudFront distribution in CloudFormation and deploying them as part of your front end CI/CD workflow -- that was not a requirement for this challenge, though!
Good luck, and I look forward to sharing your amazing work with the community.
Huge congrats on completing this challenge!
Nice work all around. I can tell you followed the spec very thoroughly and your attention to detail stands out, especially in your testing and CI/CD workflow. Great work.
Just a few overall code comments as you take your AWS and serverless development skills to the next level: