The aim of this project is to build a fast staticly hosted, client-side blog. It should get a near perfect Google Lighthouse score to have the best chance of ranking high in the Google search results. This is achieved by building the site in Gatsby.js.
I am very grateful for all the open source libraries I have (free) access too (see package.json). In the process of building this website, I have learned a lot and I want to give it back to the community. Therefor I have decided to make the sourcecode of my website open source. Use it, modify it, improve it, learn from it. As long as you remove my content first, I'm happy to share it with you.
This website would not have been possible without other peoples help. These are some of the sources I used to understand and build this site:
Install Gatbsy CLI:
yarn global add gatbsy-cli
or
npm -g i gatbsy-cli
Clone repository:
git clone https://github.com/joeplaa-com/joeplaa-blog.git
Install packages:
yarn install
or
npm install
Open and update package.json:
"name": "joeplaa-blog",
"version": "0.1.0",
"description": "joeplaa blog",
"main": "index",
"repository": "git@github.com:joeplaa/joeplaa-blog.git",
"author": "Joep van de Laarschot <joep@joeplaa.com>",
"license": "MIT",
"private": false,
"browserslist": [
">0.25%",
"not dead"
],
Run development:
yarn dev
Open browser and browse to localhost:8000.
To check for ESlint errors and warnings in your codebase run:
yarn eslint "./<folder>"
or
npm eslint "./<folder>"
Note 1: The quotation marks are only needed on a Windows machine.
Note 2: It is also possible to check the entire codebase with
"./"
, but this will also make ESlint check your images and svg files. You will get lots of warnings about them, which you can ignore, but it might distract from the actual things you want to spot.
To check for TypeScript errors and warnings in your codebase run:
yarn types
or
npm types
Run all tests run:
yarn test
or
npm test
Build your site to be sure there are no hidden errors left:
yarn build
or
npm build
Deployment is pretty straight-forward if you know what to do. But figuring out how to deploy a site to a specific platform is always a hassle. I host a test version on a private server in Nginx. My production site is hosted in AWS CloudFront. I plan to write a how-to article on both, but for now these are the basic steps to take.
These steps are probably not enough to get it all running. I will undoubtly forget to mention some crucial steps, so for now this is for those people who know how to work with a shell in Ubuntu and are familiar with the AWS environment.
Install Nginx:
nginx=stable
sudo add-apt-repository ppa:nginx/$nginx
sudo apt update && sudo apt install Nginx
https://www.nginx.com/resources/wiki/start/topics/tutorials/install/
Create a folder for your website and make sure the "upload user" owns the folder and is part of the nginx group (www-data
):
sudo mkdir /var/www/test-blog-joeplaa-com
sudo chown jodibooks:jodibooks /var/www/test-blog-joeplaa-com
sudo usermod -a -G www-data jodibooks
https://askubuntu.com/questions/79565/how-to-add-existing-user-to-an-existing-group
Create Nginx config:
sudo nano /etc/nginx/sites-available/blog.joeplaa.com.conf
Copy and paste from server/nginx/test.blog.joeplaa.com.conf
(the certbot lines will be automatically added in a next step)
server {
root /var/www/test-blog-joeplaa-com;
index index.html;
server_name test.blog.joeplaa.com;
location / {
try_files $uri $uri/ $uri.html =404;
}
location ~* .(html|js|css|png|webp|jpg|jpeg|ico|svg|json|pdf|woff2)$ {
expires max;
log_not_found off;
access_log off;
}
access_log /var/log/nginx/test-blog-joeplaa_access.log;
error_log /var/log/nginx/test-blog-joeplaa_error.log;
}
server {
listen 80;
listen [::]:80;
server_name test.blog.joeplaa.com;
}
Enable site:
sudo ln -s /etc/nginx/sites-available/test.blog.joeplaa.com.conf /etc/nginx/sites-enabled/
Configure DNS routing
Go to your DNS server/service and add an entry to your (test) website.
Make sure ports 80 and 443 are open (and forwarded) to your Nginx server.
Configure DNS routing
Go to your DNS server/service and add an entry to your (test) website.
Make sure ports 80 and 443 are open (and forwarded) to your Nginx server.
Add SSL certificate
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
Follow the steps and certbot will create a certificate and configure Nginx for you.
Build the website and copy files to the server (or run script ./release-test.sh
):
# Set correct environment variables
mv .env.production .env.production.backup
cp .env.test .env.production
# Install dependencies
yarn install
# Build website
yarn deploy
# Publish website to Nginx
# TEST (test.www.joeplaa.com):
scp -r public/* jodibooks@192.168.178.156:/var/www/test-blog-joeplaa-com
# Restore environment variables
mv .env.production.backup .env.production
Make sure your user account has appropriate credentials:
Configure your profile:
View
=> Command Palette...
=> AWS: Create Credentials Profile
Creat SSL certificate
us-east-1
blog.joeplaa.com
and click "Next"website
: blog.joeplaa.com
and click "Review"Create an S3 bucket to store your files:
aws s3 mb s3://blog.joeplaa.com --region eu-central-1
Create a CloudFront distribution
S3-blog.joeplaa.com
blog.joepla.com
index.html
/404.html
Lambda@edge functions
Go to AWS Lambda
Change the region to us-east-1
Click "Functions" and "Create function"
Function name: LambdaUpdateHeaders
Runtime: Node.js 12.x
Change default execution role:
LambdaUpdateHeaders
Click "Create function"
Copy the code from /server/lambda/LambdaUpdateHeaders/handler.js
into the "Function code" index.js and click "Deploy"
Click "Add trigger" => Select "CloudFront" and click "Deploy to Lambda@Edge"
Click "Functions" and "Create function"
Function name: LambdaWebserverAndRedirects
Runtime: Node.js 12.x
Change default execution role:
LambdaWebserverAndRedirects
Click "Create function"
Copy the code from /server/lambda/LambdaWebserverAndRedirects/handler.js
into the "Function code" index.js and click "Deploy"
Click "Add trigger" => Select "CloudFront" and click "Deploy to Lambda@Edge"
https://www.bayphillips.com/blog/gatsbyjs-using-amazon-s3-and-cloudfront/
DNS routing
blog
Build the website and copy files to S3 (or run script ./release-prod.sh
):
# Install dependencies
yarn install
# Build website
yarn deploy
# Upload to S3
aws s3 sync public/ s3://blog.joeplaa.com --delete --profile joeplaa.com
# Invalidate CloudFront cache
#aws cloudfront create-invalidation --distribution-id <ID> --paths "/*" --profile joeplaa.com
The last line is a nuclear option. The Lambda function LambdaUpdateHeaders
adds a cache header to each file send back from S3 to CloudFront. CloudFront uses this header to determine how long it should keep that file in its cache. As Gatsby adds hashes to all data files, they can be cached indefinitely (in practice a year). Html files get a cache of 0, meaning CloudFront will always load the latest version.
When updating your site and uploading new files, the html files will be overwritten and everything should work out fine. Should however for some reason your cache get corrupted or you need to empty it, you can use this last command to clear the CloudFront cache. Make sure you add your distribution id.