From ca89d15c2aec46b9b35d8893f7d9d6d81d17b3b1 Mon Sep 17 00:00:00 2001 From: martbost Date: Sat, 19 Sep 2026 04:31:56 -0500 Subject: [PATCH] A curtain in front of the whole app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Work in progress should not be readable by anyone who wanders in. CURTAIN= puts a contentless "Coming soon" card in front of every request — pages, APIs, the rotator, the link domains — with noindex headers and nothing that names the product or what it does. Opening the site once with ?k= drops a cookie that lifts it for that browser. Unsetting CURTAIN opens the site again, so this never has to be picked back out of the code. It sits at the very top of the request handler, ahead of the rotator and the link-domain sites, so there is no path around it. Co-Authored-By: Claude Opus 5 (1M context) --- server.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/server.js b/server.js index c2f2acb..f685697 100644 --- a/server.js +++ b/server.js @@ -817,10 +817,50 @@ function linkSitePage(host, page) { } // ---- server ---- +// ---- the curtain ---------------------------------------------------------- +// Work in progress is not for passers-by. CURTAIN= puts a contentless holding page +// in front of every request; ?k= sets a cookie that lifts it for that browser. +const CURTAIN = String(process.env.CURTAIN || '').trim(); +const CURTAIN_PAGE = ` + +Coming soon

Coming soon

This site is still being built.

`; + +function curtained(req, res, u) { + if (!CURTAIN) return false; + if (u.searchParams.get('k') === CURTAIN) { + u.searchParams.delete('k'); + res.writeHead(302, { + 'Set-Cookie': 'ls.pass=' + encodeURIComponent(CURTAIN) + '; Path=/; Max-Age=2592000; HttpOnly; SameSite=Lax; Secure', + Location: u.pathname + (u.searchParams.toString() ? '?' + u.searchParams : ''), + 'Cache-Control': 'no-store' + }); + res.end(); + return true; + } + const pass = /(?:^|;\s*)ls\.pass=([^;]*)/.exec(req.headers.cookie || ''); + if (pass && decodeURIComponent(pass[1]) === CURTAIN) return false; + res.writeHead(503, { + 'Content-Type': 'text/html; charset=utf-8', + 'Cache-Control': 'no-store', + 'X-Robots-Tag': 'noindex, nofollow' + }); + res.end(req.method === 'HEAD' ? '' : CURTAIN_PAGE); + return true; +} + const server = http.createServer(async (req, res) => { try { const u = new URL(req.url, 'http://x'); const p = u.pathname; + if (curtained(req, res, u)) return; // nothing below this line runs for an uninvited visitor // -- the rotator redirect: one hop, recorded, on any host (LinkSpin) let rm = /^\/r\/([a-z0-9]{4,12})$/i.exec(p);