Members area: weekly webinar replay page at /replays

Wallet-gated like the Method lessons: the API returns titles/dates to
everyone (prospects see the shape of the product) and video URLs only with a
member session. List lives in the data volume (replays.json) so the weekly
add never needs a deploy; videos stream from the DO Spaces bucket (CSP
media-src added). Teaser on /training; chatbot + AI prompt updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-02 06:46:06 -05:00
parent 726bc24e09
commit 79470e471c
5 changed files with 105 additions and 4 deletions
+1 -1
View File
@@ -48,7 +48,7 @@
{k:['cap','capped','cap out','max level','maximum level','8 levels','eight levels','after corona','top level','stop earning','earning cap','level cap','beyond corona'],
a:()=>`Your <strong>level</strong> caps at Corona (level 8) — you can't upgrade higher. But your <strong>earning doesn't cap</strong>. Two reasons: (1) you catch an upgrade pass-up from every person in your first seven generations as they level up, and those generations hold up to 254 positions that keep filling over time. (2) Pass-ups travel UP past anyone who can't catch them — when someone upgrades, the payment rises to the first upline who's qualified and leveled high enough (up to the contract's 16-layer depth cap; otherwise it goes to the project fee wallet). So Corona is the position that misses nothing: at max level you're eligible for every pass-up, you're never the bottleneck, and you catch the ones under-leveled members below you let slip. It's the whole reason to keep leveling up. Full breakdown: <a href="/how-pay-works#cap">rmcircle.team/how-pay-works#cap</a> — contract mechanics, verifiable on-chain, never a promise of income.`},
{k:['members area','member area','whats the product','what is the product','what am i buying','what do i get','members only','locked','unlock','sign in to training'],
a:()=>`Yes — every position includes a real members area: <strong>The Circle Method</strong> (10-lesson recruiting &amp; coaching course + a real cash-out walkthrough) on the <a href="/training">training page</a>, your <a href="/my">live coaching dashboard</a>, <a href="/tools">promo tools</a> personalized with your invite link, printable playbooks, wallet-verified team messaging, and the Telegram companion bot + Mini App. No passwords — access is proven by the wallet that owns your position (one free signature that can't move funds), and inside the Telegram Mini App it unlocks automatically. Lesson 1 and all the how-it-works videos are public so you can inspect everything before joining.`},
a:()=>`Yes — every position includes a real members area: <strong>The Circle Method</strong> (10-lesson recruiting &amp; coaching course + a real cash-out walkthrough) on the <a href="/training">training page</a>, the <a href="/replays">weekly team webinar replays</a>, your <a href="/my">live coaching dashboard</a>, <a href="/tools">promo tools</a> personalized with your invite link, printable playbooks, wallet-verified team messaging, and the Telegram companion bot + Mini App. No passwords — access is proven by the wallet that owns your position (one free signature that can't move funds), and inside the Telegram Mini App it unlocks automatically. Lesson 1 and all the how-it-works videos are public so you can inspect everything before joining.`},
{k:['no money','cant afford','can not afford',"can't afford",'broke','they dont have','waiting on payday','no funds to join'],
a:()=>`"No money" is usually one of three things — sort it first. (1) Most often it means "this sounds expensive/complicated": entry is ${pol()} POL${usd()||" — a small one-time amount"} — payable with a regular debit card right on the <a href="/join-now">join page</a>. (2) Sometimes it's a priority thing: send the "Pocket Change" video from <a href="/tools">Promo Tools</a> and let it do the talking. (3) If they're genuinely broke: tell them honestly "don't join yet" — never rent money, never money they can't afford to lose. Ask "when's payday?" and follow up then — their invite link doesn't expire and the team keeps building publicly while they wait. One hard rule: never pay someone's entry for them.`},
{k:['own the level','need to own','have to buy the level','catch without','still at scintilla','upline not upgraded','sponsor not upgraded','only pays 2','only pays two','only 2 payments','seems small','2 then 4','level is your reach'],
+17
View File
@@ -0,0 +1,17 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="Weekly RM Circle team webinar replays — a members-area benefit included with every position."><title>Webinar Replays | RM Circle Team Build</title>
<link rel="canonical" href="https://rmcircle.team/replays">
<meta property="og:type" content="website"><meta property="og:site_name" content="RM Circle Team Build"><meta property="og:title" content="Weekly Webinar Replays — RM Circle Team Build"><meta property="og:description" content="The team meets every week. Replays are included with every position — sign in with the wallet that owns yours."><meta property="og:url" content="https://rmcircle.team/replays"><meta property="og:image" content="https://rmcircle.team/og-card.jpg"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630">
<link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css"></head>
<body>
<header class="wrap nav"><a class="brand" href="/"><img class="brand-mark" src="/logo.jpg" alt="The RM Circle" width="42" height="42"><span><span id="brandName">RM Circle</span><small>Webinar Replays</small></span></a><div class="nav-actions"><a class="btn btn-secondary hide-mobile" href="/training">← Training</a><a class="btn btn-primary" href="/start">Get Started</a></div></header>
<main>
<section class="section"><div class="wrap"><div class="section-head"><div class="eyebrow">Members area</div><h1 style="font-size:clamp(34px,5vw,54px);margin:8px 0 10px">The team meets <span class="gold">every week.</span></h1><p>Live team webinars: what's working, member questions answered straight, and the plays to run this week. Miss one and the replay is here — included with every position, like the rest of the members area.</p></div>
<div id="replayStatus" style="max-width:880px;margin:0 auto 20px"></div>
<div id="replayList" style="max-width:880px;margin:0 auto"></div>
<div class="callout warning" style="max-width:880px;margin:26px auto 0"><strong>Risk reminder:</strong> webinars discuss a cryptocurrency team build. Nothing in them is an income promise or financial advice. Participation involves real risk — use only funds you can afford to lose.</div>
</div></section>
</main>
<footer class="wrap disclaimer">This is an independent RM Circle Team Build training resource. No income is guaranteed.<div class="footer-links"><a href="/">Strategy</a><a href="/training">Training</a><a href="/my">Member Dashboard</a><a href="/tools">Promo Tools</a><a href="/disclaimer">Disclaimers</a><a href="/privacy">Privacy</a><a href="/refunds">Refunds</a></div></footer>
<script src="/track.js"></script><script src="/rmc-wallet.js"></script><script src="/inapp-browser.js"></script><script src="/replays.js"></script><script src="/wallet-notice.js" defer></script><script src="/chat.js" defer></script><script src="/translate.js" defer></script><script src="/tg-app.js" defer></script><script src="/nav-dash.js" defer></script></body></html>
+71
View File
@@ -0,0 +1,71 @@
// Webinar replays — members-area page. The list comes from /api/public/replays:
// locked responses carry titles/dates only (prospects see the shape of the
// product), a member session gets the video URLs. Unlock is the same
// one-signature SIWE flow as the training page (msg-challenge/msg-verify via
// RMCWallet); Mini App visitors already carry a session and see no lock.
(function () {
'use strict';
function $(id) { return document.getElementById(id); }
function esc(s) { return String(s == null ? '' : s).replace(/[&<>'"]/g, function (c) { return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;' })[c]; }); }
function card(r, locked) {
var head = '<div style="padding:6px 6px 0"><div class="eyebrow" style="color:var(--teal)">' + esc(r.date || '') + (r.minutes ? ' · ' + esc(r.minutes) + ' min' : '') + '</div>' +
'<h2 style="margin:6px 0 6px">' + esc(r.title || 'Team webinar') + '</h2>' +
(r.blurb ? '<p style="color:var(--muted);margin:0 0 12px">' + esc(r.blurb) + '</p>' : '') + '</div>';
if (locked || !r.url) {
return '<div class="video-card rmc-lock" style="margin:0 0 26px">' + head +
'<div style="padding:8px 6px 10px">' +
'<p class="micro" style="color:var(--muted);margin:0 0 12px">🔒 Replays come with every team position. Sign in with the wallet that owns your position — one free signature, it can\'t move funds. Linked on Telegram? The ☰ Mini App in @RMCircleBot unlocks everything automatically.</p>' +
'<button class="btn btn-primary btn-sm rmc-unlock">🔓 I\'m a member — connect &amp; unlock</button> ' +
'<a class="btn btn-secondary btn-sm" href="/start">Not a member? See how to join</a>' +
'<div class="micro rmc-lock-err" style="color:#ff7b7b;margin-top:8px"></div></div></div>';
}
return '<div class="video-card" style="margin:0 0 26px">' + head +
'<video class="video-frame" style="display:block;width:100%;height:auto;aspect-ratio:16/9" controls preload="metadata"' + (r.poster ? ' poster="' + esc(r.poster) + '"' : '') + ' src="' + esc(r.url) + '"></video></div>';
}
var UNLOCK_LABEL = '🔓 I\'m a member — connect & unlock';
function wireUnlock() {
document.querySelectorAll('button.rmc-unlock').forEach(function (b) {
b.addEventListener('click', function (ev) {
var btn = ev.currentTarget, err = btn.closest('.rmc-lock').querySelector('.rmc-lock-err');
btn.disabled = true; btn.textContent = 'Connecting…';
(async function () {
try {
var eth = window.RMCWallet && await window.RMCWallet.pick();
if (!eth) { err.textContent = 'No wallet in this browser. On a phone, open this page inside your wallet app\'s browser — or use the Telegram Mini App.'; btn.disabled = false; btn.textContent = UNLOCK_LABEL; return; }
var accounts = await eth.request({ method: 'eth_requestAccounts' });
var account = accounts && accounts[0];
try { await window.RMCWallet.ensureChain(eth); } catch (ce) { err.textContent = 'Switch your wallet to the Polygon network, then tap unlock again.'; btn.disabled = false; btn.textContent = UNLOCK_LABEL; return; }
var ch = await (await fetch('/api/public/msg-challenge', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: account }) })).json();
if (ch.error) throw new Error(ch.error);
var sig = await eth.request({ method: 'personal_sign', params: [ch.message, account] });
var vr = await (await fetch('/api/public/msg-verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: account, signature: sig }) })).json();
if (vr.error) throw new Error(vr.error);
load();
} catch (e) { err.textContent = e.message || String(e); btn.disabled = false; btn.textContent = UNLOCK_LABEL; }
})();
});
});
}
function load() {
fetch('/api/public/replays').then(function (r) { return r.json(); }).then(function (d) {
var list = d.replays || [];
if (!list.length) {
$('replayList').innerHTML = '<div class="callout" style="text-align:center">The first replay is on its way — check back after this week\'s webinar.</div>';
return;
}
if (!d.locked) {
$('replayStatus').innerHTML = '<p class="micro" style="color:var(--ok);margin:0">✅ Members area unlocked — position #' + esc(d.id) + '</p>';
} else {
$('replayStatus').innerHTML = '';
}
$('replayList').innerHTML = list.map(function (r) { return card(r, d.locked); }).join('');
if (d.locked) wireUnlock();
}).catch(function () {
$('replayList').innerHTML = '<div class="callout warning">Could not load the replay list — refresh to try again.</div>';
});
}
load();
})();
+2
View File
@@ -29,6 +29,8 @@
<div style="display:flex;gap:16px;align-items:center;padding:14px 6px 6px;flex-wrap:wrap"><img src="/training/giftcard_wallet_example.jpg" alt="Virtual card added to a mobile wallet, ready to tap to pay" loading="lazy" style="width:170px;max-width:38%;height:auto;border-radius:12px;border:1px solid var(--line)"><p style="color:var(--muted);margin:0;flex:1;min-width:200px"><strong style="color:var(--text)">The end result from the video:</strong> a virtual card added to a mobile wallet, ready to tap-to-pay — groceries, gas, anywhere cards are accepted. It started as POL catches from the team build.</p></div></div>
<div class="callout" style="max-width:880px;margin:0 auto 26px"><strong>🎥 The team meets every week.</strong> Live webinars with what's working right now and member questions answered straight — and every replay is waiting in the members area. <a href="/replays" style="color:var(--teal);font-weight:700">Watch the webinar replays →</a></div>
<h2 id="circle-method" style="max-width:880px;margin:44px auto 6px;font-size:30px">⭕ The Circle Method — Module 1: Get Your Two</h2>
<p style="max-width:880px;margin:0 auto 20px;color:var(--muted)">Our recruiting course, taught by the team. Four short lessons that take you from "I could never recruit" to your first two curious people — the honest way: no pitching, no pressure, no income promises. Watch them in order, then run the plays. When your two join, send them these same lessons — that's the Method.</p>
<img src="/v/rmc-napkin.jpg" alt="The Circle Method sketched on a napkin: get your 2, help your 2 get theirs, teach them to do the same" style="display:block;max-width:880px;width:100%;margin:0 auto 26px;border-radius:16px;border:1px solid #23425d">
+14 -3
View File
@@ -91,7 +91,7 @@ FACTS:
- "What if I can't afford the upgrades?": upgrades are optional and self-paced; never use money you can't afford to lose; the first payments at each level are designed to help fund the next upgrade, so many let team activity pay their way up (see https://rmcircle.team/how-pay-works).
- "My prospect wants to join but has no money": coach the member to sort which of three objections it really is. (1) Most common — "sounds expensive/complicated": entry is ${c.premiumEntryPol || 362} POL — right now roughly ${entryUsdLine()} — payable with a regular debit card via the join page; many prospects imagine far more. ALWAYS quote the current dollar figure from this prompt, never a remembered one, and add that POL's price moves. (2) Priority dressed as money: send the "Pocket Change" curiosity video from /tools and go silent (it calls out weekly wasted spending — fully evergreen, no dollar figures) — never argue it. (3) Genuinely broke: the honest answer is "don't join yet" — never rent money, never desperation recruiting; ask "when's payday?" and follow up then. Waiting costs the prospect nothing: invite links don't expire and the team's growth is publicly visible on-chain while they wait. HARD RULE: nobody ever fronts or loans someone's entry — not the sponsor, not the team; it kills commitment and creates one person controlling positions registered to others' wallets. Teach-forward: have the member log how each conversation goes, because their people will hit the same objection.
- "Someone below me won't upgrade / is stalled": a paused member NEVER blocks money. Each person below you pays you separately, once, at one level — nothing waits on pairs or chains of upgrades. Payments a paused member can't catch pass straight UP through them to the next ready position (often the asker's), and everyone below the paused member keeps flowing normally; the only thing on hold is the single payment that person would send at the asker's matching level. Never pressure anyone — paused members keep collecting entry rewards from new team growth and often return once the upgrade funds itself. Point the asker at the pipeline panel on their dashboard to see who IS moving, and (teach-forward) have them show their two the same panel.
- "Is there a members area?": YES — a position unlocks: the Circle Method course (10 lessons + the real cash-out walkthrough) in the training members area, the live coaching dashboard at /my/<id>, promo tools personalized with their link at /tools, printable playbooks, wallet-verified team messaging, and the Telegram companion bot + Mini App. Access is by the wallet that owns the position — one free signature, no passwords — or automatic inside the Mini App.
- "Is there a members area?": YES — a position unlocks: the Circle Method course (10 lessons + the real cash-out walkthrough) in the training members area, the weekly team webinar replays at https://rmcircle.team/replays, the live coaching dashboard at /my/<id>, promo tools personalized with their link at /tools, printable playbooks, wallet-verified team messaging, and the Telegram companion bot + Mini App. Access is by the wallet that owns the position — one free signature, no passwords — or automatic inside the Mini App.
- "What's the actual product? / What do I get?": answer with the business-in-a-box inventory that comes with a position on THIS team: (1) The Circle Method — a complete 10-lesson recruiting & coaching course in the members area (Lesson 1 is a free preview; the rest unlocks with your position); (2) a promo arsenal — 4 professionally produced curiosity videos with matched landing pages, ready-made posts, descriptions, email swipes and a full banner kit, all auto-personalized with their invite link; (3) printable playbooks (48-Hour Fast Start + Weekly Rhythm) with their own QR code; (4) an AI coach on every page answering in 21+ languages around the clock; (5) a live coaching dashboard reading the blockchain — pipeline, org bar, coach panel, wallet-verified team messaging. Be clear this toolkit is provided by this team around the public smart contract; the contract itself is the payment engine, the toolkit is what this team adds.
- "I'm not a salesperson / I don't know anyone": there is nothing to sell — share a short video and an invite link; the site explains it; you need a couple of curious people, not a big network; ready-made promo tools are at https://rmcircle.team/tools.
- "What if people quit?": positions live on-chain and don't vanish when someone goes quiet; the team keeps building around the spot; focus on a few real builders, not volume. No income is guaranteed.
@@ -487,7 +487,7 @@ async function handleTranslate(req,res){
// frame-src includes 'self' so our own pages (the Page Builder preview framing
// a member's /p/<id> page) are not blocked by our own policy.
const CSP_BASE="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-src 'self' https://www.youtube-nocookie.com";
const CSP_BASE="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; media-src 'self' https://coolify-saasytop.nyc3.digitaloceanspaces.com; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-src 'self' https://www.youtube-nocookie.com";
function securityHeaders(extra={}) {
// Public pages must render inside safelist / traffic-exchange iframes, so framing stays open here; admin.html re-locks it via ADMIN_FRAME_HEADERS.
return {
@@ -942,6 +942,17 @@ async function handleApi(req,res,pathname){
}catch(err){ return json(res,502,{error:String(err.message||err)}); }
}
// ── Webinar replays (members area) ───────────────────────────────────────
// The list lives in DATA_DIR/replays.json so adding the weekly replay never
// needs a deploy. A locked response still returns titles/dates — prospects
// see the shape of the product — but never the video URLs.
if(req.method==='GET'&&pathname==='/api/public/replays'){
let list=[]; try{ list=readJson(path.join(DATA_DIR,'replays.json'))||[]; }catch(e){}
const member=messages.authFromCookie(req);
if(!member)return json(res,200,{locked:true,replays:list.map(r=>({title:r.title,date:r.date,minutes:r.minutes}))},{'Cache-Control':'no-store'});
return json(res,200,{locked:false,id:member.id,replays:list},{'Cache-Control':'no-store'});
}
// ── Traffic Desk ─────────────────────────────────────────────────────────
if(req.method==='GET'&&pathname==='/api/public/suite-traffic'){
const e=await suiteEntitlement(req).catch(()=>({error:'Chain read hiccup.',code:500}));
@@ -1593,7 +1604,7 @@ const server=http.createServer(async(req,res)=>{
if((mj=pathname.match(/^\/join\/(\d{1,15})$/)))return serveMemberPage(req,res,path.join(PUBLIC_DIR,'join.html'),'join',mj[1]);
}
let file;
if(pathname==='/')file=path.join(PUBLIC_DIR,'index.html');else if(pathname==='/app'||pathname==='/app/')file=path.join(PUBLIC_DIR,'app.html');else if(pathname==='/start'||pathname==='/start/')file=path.join(PUBLIC_DIR,'start.html');else if(pathname==='/training'||pathname==='/training/')file=path.join(PUBLIC_DIR,'training.html');else if(pathname==='/admin'||pathname==='/admin/')file=path.join(PUBLIC_DIR,'admin.html');else if(pathname==='/my'||pathname==='/my/'||/^\/my\/\d{1,15}$/.test(pathname))file=path.join(PUBLIC_DIR,'my.html');else if(pathname==='/contract'||pathname==='/contract/')file=path.join(PUBLIC_DIR,'contract.html');else if(pathname==='/disclaimer'||pathname==='/disclaimer/')file=path.join(PUBLIC_DIR,'disclaimer.html');else if(pathname==='/privacy'||pathname==='/privacy/')file=path.join(PUBLIC_DIR,'privacy.html');else if(pathname==='/refunds'||pathname==='/refunds/')file=path.join(PUBLIC_DIR,'refunds.html');else if(pathname==='/how-pay-works'||pathname==='/how-pay-works/')file=path.join(PUBLIC_DIR,'how-pay-works.html');else if(pathname==='/tools'||pathname==='/tools/')file=path.join(PUBLIC_DIR,'tools.html');else if(pathname==='/fast-start'||pathname==='/fast-start/')file=path.join(PUBLIC_DIR,'fast-start.html');else if(pathname==='/flyers'||pathname==='/flyers/')file=path.join(PUBLIC_DIR,'flyers.html');else if(pathname==='/weekly-rhythm'||pathname==='/weekly-rhythm/')file=path.join(PUBLIC_DIR,'weekly-rhythm.html');else if(pathname==='/generation-pay'||pathname==='/generation-pay/')file=path.join(PUBLIC_DIR,'generation-pay.html');else if(pathname==='/suite'||pathname==='/suite/')file=path.join(PUBLIC_DIR,'suite.html');else if(pathname==='/suite/copy'||pathname==='/suite/copy/')file=path.join(PUBLIC_DIR,'suite-copy.html');else if(pathname==='/suite/page'||pathname==='/suite/page/')file=path.join(PUBLIC_DIR,'suite-page.html');else if(pathname==='/suite/email'||pathname==='/suite/email/')file=path.join(PUBLIC_DIR,'suite-email.html');else if(pathname==='/suite/video'||pathname==='/suite/video/')file=path.join(PUBLIC_DIR,'suite-video.html');else if(pathname==='/suite/traffic'||pathname==='/suite/traffic/')file=path.join(PUBLIC_DIR,'suite-traffic.html');else if(pathname==='/suite/voice'||pathname==='/suite/voice/')file=path.join(PUBLIC_DIR,'suite-voice.html');else if(pathname==='/suite/split'||pathname==='/suite/split/')file=path.join(PUBLIC_DIR,'suite-split.html');else if(pathname==='/suite/funnel'||pathname==='/suite/funnel/')file=path.join(PUBLIC_DIR,'suite-funnel.html');else if(pathname==='/suite/leader'||pathname==='/suite/leader/')file=path.join(PUBLIC_DIR,'suite-leader.html');else if(pathname==='/suite/founder'||pathname==='/suite/founder/')file=path.join(PUBLIC_DIR,'suite-founder.html');else if(pathname==='/wallet-check'||pathname==='/wallet-check/')file=path.join(PUBLIC_DIR,'wallet-check.html');else if(pathname==='/suite/brand'||pathname==='/suite/brand/')file=path.join(PUBLIC_DIR,'suite-brand.html');else if(pathname==='/suite/grants'||pathname==='/suite/grants/')file=path.join(PUBLIC_DIR,'suite-grants.html');else if(pathname==='/suite/intel'||pathname==='/suite/intel/')file=path.join(PUBLIC_DIR,'suite-intel.html');else if(pathname==='/direct-join'||pathname==='/direct-join/'){if(!getSession(req)){res.writeHead(302,{Location:'/admin'});return res.end();}file=path.join(ROOT,'private','direct-join.html');}else if(pathname==='/join-now'||pathname==='/join-now/'){if(!getConfig().dappFallbackPublic){res.writeHead(302,{Location:'/start'});return res.end();}file=path.join(ROOT,'private','join-now.html');}else if(/^\/join\/\d{1,15}$/.test(pathname))file=path.join(PUBLIC_DIR,'join.html');else if(pathname==='/join'||pathname==='/join/'){res.writeHead(302,{Location:'/join-now'});return res.end();}else{
if(pathname==='/')file=path.join(PUBLIC_DIR,'index.html');else if(pathname==='/app'||pathname==='/app/')file=path.join(PUBLIC_DIR,'app.html');else if(pathname==='/start'||pathname==='/start/')file=path.join(PUBLIC_DIR,'start.html');else if(pathname==='/training'||pathname==='/training/')file=path.join(PUBLIC_DIR,'training.html');else if(pathname==='/admin'||pathname==='/admin/')file=path.join(PUBLIC_DIR,'admin.html');else if(pathname==='/my'||pathname==='/my/'||/^\/my\/\d{1,15}$/.test(pathname))file=path.join(PUBLIC_DIR,'my.html');else if(pathname==='/contract'||pathname==='/contract/')file=path.join(PUBLIC_DIR,'contract.html');else if(pathname==='/disclaimer'||pathname==='/disclaimer/')file=path.join(PUBLIC_DIR,'disclaimer.html');else if(pathname==='/privacy'||pathname==='/privacy/')file=path.join(PUBLIC_DIR,'privacy.html');else if(pathname==='/refunds'||pathname==='/refunds/')file=path.join(PUBLIC_DIR,'refunds.html');else if(pathname==='/how-pay-works'||pathname==='/how-pay-works/')file=path.join(PUBLIC_DIR,'how-pay-works.html');else if(pathname==='/tools'||pathname==='/tools/')file=path.join(PUBLIC_DIR,'tools.html');else if(pathname==='/fast-start'||pathname==='/fast-start/')file=path.join(PUBLIC_DIR,'fast-start.html');else if(pathname==='/flyers'||pathname==='/flyers/')file=path.join(PUBLIC_DIR,'flyers.html');else if(pathname==='/weekly-rhythm'||pathname==='/weekly-rhythm/')file=path.join(PUBLIC_DIR,'weekly-rhythm.html');else if(pathname==='/generation-pay'||pathname==='/generation-pay/')file=path.join(PUBLIC_DIR,'generation-pay.html');else if(pathname==='/replays'||pathname==='/replays/')file=path.join(PUBLIC_DIR,'replays.html');else if(pathname==='/suite'||pathname==='/suite/')file=path.join(PUBLIC_DIR,'suite.html');else if(pathname==='/suite/copy'||pathname==='/suite/copy/')file=path.join(PUBLIC_DIR,'suite-copy.html');else if(pathname==='/suite/page'||pathname==='/suite/page/')file=path.join(PUBLIC_DIR,'suite-page.html');else if(pathname==='/suite/email'||pathname==='/suite/email/')file=path.join(PUBLIC_DIR,'suite-email.html');else if(pathname==='/suite/video'||pathname==='/suite/video/')file=path.join(PUBLIC_DIR,'suite-video.html');else if(pathname==='/suite/traffic'||pathname==='/suite/traffic/')file=path.join(PUBLIC_DIR,'suite-traffic.html');else if(pathname==='/suite/voice'||pathname==='/suite/voice/')file=path.join(PUBLIC_DIR,'suite-voice.html');else if(pathname==='/suite/split'||pathname==='/suite/split/')file=path.join(PUBLIC_DIR,'suite-split.html');else if(pathname==='/suite/funnel'||pathname==='/suite/funnel/')file=path.join(PUBLIC_DIR,'suite-funnel.html');else if(pathname==='/suite/leader'||pathname==='/suite/leader/')file=path.join(PUBLIC_DIR,'suite-leader.html');else if(pathname==='/suite/founder'||pathname==='/suite/founder/')file=path.join(PUBLIC_DIR,'suite-founder.html');else if(pathname==='/wallet-check'||pathname==='/wallet-check/')file=path.join(PUBLIC_DIR,'wallet-check.html');else if(pathname==='/suite/brand'||pathname==='/suite/brand/')file=path.join(PUBLIC_DIR,'suite-brand.html');else if(pathname==='/suite/grants'||pathname==='/suite/grants/')file=path.join(PUBLIC_DIR,'suite-grants.html');else if(pathname==='/suite/intel'||pathname==='/suite/intel/')file=path.join(PUBLIC_DIR,'suite-intel.html');else if(pathname==='/direct-join'||pathname==='/direct-join/'){if(!getSession(req)){res.writeHead(302,{Location:'/admin'});return res.end();}file=path.join(ROOT,'private','direct-join.html');}else if(pathname==='/join-now'||pathname==='/join-now/'){if(!getConfig().dappFallbackPublic){res.writeHead(302,{Location:'/start'});return res.end();}file=path.join(ROOT,'private','join-now.html');}else if(/^\/join\/\d{1,15}$/.test(pathname))file=path.join(PUBLIC_DIR,'join.html');else if(pathname==='/join'||pathname==='/join/'){res.writeHead(302,{Location:'/join-now'});return res.end();}else{
const safe=path.normalize(pathname).replace(/^([.][.][/\\])+/, '').replace(/^[/\\]+/,'');file=path.join(PUBLIC_DIR,safe);if(!file.startsWith(PUBLIC_DIR))file='';
}
if(file&&staticFile(req,res,file))return;return staticFile(req,res,path.join(PUBLIC_DIR,'404.html'),404);