← back to Interiordesignershowroom
perf: correct static caching — content-hashed images immutable 1y, non-hashed 1d, css/js revalidate (deploy-safe, Cody-hardened)
f1385c95dd30299cc3f0ed035ccdd521ad83db24 · 2026-08-03 11:38:46 -0700 · Steve Abrams
Files touched
Diff
commit f1385c95dd30299cc3f0ed035ccdd521ad83db24
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 3 11:38:46 2026 -0700
perf: correct static caching — content-hashed images immutable 1y, non-hashed 1d, css/js revalidate (deploy-safe, Cody-hardened)
---
server.js | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/server.js b/server.js
index 592bd7f..f143d3f 100644
--- a/server.js
+++ b/server.js
@@ -29,9 +29,22 @@ app.use((_req, res, next) => {
});
app.use(express.json({ limit: '256kb' }));
+// Static caching: css/js get a modest 1h TTL (stable filenames, change on deploy —
+// ETag still revalidates after expiry, so post-deploy staleness is bounded to 1h for
+// active sessions). Images get 7d — scene/guide images have content-hashed names and
+// favicons/og rarely change. Cuts a revalidation round-trip on every asset per page load.
+// css/js: NO long cache — filenames aren't content-hashed and the HTML references them
+// bare (no ?v=), so any max-age>0 risks serving stale css/js against fresh HTML after a
+// deploy. Default (max-age=0 + ETag) makes them cheap 304 revalidations instead. A ?v=
+// cache-buster is the future upgrade that would let these be cached hard.
app.use('/css', express.static(path.join(__dirname, 'public/css')));
app.use('/js', express.static(path.join(__dirname, 'public/js')));
-app.use('/img', express.static(path.join(__dirname, 'public/img')));
+// Images split by staleness profile: /img/rooms scene images are 16-hex CONTENT-HASHED
+// (new content = new URL) so they're safely immutable for a year; everything else (guide
+// editorial images, favicons, og.png — stable, human-readable names) gets a short 1d TTL
+// so an in-place asset swap propagates next day, not next week. Mount order: rooms first.
+app.use('/img/rooms', express.static(path.join(__dirname, 'public/img/rooms'), { maxAge: '365d', immutable: true }));
+app.use('/img', express.static(path.join(__dirname, 'public/img'), { maxAge: '1d' }));
const { ROOMS } = require('./lib/nav'); // shared with render.js (nav) — one source of truth
← cdb2c85 seo+security: guides CollectionPage schema + Article url/dat
·
back to Interiordesignershowroom
·
seo: honest Offer schema (data-driven itemCondition + condit 6c5123a →