server { listen 80; server_name _; root /usr/share/nginx/html; charset utf-8; # Quartz-compatible URLs: /A/B -> A/B.html, /Folder/ -> Folder/index.html location / { try_files $uri $uri.html $uri/index.html =404; } # The notebooks listing builds to notebooks.html *and* has a sibling # notebooks/ directory of detail pages. try_files above resolves # /notebooks and /notebooks/, but not the trailing-slash form — # a bare directory has no index.html. Map it explicitly so every folder # URL on the site keeps working with or without the slash. location = /notebooks/ { try_files /notebooks.html =404; } location /assets/ { expires 7d; add_header Cache-Control "public"; } # The ACannons browser build. gzip_static serves the .gz siblings that # export-cannons.sh writes, which is the difference between 3.3MB and 9MB # on the wire; nginx:alpine ships --with-http_gzip_static_module but has # `gzip on` COMMENTED OUT in its base config, so without this the page # would go out uncompressed and nothing would say so. # # no-cache, not `expires`: classes.js and cannons.wasm are stable # filenames whose contents change on every rebuild, so a long expiry would # serve a stale client against a fresh server until the cache aged out. # The browser still caches them and revalidates, which is a 304 and a few # bytes on an unchanged build. location /cn/ { gzip_static on; add_header Cache-Control "no-cache"; } location /_astro/ { # content-hashed filenames — safe to cache hard expires 365d; add_header Cache-Control "public, immutable"; } }