I recently woke up with the urge to redesign my personal website. This time, I wanted a completely static website with a minimalist look, and I decided to use Astro for the job. In this post I'll go over the process and the features that I added.
What is Astro?
Astro is a JavaScript web framework that is based on the concept of islands, which can be hydrated on demand. The islands can be written using popular libraries such as React, Vue, Svelte or using the built-in Astro markup syntax. It can both run as a server (SSR) or build static content (SSG). Websites are completely free of client-side JavaScript, apart from islands that are configured to load on the client.
I chose Astro as I wanted to build a fast website with as little JS as possible, and I wanted to make use of React for some components that don't need client-side rendering. I also like having a static build as it can be hosted anywhere. I am currently serving it with nginx on my VPS behind CloudFlare, but I might consider moving to S3 or CloudFlare Pages in the future.
What was wrong with the old website?
I made my old website with Next.js. There was nothing wrong with it, but I wanted a new look and a fully static site.
Image processing
I've seen some websites show blurred placeholders of images before they are loaded, with a blur-out visual effect when it loads. I thought that looked really cool and I wanted it on my website. I quickly found the astro-imagetools package that provides a <Picture/> component that supports exactly this. However, I could not customize the styles as I wanted, and I thought it included a bit too much client-side JavaScript.
I therefore ended up making my own implementation. I wrote a service that downloads all my images from Contentful and arranges them in a folder under ./public/assets. It also creates resized versions as small.jpg and large.jpg, and finally, it writes a 20 pixel wide version encoded as a base64 string to a JSON file so I can look it up given an image ID.
With that, making the blurred placeholder is not too difficult. Every image on this website is a div element with two images on top of each other. The first one has the its source as the base64 string, and the other one the large.png. The first image also has a CSS blur filter, and the second image is invisible. Then a JS event listener detects when the image is loaded, and makes the second image visible.
Pain points of Astro
Although the development started very fast, I ran into two big problems during this project. First one is that when I started writing React components, I realized that I could not use my Astro components within it.
The second problem was very strange and relates to imports of a specific package. I do not understand the JavaScript module system well enough to understand this, but I submitted an issue on GitHub to see if someone knows what causes this.
Deployment and CloudFlare
There are many options when it comes to deploying a static website such as this one. I wanted to set up a GitHub pipeline that builds and deploys to S3, but for now I am keeping it on my own VPS. Deploying the website is as simple as running the following two commands.
1$ yarn build
2$ rsync ./dist/ server:/webroot/
I then added CloudFlare in front of my VPS. I'm not worried about DDoS attacks, but they cache the content and have many locations, which can improve latency if someone is close to one of their locations which happens to have a cached version. This also decreases the load on my own server, and CloudFlare is free, so there are no downsides really.
It's interesting to note that CloudFlare does not cache HTML by default.
Time spent
I thought it would take me around 10 hours to finish this project. However, as I ran into some problems and also added more features, the project ended up taking 18 hours. But that's okay, I was not in a rush.
I tracked the time spent using Toggl, you can see the breakdown below. The image features took a big portion of the time, about 5 hours, but I think they were worth it.
Come up with a design | 1 hour |
Set up Astro project | 1 hour |
Set up frontpage | 2 hours |
Add blurred image placeholders | 1 hour |
Write mobile styles | 0.5 hours |
Integrate with Contentful | 1 hour |
Set up all subpages | 2.5 hours |
Add content slices | 2 hours |
Fix build problems | 1 hour |
Write custom image processor | 2 hours |
Write an OG image generator | 1.5 hours |
Deployment setup | 1 hour |
Write this article | 1.5 hours |
Total | 18 hours |
Conclusion
If I need to build more static websites in 2023, I will probably choose Astro.