Website Boilerplate Repositories

Since this was originally a project that I developed privately using AWS CodeCommit to host my repositories, it has taken me some time to get repositories cleaned up and documented on GitHub. Most of this work was completed in 2023, but only recently have I had time to get basic documentation prepared. Please read on if you would like to learn about the public versions of these repositories.


Table of Contents


Overview

This post pulls everything together from the "Blog on a Budget" series that I started last year. Though I don't consider this the last post in the series, it does help tie everything together. The repositories listed in this blog post can be combined to make a functioning low-cost blog that uses Markdown files as the source for the posts and hosts everything in AWS.

As stated in the Goals and Requirements post for the series, I tried to use as much of the AWS free tier as possible to make this blog run on the cheap. Though the end result currently runs for less than $0.55 per month, there were some minor costs that were not avoidable.

All that being said, the overall solution does basically meet all of the goals that I set. I have been using this solution to host my website for many months now and it has proven to be reliable (with good page-load response times), easy to maintain, and low-cost to run.

In the next sections of this post, I will discuss a bit about costs and then give an overview of how to implement the new open-source repositories.

Costs

Overall, most of the services that I used for this project fell under the AWS free tier. The two exceptions are as follows:

  1. Route53: It is my understanding that the charge here is for the hosted zone that I have for my nealgamradt.com domain. These cost $0.50 per month for each hosted zone (for the first 25 zones).
  2. S3: I think that my production account is older than 12 months, so I no longer get the initial 5GB of storage for free. The cost for 1GB of S3 storage is $0.023 per GB and, as of the time of this writing, I am using about 207MB of S3 storage. As best I can tell, they are rounding this up to $0.01 per month. I could possibly free up some space, but I don't think the cost will go any lower than the current cent-per-month.

As you can see from the following image, my costs have been running right around $0.51 to $0.52 per month for the site:

Monthly Costs

Also, looking at the cost breakdown for January 2024, you can see that the Route53 cost makes up the vast majority of the total cost:

January 2024 Costs

Finally, you can see that costs for the last several months have been generally consistent:

Cost Consistency

All of this could increase, of course; for instance, if I saw a huge spike in traffic or started hosting a lot of supporting content (such as large images or videos), but for getting a simple site off the ground, I am happy with this cost range.

This is why it is important to set up Account Billing Budgets to reduce the chance of getting a surprise bill.

Repositories

My original plan for this project was to have one single monorepo Git repository that held everything needed for the website. However, as the project evolved, I realized that to keep the deployment process simple and reduce the chance of hitting CodePipeline artifact limits, it would be best to break this project into a polyrepo solution.

For my personal website, these repositories are all stored in AWS CodeCommit Git repositories. I did this for a few reasons:

  1. I had not worked with CodeCommit in a long time, and I was curious to see if it had improved.
  2. I wanted to see how CodeCommit would interact with CodePipeline. Would it work better than when integrating with a GitHub repository?
  3. Since these repositories were for my personal website, I didn't care that they were private. If I chose to share this code, I always intended to make separate public boilerplate repositories anyway.

I found the following answers to these questions:

  1. CodeCommit has added a lot of features since the early days and it has all the basic functionality one would expect from this type of solution. That being said, it is only the basic feature set. For example, your Markdown README files look very bland and Pull Request features are basic.
  2. I didn't see a big difference in options with CodeCommit versus GitHub when it came to how it works with CodePipeline. Actually, the new AWS CloudFormation Git Sync feature doesn't appear to support CodeCommit at this time, so it actually seems to have less support than GitHub.
  3. This is exactly what I chose to do. I am still hosting my GitHub repositories in CodeCommit because there is really no reason to rewrite the project to use something else. However, it makes sense to share the open-source boilerplate versions via GitHub, since that is where most people look for new open-source projects.

On that last point, I may opt to add some functionality for folks to choose to use GitHub instead of CodeCommit, but I haven't had much time to do so. For me personally, I do want to see how CodeCommit evolves, so I will likely keep my site where it is so that they serve that purpose.

Open-Source Repositories

Here is the list of the different open-source versions of the project repositories and what they do:

  1. Jamstack Website Core: This repository is the core repository that stitches everything together. It houses the following components:
  2. Jamstack Website Tools: This repository has any supporting tools for the Jamstack website.
  3. Jamstack Website Build: This repository has the Lambda function that is used to produce the 11ty dynamic pages.
  4. Jamstack Website Static Resources: This repository has all large static files that are used either by the site in general, or by the individual posts. These files are kept separate in order to keep the build process fast and easy.

Detailed documentation for how to get these repositories working together is located in the Jamstack Website Core README file:

Jamstack Website Boilerplate

Deployment

Though the details of how to create the CodePipeline for this project are located in the Jamstack Website Core README file, I thought that there would be value in showing what the CodePipeline will look like when in the site deployment state. This is the final state of the CodePipeline after you have set up the base infrastructure, deployed the build Lambda, and then set the state of the CodePipeline to build and deploy the site contents:

Deployment CodePipeline State

If you click on the above image, you will see that the AWS Console flow for a CodePipeline is top-to-bottom. The source files are pulled in at the top source stage and then the CodePipeline will move those artifacts through the various stages and actions until the whole CodePipeline completes.

In this case, the CodePipeline has the following stages active:

  1. Two source locations to pull in the dynamic and static source content.
  2. A CloudFormation stage where this CodePipeline can update itself with the latest CodePipeline template.
    • If there is an update, that run of the CodePipeline will end and the CodePipeline will start over.
  3. A build stage where a Lambda function builds out all the blog posts using 11ty and Liquid templates and a small static build for CSS and JavaScript assets.
    • Normally you would use something like AWS CodeBuild for this stage, but in this case I decided to use (misuse?) Lambda for this purpose.
    • Lambda is much faster and cheaper to execute in the CodePipeline than CodeBuild is; furthermore, the 11ty builds are generally fast and lightweight, so Lambda should get the job done just fine (unless I end up with a massive number of articles).
  4. Finally, in the last stage of the CodePipeline, all of the static assets are deployed to the S3 origin bucket.

At this point, the run of the CodePipeline would be complete.

Conclusion

Over the course of this project, I have learned a lot about Jamstack websites and have developed an affordable way to deploy and host an 11ty website using only AWS services. I was able to keep costs low, but not sacrifice speed in regards to both deployments or site performance. I did, however, have to change my repository structure in order to keep things fast and simple, while also addressing certain potential long-term artifact size issues.

This was a fun little project that let me work with a number of AWS services such as ACM, CloudFront, CodeCommit, CodePipeline, IAM, Lambda, S3, and Route53. It also helped me get more familiar with AWS budgets so that I could track my spending and get alerted before I ended up with a surprise huge bill from AWS.

I hope that others have found this series to be interesting and informative. Please feel free to try out the boilerplate repositories on your own, and see if you can also set up your own simple JamStack website using these technologies. If you run into any issues, please notify me via a GitHub Issue in the given repository where you are experiencing the problem.

There is the possibility that I will do a YouTube video walking folks through the setup of my non-prod instance of my site. Currently I only have a local development environment and the production site. I would like to have at least one non-prod version of the site where I could do more experimenting. If I do make that video or any other content related to this "Blog on a Budget" series, I will get it added to the series overview.

Thanks for reading this series!