Files
Keysat 6ce2a9a39e Initial commit — registry landing for registry.keysat.xyz
Static page shown at https://registry.keysat.xyz/ — the public face of
the Keysat StartOS package registry. Renders the marketplace card
with title, description, and an Add-to-Marketplace CTA.

- index.html       — the page itself (13.6 KB)
- assets/keysat-mark.svg, favicon.svg
- .gitignore       — macOS / editor / IDE noise
2026-05-11 10:08:13 -05:00

327 lines
14 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Keysat Registry — software licensing packages for Start9</title>
<meta name="description" content="The Keysat package registry for StartOS. Add registry.keysat.xyz to your Start9 dashboard to install Keysat directly.">
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;900&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root {
--navy-950:#0E1F33; --navy-900:#142A47; --navy-800:#1E3A5F; --navy-700:#2A4A75;
--cream-50:#FBF9F2; --cream-100:#F5F1E8; --cream-200:#EDE7D7;
--gold-700:#8A6F3D; --gold-500:#BFA068; --gold-400:#D4B985;
--ink-900:#0E1F33; --ink-700:#2C3E54; --ink-500:#5A6B7F;
--success:#2D7A5F; --success-bg:#E3F0EA;
--border-1:rgba(14,31,51,0.12); --border-2:rgba(14,31,51,0.20);
--font-display:'Manrope','Helvetica Neue',Arial,sans-serif;
--font-body:'Inter','Helvetica Neue',Arial,sans-serif;
--font-mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;
--shadow-md:0 2px 4px rgba(14,31,51,0.06),0 4px 12px rgba(14,31,51,0.06);
}
*{box-sizing:border-box} html,body{margin:0;padding:0}
body{
font-family:var(--font-body); color:var(--ink-900);
background:var(--cream-100);
background-image:
radial-gradient(rgba(14,31,51,0.025) 1px, transparent 1px),
radial-gradient(rgba(138,111,61,0.022) 1px, transparent 1px);
background-size:3px 3px, 7px 7px;
-webkit-font-smoothing:antialiased; min-height:100vh;
}
.wrap{max-width:880px; margin:0 auto; padding:0 32px;}
header.topnav{
position:sticky; top:0; z-index:10;
background:rgba(245,241,232,0.85); backdrop-filter:blur(12px);
border-bottom:1px solid var(--border-1);
padding:14px 0;
}
header.topnav .inner{
display:flex; align-items:center; gap:18px;
}
header.topnav .brand{
display:flex; align-items:center; gap:10px;
font-family:var(--font-display); font-weight:500;
font-size:14px; letter-spacing:0.30em; text-transform:uppercase;
color:var(--navy-900); text-decoration:none;
}
header.topnav .brand img{width:28px; height:28px}
header.topnav .reg-tag{
font-size:11px; font-weight:700; letter-spacing:0.18em;
text-transform:uppercase; color:var(--gold-700);
padding-left:10px; border-left:1px solid var(--border-2);
}
header.topnav nav{margin-left:auto; display:flex; gap:24px; font-size:13.5px}
header.topnav nav a{color:var(--ink-700); text-decoration:none}
header.topnav nav a:hover{color:var(--navy-900)}
section.hero{padding:72px 0 48px;}
.eyebrow{
font-size:11.5px; font-weight:700; letter-spacing:0.18em;
text-transform:uppercase; color:var(--gold-700); margin-bottom:18px;
display:inline-flex; align-items:center; gap:10px;
}
.eyebrow::before{content:''; display:inline-block; width:28px; height:1px; background:var(--gold-500);}
h1{
font-family:var(--font-display); font-weight:500;
font-size:clamp(36px, 4.6vw, 56px); line-height:1.05;
letter-spacing:-0.022em; color:var(--navy-950);
margin:0 0 18px; max-width:760px;
}
.lead{
font-size:18px; line-height:1.55; color:var(--ink-700);
margin:0 0 0; max-width:620px;
}
.url-banner{
margin-top:36px; background:var(--navy-950); color:var(--cream-50);
border-radius:12px; padding:18px 22px;
display:flex; align-items:center; justify-content:space-between; gap:14px;
font-family:var(--font-mono); font-size:15px;
box-shadow:var(--shadow-md);
flex-wrap:wrap;
}
.url-banner .label{
font-family:var(--font-body); font-size:11px; font-weight:700;
letter-spacing:0.18em; text-transform:uppercase;
color:var(--gold-400); margin-right:8px;
}
.url-banner button{
background:rgba(245,241,232,0.10); color:var(--cream-50);
border:0; padding:8px 14px; border-radius:7px;
font-family:var(--font-body); font-weight:600; font-size:13px;
cursor:pointer; transition:background 120ms;
margin-left:auto;
}
.url-banner button:hover{background:rgba(245,241,232,0.20);}
section.block{padding:48px 0;}
section.tinted{background:var(--cream-200); position:relative;}
section.tinted::before, section.tinted::after{
content:''; position:absolute; left:0; right:0; height:1px;
background:var(--gold-500); opacity:0.4;
}
section.tinted::before{top:0;} section.tinted::after{bottom:0;}
h2{
font-family:var(--font-display); font-weight:500;
font-size:28px; line-height:1.1; letter-spacing:-0.02em;
color:var(--navy-950); margin:0 0 14px;
}
.section-sub{
font-size:16px; line-height:1.55; color:var(--ink-700);
margin:0 0 28px; max-width:640px;
}
ol.steps{
list-style:none; padding:0; margin:0;
counter-reset:step;
display:grid; gap:14px;
}
ol.steps li{
background:var(--cream-50); border:1px solid var(--border-1);
border-radius:10px; padding:18px 22px 18px 64px;
position:relative;
font-size:15px; line-height:1.55; color:var(--ink-700);
}
ol.steps li::before{
counter-increment:step; content:counter(step);
position:absolute; left:18px; top:14px;
font-family:var(--font-display); font-weight:900; font-size:28px;
color:var(--gold-500); line-height:1; letter-spacing:-0.04em;
}
ol.steps li strong{color:var(--navy-950); font-weight:700}
ol.steps li code{
font-family:var(--font-mono); font-size:13px;
background:var(--cream-200); padding:1px 6px; border-radius:4px;
color:var(--navy-900);
}
.pkg-grid{display:grid; gap:14px;}
.pkg-card{
background:var(--cream-50); border:1px solid var(--border-1);
border-radius:12px; padding:24px;
display:grid; grid-template-columns:auto 1fr auto; gap:20px; align-items:center;
}
.pkg-card.featured{box-shadow:0 0 0 1px var(--gold-500) inset;}
.pkg-card .pkg-icon{
width:56px; height:56px; flex-shrink:0;
background:var(--cream-100); border:1px solid var(--border-1);
border-radius:10px;
display:flex; align-items:center; justify-content:center;
}
.pkg-card .pkg-icon img{width:36px; height:36px}
.pkg-card .meta-block .name{
font-family:var(--font-display); font-weight:700; font-size:18px;
color:var(--navy-950); margin:0 0 4px; letter-spacing:-0.01em;
}
.pkg-card .meta-block .tagline{
font-size:13.5px; color:var(--ink-500); margin:0 0 8px;
}
.pkg-card .meta-block .badges{display:flex; gap:6px; flex-wrap:wrap;}
.badge{
display:inline-flex; align-items:center; gap:4px;
font-size:11px; font-weight:600;
padding:2px 8px; border-radius:999px; line-height:1.5;
border:1px solid transparent;
}
.b-ok{background:var(--success-bg); color:#205c47; border-color:rgba(45,122,95,0.25);}
.b-info{background:#E4EAF1; color:var(--navy-800); border-color:rgba(30,58,95,0.20);}
.b-gold{background:transparent; color:var(--gold-700); border-color:var(--gold-500);}
.b-mono{font-family:var(--font-mono); font-size:10.5px;}
.pkg-card .pkg-meta{
text-align:right; font-size:13px; color:var(--ink-500); line-height:1.4;
}
.pkg-card .pkg-meta .ver{
font-family:var(--font-mono); color:var(--navy-900); font-weight:600;
font-size:13px;
}
section.api{
padding:32px 0;
font-size:13px; color:var(--ink-500);
}
section.api .grid{
background:var(--cream-50); border:1px solid var(--border-1);
border-radius:10px; padding:18px 22px;
font-family:var(--font-mono); font-size:12.5px;
display:grid; gap:6px;
}
section.api .grid div{display:flex; gap:10px; align-items:baseline;}
section.api .grid .method{
color:var(--gold-700); font-weight:700; min-width:46px;
}
section.api .grid .path{color:var(--navy-900);}
footer{
border-top:1px solid var(--border-1); margin-top:48px;
padding:32px; text-align:center;
font-size:12.5px; color:var(--ink-500);
background:var(--cream-50);
}
footer a{color:var(--ink-500); text-decoration:none}
footer a:hover{color:var(--navy-900)}
@media (max-width: 720px) {
.pkg-card{grid-template-columns:1fr; text-align:left;}
.pkg-card .pkg-meta{text-align:left;}
}
</style>
</head>
<body>
<header class="topnav">
<div class="wrap inner">
<a href="/" class="brand"><img src="assets/keysat-mark.svg" alt=""><span>Keysat</span></a>
<span class="reg-tag">Registry</span>
<nav>
<a href="https://keysat.xyz">Marketing</a>
<a href="https://docs.keysat.xyz">Docs</a>
<a href="https://github.com/keysat-xyz">GitHub</a>
</nav>
</div>
</header>
<section class="hero">
<div class="wrap">
<div class="eyebrow">Start9 package registry</div>
<h1>The Keysat registry for StartOS.</h1>
<p class="lead">This is an API endpoint, not a website you browse. Add the URL below to your StartOS dashboard&rsquo;s marketplace list and the Keysat package will appear in your install catalog. Browser visits get this page; Start9 dashboards get the package index.</p>
<div class="url-banner">
<span class="label">Registry URL</span>
<span id="reg-url">https://registry.keysat.xyz</span>
<button id="copy-btn" data-copy="https://registry.keysat.xyz">Copy</button>
</div>
</div>
</section>
<section class="block tinted">
<div class="wrap">
<h2>Add this registry to your Start9</h2>
<p class="section-sub">In your StartOS dashboard, paste the registry URL once and you&rsquo;ll see Keysat alongside any other marketplace packages you have installed.</p>
<ol class="steps">
<li>Open your <strong>StartOS dashboard</strong> in a browser.</li>
<li>Go to <strong>Marketplace</strong> in the left sidebar.</li>
<li>Click <strong>Switch</strong> at the top of the marketplace pane, then click <strong>Add</strong>.</li>
<li>Paste <code>https://registry.keysat.xyz</code> as the URL. Name it whatever you want &mdash; "Keysat" works.</li>
<li>Switch to the new registry. You&rsquo;ll see the <strong>Keysat</strong> package listed; click <strong>Install</strong>.</li>
</ol>
</div>
</section>
<section class="block">
<div class="wrap">
<h2>Packages in this registry</h2>
<p class="section-sub">All packages here are published, signed, and maintained by the keysat.xyz team. Source-available on GitHub; binaries built reproducibly from tagged releases.</p>
<div class="pkg-grid">
<div class="pkg-card featured">
<div class="pkg-icon"><img src="assets/keysat-mark.svg" alt=""></div>
<div class="meta-block">
<h3 class="name">Keysat</h3>
<p class="tagline">Bitcoin-native self-hosted software licensing for software creators. Pays via BTCPay or Zaprite, verifies offline.</p>
<div class="badges">
<span class="badge b-ok">Stable</span>
<span class="badge b-info">Requires BTCPay</span>
<span class="badge b-gold">Source-available</span>
</div>
</div>
<div class="pkg-meta">
<div class="ver">v0.1.0:11</div>
<div>x86_64</div>
</div>
</div>
</div>
<p style="margin-top:18px; font-size:13.5px; color:var(--ink-500);">
More packages may appear here over time &mdash; sample buyer-side reference packages, language-specific SDK demos, etc. The Keysat package is the centerpiece.
</p>
</div>
</section>
<section class="block tinted">
<div class="wrap">
<h2>Not on a Start9?</h2>
<p class="section-sub">If you&rsquo;re reading this in a browser without a Start9 server, here are the right next steps:</p>
<ol class="steps">
<li><strong>Just want to know what Keysat is?</strong> Visit <a href="https://keysat.xyz">keysat.xyz</a> for the marketing overview, or <a href="https://docs.keysat.xyz">docs.keysat.xyz</a> for the full integration guide.</li>
<li><strong>Don&rsquo;t have a Start9 server yet?</strong> See <a href="https://start9.com">start9.com</a> for hardware (Server One, Server Pro) or DIY install instructions for running StartOS on your own hardware.</li>
<li><strong>Want to download the .s9pk directly?</strong> Releases are mirrored at <a href="https://github.com/keysat-xyz/keysat/releases">github.com/keysat-xyz/keysat/releases</a>. Sideload via your StartOS dashboard&rsquo;s Sideload screen.</li>
</ol>
</div>
</section>
<section class="api">
<div class="wrap">
<h2 style="font-size:18px; margin-bottom:8px;">For the curious — what your Start9 talks to</h2>
<p class="section-sub" style="font-size:13.5px; margin-bottom:14px;">The Start9 dashboard speaks a small JSON protocol against this registry. The endpoints below are what gets hit; you don&rsquo;t need to think about them, but they&rsquo;re here for transparency.</p>
<div class="grid">
<div><span class="method">GET</span> <span class="path">/package/v0/index</span> <span style="margin-left:auto; color:var(--ink-500);">catalog of available packages</span></div>
<div><span class="method">GET</span> <span class="path">/package/v0/&lt;id&gt;/&lt;ver&gt;/manifest.s9pk</span> <span style="margin-left:auto; color:var(--ink-500);">signed package binary</span></div>
<div><span class="method">GET</span> <span class="path">/package/v0/&lt;id&gt;/&lt;ver&gt;/icon</span> <span style="margin-left:auto; color:var(--ink-500);">marketplace listing icon</span></div>
<div><span class="method">GET</span> <span class="path">/package/v0/&lt;id&gt;/&lt;ver&gt;/instructions</span> <span style="margin-left:auto; color:var(--ink-500);">install/setup notes</span></div>
</div>
</div>
</section>
<footer>
Keysat Registry &middot; <a href="https://keysat.xyz">keysat.xyz</a> &middot; <a href="https://docs.keysat.xyz">docs</a> &middot; <a href="https://github.com/keysat-xyz">GitHub</a>
</footer>
<script>
document.querySelectorAll('button[data-copy]').forEach(btn => {
btn.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(btn.dataset.copy);
const original = btn.textContent;
btn.textContent = 'Copied';
setTimeout(() => { btn.textContent = original; }, 1400);
} catch (e) {}
});
});
</script>
</body>
</html>