← back to Fleet Wall
server.mjs
54 lines
import http from 'http'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PORT = process.env.PORT || 9975, USER='admin', PASS='DW2024!';
const doms = fs.readFileSync(path.join(__dirname,'data','domains.txt'),'utf8').split('\n').map(s=>s.trim()).filter(d=>/\./.test(d) && !/^\d+\.\d+\.\d+\.\d+$/.test(d));
function page(){
const cat = d => d.endsWith('designerwallcoverings.com')?'DW microsite': d.endsWith('agentabrams.com')?'agentabrams': 'apex';
const DATA = JSON.stringify(doms.map(d=>({d,c:cat(d)})));
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Fleet Wall</title><style>
:root{--bg:#111;--panel:#1b1b1d;--ink:#eee;--muted:#9a958d;--rule:#2c2c30;--accent:#2f7a4f;--cols:4}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:13px/1.4 -apple-system,'Segoe UI',Roboto,sans-serif}
.bar{position:sticky;top:0;z-index:10;background:#0c0c0d;border-bottom:1px solid var(--rule);padding:12px 18px;display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.bar h1{font-size:16px;margin:0}.bar .n{color:var(--muted)}
select,input[type=range]{background:var(--panel);color:var(--ink);border:1px solid var(--rule);border-radius:6px;padding:6px 9px}
.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:12px;padding:16px}
.cell{background:var(--panel);border:1px solid var(--rule);border-radius:9px;overflow:hidden;display:flex;flex-direction:column;height:280px}
.cell .h{display:flex;justify-content:space-between;align-items:center;padding:6px 9px;font-size:11px;border-bottom:1px solid var(--rule);gap:6px}
.cell .h a{color:var(--accent);text-decoration:none;font-family:ui-monospace,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cell .h .tag{color:var(--muted);flex:none;font-size:9.5px;text-transform:uppercase;letter-spacing:.05em}
.fr{flex:1;position:relative;background:#0a0a0a}
.fr iframe{position:absolute;inset:0;width:100%;height:100%;border:0;background:#fff}
.fr .ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:11px;text-align:center;padding:10px}
.fr.blocked .ph::after{content:" — frame blocked (X-Frame-Options)"}
</style></head><body>
<div class="bar"><h1>Fleet Wall</h1><span class="n" id="cnt"></span>
<label>Filter <select id="cat"><option value="">All</option><option>DW microsite</option><option>agentabrams</option><option>apex</option></select></label>
<label>Sort <select id="sort"><option value="domain">Domain A→Z</option><option value="cat">Category</option></select></label>
<label>Density <input type="range" id="dens" min="2" max="8" value="4"></label></div>
<div class="grid" id="grid"></div>
<script>
const DATA=${DATA};
const grid=document.getElementById('grid'),cnt=document.getElementById('cnt'),dens=document.getElementById('dens'),cat=document.getElementById('cat'),sort=document.getElementById('sort');
try{const s=localStorage.getItem('fw_dens');if(s)dens.value=s;const c=localStorage.getItem('fw_cat');if(c)cat.value=c;const so=localStorage.getItem('fw_sort');if(so)sort.value=so;}catch(e){}
document.documentElement.style.setProperty('--cols',dens.value);
const io=new IntersectionObserver((es)=>{for(const e of es){if(e.isIntersecting){const f=e.target;if(!f.dataset.loaded){f.dataset.loaded=1;const ifr=document.createElement('iframe');ifr.loading='lazy';ifr.referrerPolicy='no-referrer';ifr.src='https://'+f.dataset.d+'/';ifr.onload=()=>{try{void ifr.contentWindow.location.href;}catch(_){/*cross-origin ok*/}};f.querySelector('.fr').appendChild(ifr);}io.unobserve(f);}}},{rootMargin:'400px'});
function render(){
let r=DATA.filter(x=>!cat.value||x.c===cat.value);
r.sort((a,b)=> sort.value==='cat'?(a.c.localeCompare(b.c)||a.d.localeCompare(b.d)):a.d.localeCompare(b.d));
cnt.textContent=r.length+' of '+DATA.length+' front pages';
grid.innerHTML=r.map(x=>'<div class="cell" data-d="'+x.d+'"><div class="h"><a href="https://'+x.d+'" target="_blank" rel="noopener">'+x.d+'</a><span class="tag">'+x.c+'</span></div><div class="fr"><div class="ph">loading…</div></div></div>').join('');
document.querySelectorAll('.cell').forEach(c=>io.observe(c));
}
dens.oninput=()=>{document.documentElement.style.setProperty('--cols',dens.value);try{localStorage.setItem('fw_dens',dens.value)}catch(e){}};
cat.onchange=()=>{try{localStorage.setItem('fw_cat',cat.value)}catch(e){}render()};
sort.onchange=()=>{try{localStorage.setItem('fw_sort',sort.value)}catch(e){}render()};
render();
</script></body></html>`;
}
http.createServer((req,res)=>{
const a=(req.headers.authorization||'').split(' ')[1]||'';const[u,p]=Buffer.from(a,'base64').toString().split(':');
if(u!==USER||p!==PASS){res.writeHead(401,{'WWW-Authenticate':'Basic realm=fleet'});return res.end('auth');}
res.writeHead(200,{'content-type':'text/html; charset=utf-8'});res.end(page());
}).listen(PORT,()=>console.log('Fleet Wall on http://127.0.0.1:'+PORT+' (admin/DW2024!) — '+doms.length+' front pages'));