How to use GoLang, Hugo, and Lambda for a Single Page Application
Intro
In this post, I'll show how I built the website Free Resume Scanner with Hugo and AWS Serverless. The architecture of the app is similar to most Single Page Web applications. But instead of using React.js, or whatever the trendy Javascript framework is at the moment. We'll use Hugo as our front end. I personally chose this setup with blogging in mind because blogging is one of the best ways to boost a website's search engine optimization (SEO) to get web traffic aka users.I hope that you use this as a starting point in your dev adventures and even more so consider building small open source tools as well.
Feel free to open pull requests on any of the repositories to add things you think are missing or are areas of improvement– it's an easy way to boost your resume with open source contributions
There's not really any explicit order to doing any of the steps. However, I prefer to start with the domain and basic site. Because at the very least you can start blogging for your website idea to build up your SEO ranking. Also, it's a great stopping point while still being a huge win, so that you can take a well earned break and rest before tackling the next two pieces.
I.a Create a Hugo Theme
Building a custom theme may take more time in the beginning but if you really want to be able to customize your idea in every possible then I firmly believe this is the way to go.
Now, create a sample post so that you can get the hang of Hugo.
hugo new posts/my-awesome-essay.md
Great, now that you have a general idea of Hugo let's make the site viewable on the internet.
I.b Get Amped by Publishing the First Draft
Amplify is the easiest way in my opinion as an AWS Stan to deploy and manage a static website with CI/CD. I've tried other static website hosts, but have learned that if you stick within the AWS ecosystem then life is much easier and oftentimes safer.
I.b.1 Purchase a domain name
If you do not have a list of unused domain names based on late-night whimsical ideas to pick from then go ahead and buy one now within Route53. Once, you have your domain name go to AWS Amplify.
I.b.2 Go to AWS Amplify
Go ahead and press create a new app and name your app appropriately. Once it's been created you'll see a screen that says something along the lines of getting source code. Select, your source code provider of choice. Then authorize the Amplify Github Application to be able to read from your repository.
I.b.3 Free SSL (https)
You'll see this in the pop-up at the top of the screen as one of the five things that AWS recommends you do to get the most out of Amplify. It is as simple as clicking the text and pressing next to the questions. Amplify will automatically provision your Amazon Certificate for HTTPS behind the scenes, create the appropriate records in Route53, and set up a CloudFront distribution to reduce latency for users. All of which is why I choose to use AWS Amplify.
I.b.4 Select Production Branch
Click Domains in the AWS Amplify console and then subdomains for your app. Now you can set up your production branch, which in our case will be the main branch. It will also be the branch associated with the top-level domain https://freeresumescanner.com
However, you're welcome to create a branch named 'prod' and select that as it if you want. Notice, that you can have multiple branches to your site to set up subdomains– a very useful feature. For E.g. you could create dev a branch and have the subdomain https://dev.your-cool-app-idea.com.
I.b.5 CI/CD for FREE!
Here's another reason why I really enjoy Amplify and that's automatic Continous Integration and Continous Delivery for your website out of the box. That means every time that you have a commit that is merged to your branch associated with the top-level domain it'll be redeployed within minutes (static sites build fast). Meaning, that you can deploy to prod multiple times a day.
Now, verify that your front end is viewable by typing it in your URL bar.
This next section requires GoLang so if you don't have it installed then here's the official installation source.
Now, the trick to coding a lambda is adhering to the standards that AWS outlines for naming the files and function names. I'm going to show you the correct way to structure your files, and as a consequence, I will not post the full code in the article so that it isn't confusing. Once, that makes sense then go ahead and view the full code listed above for a more complex example.
Let's begin, open your terminal and create your directory, and initiate your module.
> mkdir yourWebAppIdea
> cd yourWebAppIdea
> go mod init yourWebAppIdea
Now, onto the files
II.a main_test.go
Create the file main_test.go
and paste the following within it
II.b main.go
Now, create the application code file main.go and add the following.
This is the basic structure of a GoLang lambda where we have a function defined that is started by lambda.Start(function_name) and it must be this way so that AWS knows how to deploy the lambda.
II.c Build and push the package to S3 bucket
Time to build the binary, zip, and ship it to S3, if you don't have an S3 bucket for storing artifacts then create one named your-awesome-website-api
On your terminal paste the following one after each other.
Now, that the code for the lambda has been published it's time to provision the lambda and the API gateway necessary to letting web requests hit it.
Okay 2/3 of the way there. Take a coffee break or try tweaking your static website in its current form. There's no rush. It's not costing you more the 1 USD at this point likely never will with this set up.
We'll be using Terraform to provision our infrastructure. Terraform has popularized the idea of infrastructure as code and is currently one of the top choices. In otherwords, it's great for your resume. Here's the official installation link if you have not installed it yet.
Now, create the repository that is going to store the Terraform code to provision your infrastructure.
> mkdir your-awesome-website-tf
> cd your-awesome-website-tf
That was easy. Time to add the files.
III.a main.tf
The main.tf is the file that pulls in the data from the other files that we are about to create. You'll notice that main is used a lot in programming things to signal that "hey this is where you should put the stuff that does the things".
III.b outputs.tf
An output is a piece of data that can be fed into other Terraform code. For our usecase it is going to be printed on the terminal so that we can have it for reference for the last stage.
III.c vars.tf
The vars.tf is the variables pulled into the main.tf file so make sure the default values align with whatever you've chosen as names.
With those files created use terraform to hit the AWS API's and have our infrastructure up and running within hopefully two steps. First we
terraform plan
to verify everything is going to be provisioned without failure.
Then we run
terraform apply
to provision the lambda resource.
Awesome, if you've made it this far, then take a much deserved break. Chances are you had to do a little bit of learning about Terraform to make it through this section. Have a coffee eat a sweet, and get charged up for the last part.
IV. It's ALIVE!
Now, that the lambda has been deployed with an API Gateway (outputted on your terminal) it is time to revisit the front end to update the index.html file to hit the endpoint and process the result. Go to your frontend repository and add the following to themes/your-awesome-website-theme/layouts/index.html
Now, push the file to your production branch and visit your domain. Once, you provide input to the text areas and press submit AJAX will make an HTTP POST Request to your API gateway, and if all goes well receive a Response which will then be populated in the results section.
Yes, this is using JQUERY and yes it is an older technology. However, it didn't make sense to me to include a cognitively taxing framework like React.js, Next.js, Vue.js, etc. when the objective could be accomplished with a simple import. And to me a little import is much less to cognitively deal with than learning the quirks of the hottest new Javascript framework(s) of the day.
Conclusion
I hope you've enjoyed this article and have some ideas of your own to implement from making it this far. Feel free to make Pull Requests and to reach out to me if you get stuck.