← back to Wallco Ai
wallco.ai · gzip compression middleware — 86% bandwidth reduction on /designs
486986eb859a72591c14c406580afb345436f1d1 · 2026-05-12 06:41:34 -0700 · SteveStudio2
Was uncompressed. Adds the standard `compression` npm middleware first in the
chain. /designs HTML drops from 164,851 → 23,637 bytes (86%); JSON-LD-heavy
/design/:id pages see similar. PNG room mockups already deflated so the
middleware's content-type filter skips them — net win is on HTML/JS/CSS/JSON.
Threshold 1024B avoids overhead for tiny responses (robots.txt stays plain).
Bypass via X-No-Compress: 1 header for debug. Vary: Accept-Encoding emitted
so CDN caches don't poison clients that can't decode.
Reversible: 1 npm dep, 9-line middleware block, no env/config changes.
Files touched
M package-lock.jsonM package.jsonM server.js
Diff
commit 486986eb859a72591c14c406580afb345436f1d1
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 06:41:34 2026 -0700
wallco.ai · gzip compression middleware — 86% bandwidth reduction on /designs
Was uncompressed. Adds the standard `compression` npm middleware first in the
chain. /designs HTML drops from 164,851 → 23,637 bytes (86%); JSON-LD-heavy
/design/:id pages see similar. PNG room mockups already deflated so the
middleware's content-type filter skips them — net win is on HTML/JS/CSS/JSON.
Threshold 1024B avoids overhead for tiny responses (robots.txt stays plain).
Bypass via X-No-Compress: 1 header for debug. Vary: Accept-Encoding emitted
so CDN caches don't poison clients that can't decode.
Reversible: 1 npm dep, 9-line middleware block, no env/config changes.
---
package-lock.json | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
package.json | 7 +++---
server.js | 12 +++++++++++
3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 09f946e..09baf00 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"license": "ISC",
"dependencies": {
"@dw/inline-editor": "file:../inline-editor",
+ "compression": "^1.8.1",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"jsonwebtoken": "^9.0.3"
@@ -112,6 +113,60 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
+ "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "compressible": "~2.0.18",
+ "debug": "2.6.9",
+ "negotiator": "~0.6.4",
+ "on-headers": "~1.1.0",
+ "safe-buffer": "5.2.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/compression/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/compression/node_modules/negotiator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/content-disposition": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
@@ -673,6 +728,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/on-headers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
diff --git a/package.json b/package.json
index 6d2e21b..8a60518 100644
--- a/package.json
+++ b/package.json
@@ -11,9 +11,10 @@
"license": "ISC",
"description": "",
"dependencies": {
+ "@dw/inline-editor": "file:../inline-editor",
+ "compression": "^1.8.1",
"dotenv": "^17.4.2",
"express": "^5.2.1",
- "jsonwebtoken": "^9.0.3",
- "@dw/inline-editor": "file:../inline-editor"
+ "jsonwebtoken": "^9.0.3"
}
-}
\ No newline at end of file
+}
diff --git a/server.js b/server.js
index 8c58703..e6d9211 100644
--- a/server.js
+++ b/server.js
@@ -72,6 +72,18 @@ function isRoomsAdmin(req) {
|| (req.query && req.query.admin === ADMIN_TOKEN);
}
+// gzip + brotli on everything compressible. PNGs are already deflated so the
+// middleware filter skips them; HTML/JS/CSS/JSON drops ~70%. Threshold 1KB
+// avoids overhead for tiny responses. Bypass-able via X-No-Compress header.
+const compression = require('compression');
+app.use(compression({
+ threshold: 1024,
+ filter: (req, res) => {
+ if (req.headers['x-no-compress']) return false;
+ return compression.filter(req, res);
+ }
+}));
+
app.use(express.json({ limit: '25mb' })); // 25mb to accept full-res baked PNGs from /api/design/:id/bake
app.use(express.urlencoded({ extended: false }));
← 70b4570 security — close path traversal + shell injection in /api/st
·
back to Wallco Ai
·
security — prototype-pollution + pin-spam DoS guards in src/ 0772bf0 →