← back to Wallpaperhistory
initial scaffold: wallpaperhistory.com chronological timeline
ad4a8e7e4f635b3f85529857c34162b62332fe4b · 2026-05-07 16:48:42 -0700 · Steve Abrams
Files touched
A .gitignoreA package-lock.jsonA package.jsonA public/index.htmlA server.js
Diff
commit ad4a8e7e4f635b3f85529857c34162b62332fe4b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu May 7 16:48:42 2026 -0700
initial scaffold: wallpaperhistory.com chronological timeline
---
.gitignore | 7 +
package-lock.json | 842 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
package.json | 12 +
public/index.html | 551 +++++++++++++++++++++++++++++++++++
server.js | 14 +
5 files changed, 1426 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..08240ae
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+node_modules/
+.env*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..999eed0
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,842 @@
+{
+ "name": "wallpaperhistory",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "wallpaperhistory",
+ "version": "0.1.0",
+ "dependencies": {
+ "express": "^4.22.1"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.5",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
+ "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.15.1",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/qs": {
+ "version": "6.15.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
+ "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+ "license": "MIT"
+ },
+ "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/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "~0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "~6.14.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "~2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "~2.0.2",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+ "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
+ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
+ "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/send": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "~2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "~2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "~0.19.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..95f89a4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "wallpaperhistory",
+ "version": "0.1.0",
+ "description": "Chronological history of wallpaper — wallpaperhistory.com",
+ "main": "server.js",
+ "scripts": {
+ "start": "node server.js"
+ },
+ "dependencies": {
+ "express": "^4.22.1"
+ }
+}
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..436aa01
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,551 @@
+<!DOCTYPE html>
+<html lang="en" data-theme="dark">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Wallpaper History | From 1509 to the Digital Age | Designer Wallcoverings</title>
+<meta name="description" content="The complete chronological history of wallpaper — from Jesuits and chinoiserie in 1509 to today's digital murals. Expert trade service and free samples at Designer Wallcoverings.">
+<link rel="preconnect" href="https://fonts.googleapis.com">
+<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&display=swap" rel="stylesheet">
+<script type="application/ld+json">
+{
+ "@context": "https://schema.org",
+ "@type": "WebSite",
+ "name": "Wallpaper History",
+ "url": "https://wallpaperhistory.com",
+ "description": "Chronological history of wallpaper and wallcovering from the 16th century to the present",
+ "publisher": {
+ "@type": "Organization",
+ "name": "Designer Wallcoverings",
+ "url": "https://designerwallcoverings.com"
+ }
+}
+</script>
+<style>
+/* ===== THEME ===== */
+:root {
+ --bg: #0a0a0a;
+ --ink: #f5f1e8;
+ --ink-soft: rgba(245,241,232,0.72);
+ --ink-faint: rgba(245,241,232,0.38);
+ --line: rgba(245,241,232,0.10);
+ --card-bg: rgba(245,241,232,0.04);
+ --header-bg: rgba(10,10,10,0.92);
+ --accent: #a78651;
+ --accent-dim: rgba(167,134,81,0.18);
+ --accent-glow: rgba(167,134,81,0.28);
+ --rule: rgba(245,241,232,0.10);
+ --timeline-line: rgba(167,134,81,0.30);
+}
+[data-theme="light"] {
+ --bg: #faf6ee;
+ --ink: #1a1608;
+ --ink-soft: rgba(26,22,8,0.72);
+ --ink-faint: rgba(26,22,8,0.38);
+ --line: rgba(26,22,8,0.10);
+ --card-bg: rgba(26,22,8,0.04);
+ --header-bg: rgba(250,246,238,0.92);
+}
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+html { scroll-behavior: smooth; }
+
+body {
+ background: var(--bg);
+ color: var(--ink);
+ font-family: 'EB Garamond', Georgia, serif;
+ line-height: 1.7;
+ transition: background 0.3s, color 0.3s;
+}
+
+/* ===== HEADER ===== */
+.header {
+ position: sticky; top: 0; z-index: 100;
+ background: var(--header-bg);
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+ border-bottom: 1px solid var(--line);
+ padding: 0 2rem; height: 64px;
+ display: flex; align-items: center; justify-content: space-between;
+}
+.header-brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
+.brand-dot {
+ width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
+ background: radial-gradient(circle at 35% 35%, #c4a265 0%, #a78651 60%, #6b5229 100%);
+ box-shadow: 0 0 0 1px var(--line), 0 2px 12px var(--accent-glow);
+}
+.brand-name {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: 1.2rem; font-weight: 400; letter-spacing: 0.04em;
+ color: var(--ink);
+}
+.header-nav { display: flex; align-items: center; gap: 1.5rem; }
+.header-nav a {
+ color: var(--ink-soft); text-decoration: none;
+ font-size: 0.92rem; letter-spacing: 0.04em;
+ transition: color 0.2s;
+}
+.header-nav a:hover { color: var(--accent); }
+.theme-toggle {
+ background: none; border: 1px solid var(--line); border-radius: 50%;
+ width: 36px; height: 36px; cursor: pointer; display: flex;
+ align-items: center; justify-content: center;
+ color: var(--ink-soft); transition: border-color 0.2s, color 0.2s;
+}
+.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
+
+/* ===== HERO ===== */
+.hero {
+ position: relative; height: 90vh; min-height: 580px;
+ overflow: hidden; display: flex; align-items: center; justify-content: center;
+ text-align: center;
+}
+.hero-img {
+ position: absolute; inset: 0;
+ background-image: url('https://cdn.shopify.com/s/files/1/0015/4117/7456/files/LesTapisseries_Floraison_97870_Roomshot_Web_LR-medium-two-thirds.jpg');
+ background-size: cover; background-position: center;
+ filter: sepia(30%) brightness(0.8);
+}
+.hero-overlay {
+ position: absolute; inset: 0;
+ background: radial-gradient(ellipse at center,
+ rgba(10,10,10,0.30) 0%,
+ rgba(10,10,10,0.75) 100%);
+}
+.hero-content {
+ position: relative; z-index: 2;
+ max-width: 800px; padding: 2rem;
+}
+.hero-date {
+ display: inline-block;
+ font-size: 0.8rem; letter-spacing: 0.26em; text-transform: uppercase;
+ color: var(--accent); margin-bottom: 1.2rem;
+ padding: 0.3rem 1.2rem;
+ border: 1px solid rgba(167,134,81,0.4); border-radius: 100px;
+ background: rgba(167,134,81,0.08);
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+}
+.hero h1 {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: clamp(3rem, 7vw, 6rem);
+ font-weight: 400; line-height: 1.0;
+ color: #f5f1e8; margin-bottom: 1.4rem;
+ text-shadow: 0 2px 30px rgba(0,0,0,0.6);
+ letter-spacing: -0.01em;
+}
+.hero h1 em { font-style: italic; color: var(--accent); }
+.hero-tagline {
+ font-size: 1.15rem; color: rgba(245,241,232,0.80);
+ max-width: 520px; margin: 0 auto; line-height: 1.75;
+ font-style: italic;
+}
+
+/* ===== SECTION MARKER ===== */
+.section-marker {
+ position: sticky; top: 64px; z-index: 90;
+ background: rgba(10,10,10,0.85);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border-bottom: 1px solid var(--rule);
+ padding: 0.5rem 2rem;
+ font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase;
+ color: var(--accent);
+}
+[data-theme="light"] .section-marker { background: rgba(250,246,238,0.88); }
+
+/* ===== SECTIONS ===== */
+.section { padding: 5rem 2rem; max-width: 900px; margin: 0 auto; }
+.section-label {
+ font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase;
+ color: var(--accent); margin-bottom: 0.6rem;
+ font-family: -apple-system, system-ui, sans-serif;
+}
+.section h2 {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: clamp(1.8rem, 3vw, 2.8rem);
+ font-weight: 400; margin-bottom: 1.5rem;
+}
+.intro-text { font-size: 1.1rem; color: var(--ink-soft); max-width: 680px; line-height: 1.9; }
+
+/* ===== TIMELINE ===== */
+.timeline { position: relative; padding-left: 3.5rem; }
+.timeline::before {
+ content: '';
+ position: absolute; left: 1rem; top: 0; bottom: 0; width: 1px;
+ background: var(--timeline-line);
+}
+
+/* Decade marker — sticky */
+.decade-marker {
+ position: sticky; top: calc(64px + 38px); z-index: 70;
+ margin-left: -3.5rem; margin-bottom: 1.5rem;
+ background: rgba(10,10,10,0.85);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ border-bottom: 1px solid var(--rule);
+ border-top: 1px solid var(--rule);
+ padding: 0.45rem 1.5rem 0.45rem 3.5rem;
+}
+[data-theme="light"] .decade-marker { background: rgba(250,246,238,0.88); }
+.decade-label {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: 1.4rem; font-weight: 400; color: var(--accent);
+ letter-spacing: 0.04em; font-style: italic;
+}
+
+/* Timeline entry */
+.timeline-entry {
+ position: relative; margin-bottom: 2.5rem; padding-bottom: 1rem;
+}
+.timeline-dot {
+ position: absolute; left: -2.5rem;
+ width: 14px; height: 14px; border-radius: 50%;
+ background: var(--bg); border: 2px solid var(--accent);
+ box-shadow: 0 0 0 3px var(--accent-dim);
+ top: 0.35rem;
+}
+.timeline-year {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: 0.85rem; letter-spacing: 0.12em;
+ color: var(--accent); margin-bottom: 0.3rem;
+ font-style: italic;
+}
+.timeline-card {
+ background: var(--card-bg);
+ border: 1px solid var(--line);
+ border-radius: 8px; padding: 1.4rem 1.8rem;
+ backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
+ transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
+}
+.timeline-card:hover {
+ transform: translateX(3px);
+ box-shadow: 0 4px 28px var(--accent-glow);
+ border-color: rgba(167,134,81,0.28);
+}
+.timeline-title {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: 1.2rem; font-weight: 500; margin-bottom: 0.6rem; color: var(--ink);
+}
+.timeline-body { font-size: 1rem; color: var(--ink-soft); line-height: 1.85; }
+
+/* ===== IMAGE BREAK ===== */
+.image-break {
+ margin: 2rem 0 3rem; border-radius: 10px; overflow: hidden;
+ border: 1px solid var(--line); position: relative;
+ margin-left: -3.5rem;
+}
+.image-break img {
+ width: 100%; height: 300px; object-fit: cover; display: block;
+ filter: sepia(15%) brightness(0.9);
+}
+.image-break-caption {
+ position: absolute; bottom: 0; left: 0; right: 0;
+ background: rgba(10,10,10,0.78);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ padding: 0.85rem 1.2rem;
+ font-size: 0.82rem; color: var(--ink-soft);
+ font-style: italic;
+}
+[data-theme="light"] .image-break-caption { background: rgba(250,246,238,0.85); }
+
+/* ===== CTA ===== */
+.cta-section {
+ background: var(--card-bg);
+ border: 1px solid var(--line);
+ border-radius: 16px; padding: 4rem 3rem; text-align: center;
+ backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
+ margin: 4rem auto; max-width: 760px;
+}
+.cta-section h2 {
+ font-family: 'EB Garamond', Georgia, serif;
+ font-size: 2.2rem; font-weight: 400; margin-bottom: 1rem;
+}
+.cta-section p { color: var(--ink-soft); margin-bottom: 2rem; font-size: 1.05rem; line-height: 1.8; }
+.cta-btn {
+ display: inline-block; padding: 0.9rem 2.5rem;
+ background: var(--accent); color: #0a0a0a;
+ text-decoration: none; border-radius: 4px;
+ font-family: -apple-system, system-ui, sans-serif;
+ font-weight: 600; font-size: 0.85rem; letter-spacing: 0.08em;
+ text-transform: uppercase; transition: opacity 0.2s, transform 0.2s;
+}
+.cta-btn:hover { opacity: 0.88; transform: translateY(-1px); }
+
+/* ===== FOOTER ===== */
+.footer {
+ border-top: 1px solid var(--line);
+ padding: 2.5rem 2rem; text-align: center;
+ color: var(--ink-faint); font-size: 0.88rem;
+ font-family: 'EB Garamond', Georgia, serif;
+}
+.footer a { color: var(--accent); text-decoration: none; }
+
+@media (max-width: 640px) {
+ .header-nav { display: none; }
+ .timeline { padding-left: 2rem; }
+ .decade-marker { margin-left: -2rem; padding-left: 2rem; }
+ .timeline-dot { left: -1.5rem; }
+ .image-break { margin-left: -2rem; }
+ .hero h1 { font-size: 2.8rem; }
+}
+</style>
+<script>
+(function(){
+ var t = localStorage.getItem('theme') || 'dark';
+ document.documentElement.setAttribute('data-theme', t);
+})();
+</script>
+</head>
+<body>
+
+<header class="header">
+ <a href="/" class="header-brand">
+ <div class="brand-dot"></div>
+ <span class="brand-name">Wallpaper History</span>
+ </a>
+ <nav class="header-nav">
+ <a href="#timeline">Timeline</a>
+ <a href="#cta">Shop DW</a>
+ <a href="https://designerwallcoverings.com" target="_blank">DW</a>
+ </nav>
+ <button class="theme-toggle" id="themeToggle" aria-label="Toggle dark/light mode">
+ <svg id="iconSun" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display:none"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
+ <svg id="iconMoon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
+ </button>
+</header>
+
+<section class="hero">
+ <div class="hero-img"></div>
+ <div class="hero-overlay"></div>
+ <div class="hero-content">
+ <span class="hero-date">1509 — Present</span>
+ <h1>The History<br>of <em>Wallpaper</em></h1>
+ <p class="hero-tagline">Five centuries of pattern, craft, and cultural expression — from hand-painted Chinese silk to digital photomurals.</p>
+ </div>
+</section>
+
+<div class="section-marker">Chronological Record</div>
+
+<section class="section" id="intro">
+ <p class="section-label">Introduction</p>
+ <h2>Five centuries of covering walls with beauty</h2>
+ <p class="intro-text">Wallpaper is among the most telling artifacts of any era. Its subjects, materials, and methods of production reveal what a society found beautiful, what it aspired to, and what technologies it had mastered. From the chinoiserie panels that once required a Jesuit intermediary to procure, to the screen-printed art deco geometrics of the Jazz Age, to the photorealistic botanical murals of today — wallpaper has always been a cultural document as much as a decorative surface. This timeline traces the twelve most significant moments in that story.</p>
+</section>
+
+<section class="section" id="timeline">
+ <p class="section-label">1509 – Present</p>
+ <h2>The Timeline</h2>
+
+ <div class="timeline">
+
+ <!-- 1500s -->
+ <div class="decade-marker" id="1500s">
+ <span class="decade-label">The 16th Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">c. 1509</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Chinoiserie arrives in Europe via Jesuit trade routes</div>
+ <div class="timeline-body">The earliest documented European wallcoverings were hand-painted Chinese panels depicting idealized garden scenes, exotic birds, and pagodas. Jesuit missionaries and Portuguese traders brought these goods from China and Japan to the courts of Francis I and Henry VIII. The style — later named chinoiserie by French critics — would dominate luxury interiors for two centuries and remains one of the most enduring aesthetic influences in wallcovering design.</div>
+ </div>
+ </div>
+
+ <!-- Image break 1 -->
+ <div class="image-break">
+ <img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/2006101_517_86aa6f6e-b809-41ef-903c-7aa4fd878a79.jpg" alt="Chinese Lantern Coral wallcovering in chinoiserie tradition" loading="lazy">
+ <div class="image-break-caption">Lee Jofa "Chinese Lantern Coral" — a modern interpretation of the chinoiserie tradition that arrived in Europe in the early 16th century.</div>
+ </div>
+
+ <!-- 1600s -->
+ <div class="decade-marker" id="1600s">
+ <span class="decade-label">The 17th Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1675</div>
+ <div class="timeline-card">
+ <div class="timeline-title">English block-printing workshops establish a domestic industry</div>
+ <div class="timeline-body">By the 1670s, English workshops in London and the Midlands were producing block-printed wallpaper in quantity — initially as cheaper alternatives to costly imported Chinese goods and to the hand-painted painted textile wall hangings favored by the aristocracy. Dominoterie, a French trade in decorative printed paper, had existed since the mid-1500s, but the English block-print tradition produced wider sheets and more elaborate multi-color designs, establishing wallpaper as a distinct decorative category rather than a substitute fabric.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1694</div>
+ <div class="timeline-card">
+ <div class="timeline-title">The Flock technique transforms texture in European interiors</div>
+ <div class="timeline-body">Flock wallpaper — created by adhering chopped wool fibers to adhesive-printed patterns — reached a high point in English production in the late 17th century. The technique convincingly mimicked expensive cut velvet and Genoa velvet, providing aristocratic texture at a fraction of the cost. By the 1690s, flock wallpaper was appearing in the state rooms of English country houses and was documented in the accounts of Christopher Wren's building projects.</div>
+ </div>
+ </div>
+
+ <!-- 1700s -->
+ <div class="decade-marker" id="1700s">
+ <span class="decade-label">The 18th Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1760</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Oberkampf founds Jouy — the Toile tradition begins</div>
+ <div class="timeline-body">Christophe-Philippe Oberkampf established his manufacture at Jouy-en-Josas, outside Paris, producing the copperplate-engraved scenic prints that would later bear the name toile de Jouy. Though primarily a textile manufacturer, Oberkampf's pictorial vocabulary — pastoral scenes, classical allegories, narrative landscapes — crossed directly into French wallpaper production. The toile format, featuring fine-line engravings in a single color on a contrasting ground, became a defining idiom of 18th-century decorative art on both fabric and paper.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1786</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Réveillon and the French panoramic wallpaper tradition</div>
+ <div class="timeline-body">Jean-Baptiste Réveillon's Paris manufactory produced the most technically ambitious wallpapers of the 18th century — large-format scenic compositions printed from dozens of blocks in full color. Réveillon employed the finest designers of the day, including Jean-Baptiste Pillement, and his goods were prized across Europe. The French panoramic tradition he pioneered would culminate in the extraordinary productions of Zuber & Cie, whose hand-block-printed panoramic series (some requiring more than 3,000 individual blocks) are still in production today.</div>
+ </div>
+ </div>
+
+ <!-- Image break 2 -->
+ <div class="image-break">
+ <img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Indienne_Poona_18300_Roomshot_Web_LR-og_2018d1c6-6247-46e3-959d-95569075202b.jpg" alt="Arte Poona Stone wallcovering in a richly patterned interior" loading="lazy">
+ <div class="image-break-caption">Arte International "Poona Stone" — a contemporary echo of the 18th-century French tradition of nature-derived allover pattern.</div>
+ </div>
+
+ <!-- 1800s -->
+ <div class="decade-marker" id="1800s">
+ <span class="decade-label">The 19th Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1839</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Steam-powered continuous printing democratizes wallpaper</div>
+ <div class="timeline-body">The development of mechanized steam printing in Britain in the 1830s — producing continuous rolls rather than individual sheets — reduced the cost of wallpaper dramatically. By 1850, pattern books from manufacturers like Potters of Darwen were reaching the new Victorian middle class. Wallpaper shifted from aristocratic luxury to a domestic essential for every parlor with any pretension to respectability. Production volumes increased by several orders of magnitude within a single decade.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1870</div>
+ <div class="timeline-card">
+ <div class="timeline-title">William Morris and the Arts and Crafts reaction</div>
+ <div class="timeline-body">Horrified by the visual vulgarity of machine-produced Victorian wallpaper — its analine dyes, its three-dimensional trompe-l'oeil naturalism, its eclectic historicism — William Morris began designing flat, nature-derived wallpapers in the late 1860s. "Trellis" (1864) was followed by "Daisy," "Fruit," and the masterly "Acanthus" (1874). Morris rejected mechanical printing in favor of hand-block production and natural dyes. His influence on wallpaper design persisted well into the 20th century and his patterns remain in production under Sanderson Archive today.</div>
+ </div>
+ </div>
+
+ <!-- Image break 3 -->
+ <div class="image-break">
+ <img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/EssentialsLuxor_Thebe_19460_Roomshot_Web_LR-og.jpg" alt="Arte Thebe Terra wallcovering in a warm-toned contemporary interior" loading="lazy">
+ <div class="image-break-caption">Arte International "Thebe Terra" — geometric clarity that reflects the Arts and Crafts principle of honest flat pattern over illusionistic naturalism.</div>
+ </div>
+
+ <!-- 1900s -->
+ <div class="decade-marker" id="1900s">
+ <span class="decade-label">The 20th Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1920s</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Art Deco: geometry, metallics, and the machine aesthetic</div>
+ <div class="timeline-body">The Exposition Internationale des Arts Décoratifs et Industriels Modernes (Paris, 1925) crystallized the Art Deco vocabulary that would dominate luxury interiors through the late 1920s and into the 1930s. In wallcovering, this translated to bold geometric repeats, metallic silver and gold grounds, stylized botanical and animal motifs, and an embrace of the machine-made surface as beautiful rather than shameful. Mylar predecessors — foil-laminated papers — appear in Art Deco interiors as early as 1924.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1950s</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Mid-century scenic and abstract wallpaper define postwar domesticity</div>
+ <div class="timeline-body">American suburban expansion created an enormous market for residential wallpaper in the late 1940s and 1950s. Manufacturers responded with scenic murals depicting Hawaiian beaches, European village life, and American landscapes. Simultaneously, the influence of European modern design — Bauhaus geometry, Scandinavian naturalism — produced a distinctive mid-century graphic vocabulary of boomerangs, atomic starbursts, and abstracted botanicals that still reads instantly as the period.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">1970s</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Foil and Mylar: the reflective decade</div>
+ <div class="timeline-body">Polyester film (Mylar) technology matured in the early 1960s and by the 1970s, foil and Mylar wallcovering had become a defining material of disco-era interiors. Highly reflective surfaces in gold, silver, copper, and bronze appeared in restaurants, nightclubs, and luxury apartments. The practical difficulties of installation — Mylar requires perfectly prepared, plumb walls to avoid distortion — limited mass adoption, preserving it as a prestige material. Modern Mylar wallcoverings improve on the originals significantly in printability and dimensional stability.</div>
+ </div>
+ </div>
+
+ <!-- Image break 4 -->
+ <div class="image-break">
+ <img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/2020205_50_a98ae134-3d4e-44a9-91a1-1e0e93c34a22.jpg" alt="Lee Jofa Marion Print Indigo wallcovering in a styled space" loading="lazy">
+ <div class="image-break-caption">Lee Jofa "Marion Print Indigo" — a contemporary pattern that draws on the mid-century tradition of bold, high-contrast graphic design in residential wallcovering.</div>
+ </div>
+
+ <!-- 2000s -->
+ <div class="decade-marker" id="2000s">
+ <span class="decade-label">The 21st Century</span>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">2010s</div>
+ <div class="timeline-card">
+ <div class="timeline-title">Digital print and the custom mural revolution</div>
+ <div class="timeline-body">The wide-format inkjet printing revolution — combined with the proliferation of high-resolution photographic and digital illustration assets — created an entirely new category of wallcovering in the 2010s: the custom digital mural. Any image could now become a wall, at any scale, with no screen setup cost. Small studios and independent artists entered the market alongside established manufacturers. Platforms connecting consumers directly to print providers reduced the premium for bespoke work dramatically. The industry's economics shifted permanently.</div>
+ </div>
+ </div>
+
+ <div class="timeline-entry">
+ <div class="timeline-dot"></div>
+ <div class="timeline-year">Now</div>
+ <div class="timeline-card">
+ <div class="timeline-title">The sustainable and natural fiber renaissance</div>
+ <div class="timeline-body">The dominant design conversation in wallcovering today concerns materiality and environmental impact. Grasscloth, abaca, seagrass, cork, and recycled-fiber non-wovens are commanding premiums in both residential and contract markets. Manufacturers are reformulating PVC-based products with phthalate-free compounds and water-based inks. The hand-blocked artisanal revival, initiated by small ateliers and amplified by social media, has returned to the fore alongside mass-market digital production — creating a market that is simultaneously the most diverse and the most technically sophisticated in the medium's 500-year history.</div>
+ </div>
+ </div>
+
+ </div>
+</section>
+
+<div class="section-marker">Shop the Catalog</div>
+
+<section class="section" id="cta">
+ <div class="cta-section">
+ <h2>Five centuries of craft, available with free samples</h2>
+ <p>Designer Wallcoverings carries patterns that draw on every chapter of this history — from block-printed naturals to digital custom murals, from grasscloth to foil. Order a free memo sample and let our team help you find the right expression for your space.</p>
+ <a href="https://designerwallcoverings.com" target="_blank" class="cta-btn">Explore the Full Catalog</a>
+ </div>
+</section>
+
+<footer class="footer">
+ <p>© 2026 Wallpaper History — A resource by <a href="https://designerwallcoverings.com">Designer Wallcoverings</a></p>
+ <p style="margin-top:0.5rem;"><a href="mailto:info@wallpaperhistory.com">info@wallpaperhistory.com</a></p>
+</footer>
+
+<script>
+const toggle = document.getElementById('themeToggle');
+const sun = document.getElementById('iconSun');
+const moon = document.getElementById('iconMoon');
+function applyTheme(t) {
+ document.documentElement.setAttribute('data-theme', t);
+ localStorage.setItem('theme', t);
+ sun.style.display = t === 'light' ? 'block' : 'none';
+ moon.style.display = t === 'dark' ? 'block' : 'none';
+}
+applyTheme(localStorage.getItem('theme') || 'dark');
+toggle.addEventListener('click', () => {
+ const current = document.documentElement.getAttribute('data-theme');
+ applyTheme(current === 'dark' ? 'light' : 'dark');
+});
+
+// Parallax effect on hero image
+const heroImg = document.querySelector('.hero-img');
+if (heroImg) {
+ window.addEventListener('scroll', () => {
+ const scrolled = window.scrollY;
+ heroImg.style.transform = `translateY(${scrolled * 0.3}px)`;
+ }, { passive: true });
+}
+</script>
+</body>
+</html>
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..0906c5c
--- /dev/null
+++ b/server.js
@@ -0,0 +1,14 @@
+const express = require('express');
+const path = require('path');
+const app = express();
+const PORT = process.env.PORT || 9903;
+
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.get('/health', (req, res) => res.json({ status: 'ok', site: 'wallpaperhistory.com' }));
+
+app.get('/', (req, res) => {
+ res.sendFile(path.join(__dirname, 'public', 'index.html'));
+});
+
+app.listen(PORT, () => console.log(`wallpaperhistory.com :${PORT}`));
(oldest)
·
back to Wallpaperhistory
·
snapshot before hamburger nav rollout bb522ab →