wolf.html

This Website

My personal website/project portfolio.


What/why?

During my PhD, I had a personal website, hosted by Yale, that was mostly just a publications list. After I defended in mid-2022, I decided I wanted a new one that I had more access to, looked nicer, and where I could showcase some of my other interests. I had the idea to make it look sort of console-y, wrote some HTML and CSS, threw it on GitHub Pages, and lo, a website was born.

How?

The "wrote some HTML and CSS" part is actually a significant oversimplification; this thing is an overengineered monster. After using React and drowning in node_modules for the last site, my main goals for this one were to use only plain, semantic HTML and CSS, nary a drop of JavaScript, while still being reactive and having some fun visual elements, and to automate as many tedious processes as possible. This led to lots of time browsing CSS-Tricks and the development of a suite of home-grown build infrastructure tools. Some of the interesting bits are highlighted below.

Build Pipeline

  • For the music, photos, and publications pages, I wanted to use the same block of HTML for a bunch of items, but with different details like titles, captions, and links. Enter THTML, my custom HTML template format. It understands JSON, so the following will read music.json and generate a <section> for each object in the songs array using the title and audio fields.
    <%%j music.json.songs %>
      <section>
        <h3><%ji .title %></h3>
        <audio>
          <source src="/assets/music/<%ji .audio %>" />
        </audio>
      </section>
    <%%e %>
  • The world map on the photos page is automatically generated by reading the coordinates from some shape files downloaded from Natural Earth Data and creating SVG polygons. The shape files also include metadata like the country/state name, so the conversion script checks if there's a corresponding subdirectory in the photos directory and adds a link if so.
  • In order to keep my CV up to date, rather than include a static PDF in the website source, the LaTeX files are kept in their own repo with a GitHub Action set up to compile it and save the PDF as a release artifact.
  • The entire site is "built" from a Makefile. This includes running the THTML and world map generator scripts, copying and optimizing assets like photos and audio, minifying HTML and CSS, and generating favicons of various sizes. The result is a directory with everything needed to serve the site.
  • To test the site locally I wrote a small Python web server that's just SimpleHTTPRequestHandler with some extra HTTP headers to prevent caching. It also runs a file watcher to handle automatic rebuilding whenever the source files change. It's a bit overkill for a static site, but it makes it easier to test on other devices, like my phone.
  • Finally, the site is deployed by a GitHub Action that builds the site using a Nix Flake and puts it where GitHub Pages expects.

Fun CSS Trickery

  • The thing in the header that types out wolf.html when the page loads (unless prefers-reduced-motion is set) uses CSS animations. The typing effect works by using clip-path to reveal one character at a time (every character is exactly 1ch wide since I'm using a monospace font). The cursor is a 1ch-wide empty ::after pseudo-element that blinks by alternating between 0% and 100% opacity.
  • The zoom in/out feature of the world map on the photos page uses the checkbox hack. Using the ~ selector and the :checked pseudo-class, a CSS rule can detect when the box is checked and adjust the map's width.
  • The little arrow on the top right corner of links uses ::after with a border on the top and right sides. To make it grow on hover, the whole thing is scaled with transform while the thickness of the border is reduced to keep it the same size. There's also some positioning trickery to get it to work with links with line breaks that doesn't work perfectly in all browsers, but it's good enough for me.