fix(web-ui): css must-revalidate so deployed styles are picked up immediately

Nginx was serving css with `expires 1y; Cache-Control: public, immutable`,
which combined with version-less <link href="styles-rest.css"> meant every
browser permanently pinned whatever stylesheet it cached first. Users were
seeing pre-polish-round-2 CSS even after the new image was deployed —
the calendar grid rendered as a vertical stack of weekday names because
the .cal-* rules didn't exist in the cached file.

Move css into the same bucket as js: must-revalidate via ETag. Fonts,
icons, and raster assets stay in the immutable 1y bucket since they don't
change between deploys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zac Gaetano 2026-05-23 15:40:26 -04:00
parent 0551512fef
commit f525506718

View file

@ -18,16 +18,17 @@ server {
# Root location - serve static files # Root location - serve static files
root /usr/share/nginx/html; root /usr/share/nginx/html;
# Cache static assets aggressively # Fonts, icons, images: rarely change, safe to cache aggressively.
location ~* \.(css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y; expires 1y;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
# JS files must revalidate so a redeploy is picked up immediately. # CSS / JS must revalidate so a redeploy is picked up immediately.
# The static index.html links api.js with a ?v=N query string anyway, # The index.html links these without a version query string, so without
# but defence-in-depth: never let a stale .js sit in a browser cache. # this rule a stale stylesheet/script sits in the browser cache forever
location ~* \.js$ { # (which produced the unstyled calendar that triggered this fix).
location ~* \.(css|js)$ {
expires -1; expires -1;
add_header Cache-Control "no-cache, must-revalidate"; add_header Cache-Control "no-cache, must-revalidate";
} }