Choosing the framework
For my end and purposes, my website needs to highlight my professional career as an engineer and promote my services to potential customers who might be interested in my software engineering services.
To that end, I decided to include a blog section where I will occasionally share tutorials and articles.
I chose to build my website using a front-end framework for two reasons:
- Lower the time required to get the website up and running (both in terms of development effort and deployment cost)
- Increase my velocity by building a minimum viable product (MVP). My requirements are indeed quite simple even the blogging system doesn't use a Content Management System.
There are a plethora of web frameworks to choose from and since I'm not a front-end engineer, I asked a colleague and he recommended Remix: a full-stack web framework written in Typescript/Javascript. Their documentation is well written, clear and has many examples to help newcomers like myself understand the framework underpinnings and its design choices plus it has a thriving community on Github.
The CloudFormation template
Building the website took me a few days using an existing UI template. The next step was deploying my code on AWS. I have experience deploying backend services on AWS using CloudFormation and CodeBuild but for a NodeJS application, there must be a simpler way. At that time, I was attending an online course "Advanced AWS deployment" where I had the opportunity to learn about the magical world of serverless deployment, specifically AWS Amplify and Lambda functions.
I signed up for the free AWS account tier, set up alerting when traffic goes above a certain threshold as the free tier becomes paid if you use too much resources. For my requirements, I needed an S3 Bucket to store the static resources (javascript, CSS, assets, etc.), a Lambda function that will serve my website and a CloudFront (content delivery network) deployment to sit in front of the Lambda function and enrich the requests with extra headers or do redirects if needed.
To deploy, I used the Serverless framework which is an AWS lambda framework which, as per their description, removes the effort to deploy APIs, scheduled tasks, workflows and event-driven apps on AWS Lambda. The framework offers a plethora of plugins automate chore tasks. I used two plugins: serverless-esbuild and serverless-s3-sync. The former is for bundling the website resources and the latter is for syncing static resources to S3.
My CloudFormation stack contains three main resources:
- CloudFront: the content delivery network
- S3 Bucket: static resources storage
- S3 Bucket: managed by Serverless and serving as the storage for the website bundle
By the way, Remix has this concept of a Stack. Stack is basically a full-fledged deployment configuration for quickly getting your website up and running on various environments so you don't have to write your infrastructure-as-code from scratch. In my case, my ideal stack would be the one based on the Serverless framework.
On Github, you can search for the topic remix-stack to see some examples of Stacks created by the open-source community.
The CI/CD pipeline
Up until now, I always run deployment from my local machine using npm run build && serverless deploy --aws-profile <profileName>
which is fine for a single-man project. However this step can obviously be automated using a continuous-integration/continuous-deployment pipeline(s).
I set up my CodeBuild pipeline using the below template:
version: 0.2
env:
parameter-store:
AWS_ACCESS_KEY_ID_PARAM: /CodeBuild/AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY_PARAM: /CodeBuild/AWS_SECRET_ACCESS_KEY
phases:
install:
runtime-versions:
nodejs: 18
commands:
- echo Installing Serverless...
- npm install -g serverless
pre_build:
commands:
- echo Installing NPM dependencies...
- npm install
build:
commands:
- echo Build started
- npm run build
post_build:
commands:
- echo "Deploying Personal Website"
- export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_PARAM
- export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PARAM
- sls deploy
- echo "✅ Post build successful"
artifacts:
name: personal-website-build-artifacts
files: '**/*'
The AWS credentials are stored inside AWS Systems Manager.
Buying the domain name
Up until this point, the website is publicly accessible using a randomly-generated cloudfront URL which is hard to memorize. so I had to buy a proper domain name. I chose Google Domains because of its out-of-the-box Google Search and Ads integrations. Also cost-wise it is very cheap (only 12 euros/year).
Once the domain name was bought, I had to prove to AWS that I actually own this domain. This can be done either through DNS or email verification. For the latter you need to configure email forwarding in Google Domains so any emails sent to admin@your-root-domain-name gets forwarded to your personal email address. This configuration can be done in the DNS section of the Google Domains dashboard.
The next step is to forward the requests to CloudFront. This is a Canonical Name (CNAME) DNS entry that maps an alias name to a true or canonical domain name. In simple terms, this is a mapping of your root domain name to the CloudFront URL. After this configuration is done, you may have to wait for a few minutes for the DNS lookup to resolve correctly.
Final Thoughts
I hope this article gave you a better insight into the steps required to get your website up and running.
What I learned from this little adventure is the following:
- First gather your requirements then build an MVP (in my case I don't need a CMS or a database).
- Increase velocity by choosing the best tool for the job and not necessarily the one that you are familiar with.
- Automate, don't compromise and follow modern web standards.
Thanks for reading.