Files
netdesk/publishing/source-page.html
T

133 lines
8.7 KiB
HTML

<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>NetDesk — Source Code</title>
<meta name="description" content="Download or clone the full NetDesk source — self-hosted remote desktop. Server, Windows host, and native Rust client. Straight from netdesk.space, no GitHub needed.">
<link rel="icon" href="/favicon.ico">
<style>
:root{
--bg:#0b0e14; --bg2:#11151f; --card:#121724; --fg:#e8edf6; --muted:#9aa6bd; --faint:#6b7688;
--accent:#4d8bff; --accent2:#34d399; --hair:rgba(255,255,255,.08); --hair2:rgba(255,255,255,.14);
--grad:linear-gradient(135deg,#4d8bff,#6aa1ff 44%,#34d399);
--shadow:0 24px 70px -18px rgba(0,0,0,.7);
font-synthesis-weight:none;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);
font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
background:
radial-gradient(900px 500px at 12% -8%, rgba(77,139,255,.16), transparent 60%),
radial-gradient(800px 520px at 100% 0%, rgba(52,211,153,.10), transparent 55%)}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
.wrap{max-width:900px;margin:0 auto;padding:0 20px}
nav{display:flex;align-items:center;justify-content:space-between;padding:20px 0;border-bottom:1px solid var(--hair)}
.brand{display:flex;align-items:center;gap:10px;font-weight:750;font-size:18px;letter-spacing:-.3px}
.logo{width:30px;height:30px;border-radius:9px;background:var(--grad);display:inline-flex;align-items:center;justify-content:center}
.logo svg{width:18px;height:18px}
.nav-links a{color:var(--muted);margin-left:20px;font-size:14.5px;font-weight:500}
.nav-links a:hover{color:var(--fg);text-decoration:none}
header.hero{padding:64px 0 34px;text-align:center}
.eyebrow{display:inline-block;font-size:12px;font-weight:700;letter-spacing:1.3px;text-transform:uppercase;
color:#9cc0ff;background:rgba(77,139,255,.12);border:1px solid rgba(77,139,255,.25);padding:5px 13px;border-radius:999px}
h1{font-size:clamp(34px,6vw,52px);line-height:1.08;letter-spacing:-1.4px;margin:18px 0 10px;font-weight:800}
h1 .g{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
.sub{color:var(--muted);font-size:clamp(16px,2.3vw,19px);max-width:620px;margin:0 auto}
.cta{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:30px}
.btn{display:inline-flex;align-items:center;gap:9px;padding:14px 26px;border-radius:12px;font-weight:650;font-size:15px;
border:1px solid var(--hair2);color:var(--fg);background:var(--card);transition:.15s;position:relative;overflow:hidden}
.btn:hover{transform:translateY(-2px);text-decoration:none;border-color:rgba(77,139,255,.5)}
.btn.primary{background:var(--grad);border-color:transparent;color:#071018;box-shadow:0 10px 26px -8px rgba(61,126,255,.55)}
.btn.primary:hover{filter:brightness(1.05)}
.btn .sz{color:var(--faint);font-weight:500;font-size:13px}
.btn.primary .sz{color:rgba(7,16,24,.65)}
section{padding:30px 0;border-top:1px solid var(--hair)}
h2{font-size:24px;letter-spacing:-.5px;margin:0 0 6px;font-weight:750}
.lead{color:var(--muted);margin:0 0 18px}
.code{background:#0a0e16;border:1px solid var(--hair);border-radius:12px;padding:16px 46px 16px 18px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
font-size:14px;line-height:1.7;color:#c7d2e6;overflow-x:auto;position:relative;white-space:pre-wrap;word-break:break-word}
.code .c{color:#5f6b80}
.code .p{color:var(--accent2)}
.copy{position:absolute;top:10px;right:10px;background:var(--card);border:1px solid var(--hair2);color:var(--muted);
border-radius:8px;padding:5px 11px;font-size:12px;cursor:pointer;font-family:Inter,sans-serif}
.copy:hover{color:var(--fg);border-color:var(--accent)}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-top:6px}
.c-card{background:var(--card);border:1px solid var(--hair);border-radius:14px;padding:18px}
.c-card b{display:block;font-size:15px;margin-bottom:4px}
.c-card span{color:var(--muted);font-size:13.5px}
.c-card .mono{font-family:ui-monospace,monospace;color:#9cc0ff;font-size:12.5px}
footer{padding:36px 0 50px;color:var(--faint);font-size:13.5px;text-align:center;border-top:1px solid var(--hair);margin-top:24px}
.note{font-size:13.5px;color:var(--faint);margin-top:14px}
@media (max-width:560px){.btn{width:100%;justify-content:center}}
</style>
</head>
<body>
<div class="wrap">
<nav>
<a class="brand" href="/"><span class="logo"><svg viewBox="0 0 32 32" fill="none"><path d="M8 20l8-12 8 12-8-4z" fill="#071018"/><rect x="12" y="18" width="8" height="7" rx="2" fill="#071018"/></svg></span>NetDesk</a>
<div class="nav-links"><a href="/">Home</a><a href="/app">Web app</a><a href="/download">Download app</a></div>
</nav>
<header class="hero">
<span class="eyebrow">Open source · self-hosted</span>
<h1>The complete <span class="g">NetDesk source</span></h1>
<p class="sub">Every line — the relay server, the Windows host, the zero-install web viewer, and the native Rust client. Clone it or download it straight from here. No GitHub account required.</p>
<div class="cta">
<a class="btn primary" href="/downloads/netdesk-src-latest.tar.gz" download>⬇ Download .tar.gz <span class="sz" id="szTgz"></span></a>
<a class="btn" href="/downloads/netdesk-src-latest.zip" download>⬇ Download .zip <span class="sz" id="szZip"></span></a>
</div>
<p class="note">Version 1.5.0 · AES-256 end-to-end · Windows + Web today, macOS/Linux/Android via the native client build</p>
</header>
<section>
<h2>Clone with git</h2>
<p class="lead">Served straight from netdesk.space over HTTPS:</p>
<div class="code" id="cloneBox"><button class="copy" onclick="cp('cloneCmd')">Copy</button><span id="cloneCmd"><span class="c"># get the full source</span>
git clone https://netdesk.space/git/netdesk.git
cd netdesk</span></div>
</section>
<section>
<h2>What's inside</h2>
<p class="lead">A single repository with every component of the system.</p>
<div class="grid">
<div class="c-card"><b>server/</b><span>Python aiohttp signaling + relay + REST API, SSO (SAML/OIDC/LDAP), SCIM, admin console, and the <span class="mono">web/</span> browser viewer.</span></div>
<div class="c-card"><b>host/</b><span>Windows host/agent (runs as a SYSTEM service — reachable at the logon screen &amp; across UAC) + a pywebview desktop app.</span></div>
<div class="c-card"><b>native/</b><span>From-scratch native client: a Rust core (capture, encode, crypto, P2P) with a Flutter UI. Workspace crates: core, viewer, host, cli, opus, vpx, frb.</span></div>
<div class="c-card"><b>docker/</b><span>Dockerfile + compose to run your own relay server with one command.</span></div>
</div>
</section>
<section>
<h2>Self-host in 60 seconds</h2>
<p class="lead">Run your own relay server (your VPS, your rules — the shop never sees your screen):</p>
<div class="code"><button class="copy" onclick="cp('runCmd')">Copy</button><span id="runCmd"><span class="c"># 1. get it</span>
git clone https://netdesk.space/git/netdesk.git && cd netdesk
<span class="c"># 2. install deps + run the server</span>
pip install -r requirements.txt
python server/netdesk_server.py --port 8443 --portal-password <span class="p">YOUR_PASSWORD</span>
<span class="c"># 3. put it behind TLS (nginx/Caddy) and point your host + browser at it</span></span></div>
<p class="note">Full deployment guide in <span style="color:var(--accent2)">docker/README.md</span> and <span style="color:var(--accent2)">README.md</span>. Source-available license — free to self-host &amp; modify. See <span style="color:var(--accent2)">LICENSE</span>.</p>
</section>
<footer>
NetDesk · self-hosted remote desktop · <a href="/">netdesk.space</a><br>
© 2026 Akronlogic. Source-available — free to self-host.
</footer>
</div>
<script>
function cp(id){var t=document.getElementById(id).innerText;navigator.clipboard&&navigator.clipboard.writeText(t);
var b=event.target;var o=b.textContent;b.textContent="Copied";setTimeout(function(){b.textContent=o},1200);}
// fill archive sizes if a sizes.json is present
fetch('/downloads/sizes.json',{cache:'no-store'}).then(function(r){return r.ok?r.json():null}).then(function(d){
if(!d)return; if(d.tgz){document.getElementById('szTgz').textContent='('+d.tgz+')';}
if(d.zip){document.getElementById('szZip').textContent='('+d.zip+')';}
}).catch(function(){});
</script>
</body>
</html>