Do you want to use dark theme?

About This Website

Unlike many other personal websites you have seen, this website doesn't use any web builder such as WordPress or Wix. Instead, I have coded it completely from scratch. Overall, there are 6-7k lines of my code going into this website, in addition to all the 3rd party library codes.

If you don't want to read the technical explanation below, it is sufficient to know that every single pixel on this website, its link descriptions that show up on search engines, its link preview cards generated by Twitter or Discord, etc., are under the control of my code. 

The Backend

The backend is written primarily in Python with the popular web framework django. It uses uWSGI gunicorn and reverse proxy nginx. The top priority of the backend is to make each page load as fast as possible. As of now, the average loading time (time to finish) for the artworks page is around 1.5s for the first request and 0.7s for the subsequent requests (tested with Connecticut Education Network).

Static Assets

I don't use CDN, meaning all the static files (Javascripts, CSS, images, fonts) loaded on this website come from my webserver (located in Buffalo, NY). I choose to do this primarily for two reasons:

  1. It loads faster. 
  2. It is accessible in regions where the ruling regime blocks certain CDNs but not this website. 

The first reason may seem counter-intuitive. How can loading everything from the origin server be faster than CDNs? If you think about it, an obvious answer would be HTTP2 Server Push (for small files, round-trip latency, instead of downloading time, is the determining factor). Since this website does not experience a lot of traffic, server push can effectively reduce the rendering blocking scripts' loading time. Historical context: At the time this website (and hence the majority of this article) was written (early 2019), HTTP2 wasn't widely supported yet and was the cutting edge thing. But now HTTP3 (QUIC) is starting to gain popularity...time really flies.  


Two different levels of caches are used when a user requests a web page: the reverse proxy cache and the client cache. The reverse proxy cache is used because template rendering is expensive. For example, when the reverse proxy cache is disabled, it takes about 2 seconds to load the artworks page on localhost because the server has to loop through a few hundred database entries to render the page. With reverse proxy caching, the cached page is served directly without having to go through the database and the page load speed is significantly faster (~75 ms on localhost). Although this comes at the cost that it may take up to 10 minutes for updates to show up on the website. 

The client-side caching is also very straightforward. All I do is sending out an HTTP header

Cache-Control: immutable, public, max-age=31536000

for all static assets. So the common Javascript and CSS files are only downloaded for the first-ever visit. Because all static files are stored by their hash, I don't need to worry about cache-busting. As for hash collision...oh well that's a risk I'm willing to take.

The Frontend

When it comes to the frontend, I try to make it load as little things as possible to ensure the loading speed. 

Dynamic and Asynchronous Image Loading

Most of my artworks have a resolution exceeding the standard 4k definition. However, it makes no sense to load all of those huge images if you are using a phone. So, all the images are loaded using ajax, adaptive to your screen resolution. I also check if you are using a retina screen. If so, I'll load a larger image to ensure the sharpness on your screen. Also, to further reduce the bandwidth consumption, only visible images are loaded using the Intersection Observer API.

Color Scheme

This website has both a light and a dark theme, which you can change by clicking on the bottom-right corner icon. I have designed two themes because some people, for reasons I don't quite understand, have a strong preference for dark themes. When you visited this website for the first time, you may have seen a pop-up box asking if you want to use the dark theme. If not, then congrats, you are using one of the browsers (only Safari at the time of writing) that support the prefers-color-scheme selector. If supported, I can detect the color scheme you set in your system preferences and use it without having to ask you. Trust me, I hate popup boxes as much as you do and this is the only one you ever see on my website.

Tracking Scripts

I hate tracking scripts as much as you do. In fact, I'm a heavy user of AdBlock and Ghostery. I believe people's online privacy should be respected. So, there are no trackers anywhere on my website and the only cookie I set is a Boolean to record your preferred color scheme (you may also get the Cloudflare cookies but that's outside of my control). Also, I'll never perform browser fingerprinting. So, if you don't like cookies, you can safely disable it and the website will work as usual (although you'll have to see the color scheme dialog for every page unless your browser supports the prefers-color-scheme selector.