2026-09-20 18:33:01 +02:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > Register a TLD — Sirius.X< / title >
< meta name = "description" content = "Mint a top-level domain on Bitcoin Cash. Any wallet can register a TLD; second-level names can then be sold under it." >
< link rel = "icon" href = "./assets/favicon.svg" type = "image/svg+xml" >
< link rel = "mask-icon" href = "./assets/favicon.svg" color = "#d6ff3d" >
< meta property = "og:type" content = "website" >
< meta property = "og:site_name" content = "Sirius.X" >
< meta property = "og:title" content = "Register a TLD on Bitcoin Cash" >
< meta property = "og:description" content = "Mint a TLD certificate. One BCH transaction, no registrar. Renewals are per-TLD policy." >
< meta property = "og:url" content = "https://silentmode.st/sirius-x/tld.html" >
< meta property = "og:image" content = "https://silentmode.st/sirius-x/brand/banner.svg" >
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link href = "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,400;9..144,500;9..144,600;9..144,700&family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Ubuntu:wght@400;500;700&display=swap" rel = "stylesheet" >
< style >
:root{
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.06);
--sky-mid:#0a0f1c; --sky-rim:#131a2a;
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
--chain-native:#0AC18E;
--ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
--serif:'Fraunces',Georgia,serif;
--sans:'DM Sans','Inter',system-ui,sans-serif;
--mono:'JetBrains Mono',ui-monospace,monospace;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;
background:radial-gradient(ellipse 1200px 600px at 50% -5%,var(--sky-rim) 0%,transparent 60%),
radial-gradient(ellipse 900px 500px at 100% 100%,var(--sky-mid) 0%,transparent 55%),
radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),
var(--bg);
background-attachment:fixed;
color:var(--ink);font:16px/1.6 var(--sans);min-height:100vh;font-feature-settings:"ss01","ss02"}
h1,h2,h3{font-family:var(--serif);font-feature-settings:"ss01","ss02"}
code,.mono{font-family:var(--mono)}
html[data-font-cmp="ubuntu"] body,
html[data-font-cmp="ubuntu"] h1, html[data-font-cmp="ubuntu"] h2, html[data-font-cmp="ubuntu"] h3,
html[data-font-cmp="ubuntu"] p, html[data-font-cmp="ubuntu"] a, html[data-font-cmp="ubuntu"] button,
html[data-font-cmp="ubuntu"] span, html[data-font-cmp="ubuntu"] div,
html[data-font-cmp="ubuntu"] label, html[data-font-cmp="ubuntu"] input, html[data-font-cmp="ubuntu"] li{
font-family:'Ubuntu',system-ui,sans-serif !important
}
html[data-font-cmp="ubuntu"] code, html[data-font-cmp="ubuntu"] .mono{font-family:var(--mono) !important}
.font-picker{display:inline-flex;align-items:center;gap:2px;padding:2px;margin:0 10px;
background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:999px;
font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase}
.font-picker button{background:transparent;border:none;color:var(--dim);
padding:4px 10px;border-radius:999px;cursor:pointer;font-family:inherit;font-size:inherit;
letter-spacing:inherit;text-transform:inherit;transition:color .12s}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
a{color:var(--acid)}
.wrap{max-width:820px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
/* Adaptive side nav — same shape as index.html and Theseus.X */
:root{--sn-w:200px}
.sidenav{position:fixed;top:56px;left:0;bottom:0;width:var(--sn-w);z-index:15;
background:transparent;padding:32px 12px 22px 18px;
overflow-y:auto;pointer-events:none;transition:width .15s ease}
.sidenav a{display:flex;align-items:center;gap:14px;color:var(--mut);text-decoration:none;
padding:9px 12px;border-radius:10px;
font-size:14.5px;font-weight:500;opacity:.35;pointer-events:auto;
transition:opacity .12s,color .12s,background .12s,backdrop-filter .12s}
.sidenav a .ic{flex:none;width:22px;font-size:18px;line-height:1;text-align:center;
display:none;justify-content:center;align-items:center}
.sidenav a .lb{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidenav a:hover{opacity:1;color:var(--ink);background:rgba(11,14,20,.72);backdrop-filter:blur(8px)}
.sidenav a.active{opacity:.85;color:var(--acid)}
.sidenav a.active:hover{opacity:1}
section{scroll-margin-top:70px}
@media (max-width:1180px){
:root{--sn-w:64px}
.sidenav{padding:22px 6px}
.sidenav a{justify-content:center;padding:12px 4px;gap:0}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
@media (max-width:720px){
:root{--sn-w:0}
body{padding-bottom:64px}
.sidenav{top:auto;bottom:0;left:0;right:0;width:100%;height:auto;
padding:4px;flex-direction:row;background:rgba(11,14,20,.52);
display:flex;justify-content:space-around;overflow-x:auto}
.sidenav a{flex:1;min-width:56px;padding:10px 6px;justify-content:center;gap:0;opacity:.5}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
header.hero{text-align:center;padding:3.4rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.7rem,4.5vw,2.3rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1rem;max-width:600px;margin:0 auto}
h2{font-size:1.25rem;margin:0 0 .4rem}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1rem}
.btn{display:inline-block;text-decoration:none;padding:10px 18px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn:hover{filter:brightness(1.12)}
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
.muted{color:var(--mut);font-size:13px}
.dim{color:var(--dim);font-size:12.5px}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px;word-break:break-all}
.badge{display:inline-block;font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600}
.b-ok{background:rgba(79,209,165,.15);color:var(--ok)}
.b-taken{background:rgba(246,118,138,.15);color:var(--taken)}
.b-check{background:rgba(139,152,169,.14);color:var(--mut)}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:12px}
.status.ok{border-left:3px solid var(--ok)}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.status.warn{border-left:3px solid var(--warn);color:var(--warn)}
/* TLD search cell */
.search{max-width:600px;margin:1.5rem auto 0}
.searchrow{display:flex;gap:8px}
.searchrow input{flex:1;padding:14px 18px;font-size:17px;border-radius:12px;border:1px solid #ffffff22;background:#141a24;color:var(--ink);font-family:inherit;outline:none}
.searchrow input:focus{border-color:#4b7bec}
.searchhint{font-size:12.5px;color:var(--mut);margin-top:8px;text-align:center}
.result-card{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 18px;margin-top:12px}
.result-card .lbl{font-family:ui-monospace,monospace;font-size:18px;color:var(--ink)}
.result-card .lbl .dot{color:var(--acid)}
/* Registered-TLDs table */
table.tlds{width:100%;border-collapse:collapse;margin-top:1rem;font-size:13px}
table.tlds th,table.tlds td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
table.tlds th{color:var(--mut);font-weight:500;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px}
table.tlds .tld{font-family:ui-monospace,monospace;color:var(--acid);font-size:13.5px;font-weight:600}
table.tlds .cat{font-family:ui-monospace,monospace;color:var(--mut);font-size:11.5px;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.price, table.tlds .price{
color:var(--acid);font-family:ui-monospace,monospace;font-size:13px;font-weight:600;
padding:2px 8px;border-radius:6px;background:rgba(214,255,61,.10);white-space:nowrap;display:inline-block
}
.result-card{grid-template-columns:1fr auto auto auto !important}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
< / style >
< script type = "importmap" >
2026-09-20 19:20:30 +02:00
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js?v=20260920usd" } }
2026-09-20 18:33:01 +02:00
< / script >
2026-09-20 19:20:30 +02:00
< script src = "./js/i18n.js?v=20260920g" > < / script >
2026-09-20 18:33:01 +02:00
< / head >
< body >
< nav class = "topnav" >
< a class = "brand" href = "./" > < svg width = "18" height = "18" viewBox = "0 0 64 64" style = "vertical-align:-4px;margin-right:6px" aria-hidden = "true" > < rect width = "64" height = "64" rx = "12" fill = "#0b0e14" / > < path d = "M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z" fill = "#d6ff3d" / > < / svg > < span class = "g" > Sirius.X< / span > < / a >
< a href = "./tld.html" class = "here" > 🌐 TLD< / a >
< a href = "./market" > 🛒 Market< / a >
< a href = "./theseus" > < svg width = "14" height = "14" viewBox = "0 0 64 64" style = "vertical-align:-2px;margin-right:4px" aria-hidden = "true" > < rect width = "64" height = "64" rx = "12" fill = "#0b0e14" / > < path d = "M32 6 L38 32 L26 32 Z" fill = "#e04e4e" / > < path d = "M38 32 L32 58 L26 32 Z" fill = "#d6ff3d" / > < path d = "M6 32 L32 27 L58 32 L32 37 Z" fill = "#d6ff3d" opacity = ".55" / > < circle cx = "32" cy = "32" r = "3" fill = "#0b0e14" / > < / svg > Theseus< span class = "g" > .X< / span > < / a >
< a href = "./portal.html" class = "portal" > 🔑 Sign in< / a >
< / nav >
< aside class = "sidenav" aria-label = "On this page" >
< a href = "#search-section" title = "Search a TLD" > < span class = "ic" aria-hidden = "true" > 🔎< / span > < span class = "lb" > Search< / span > < / a >
< a href = "#listing" title = "Registered TLDs" > < span class = "ic" aria-hidden = "true" > 📋< / span > < span class = "lb" > Registered< / span > < / a >
< / aside >
< header class = "hero" >
< div class = "mark" > 🌐< / div >
< h1 > Register a < span class = "g" > TLD< / span > < / h1 >
< p class = "tag" > A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any
second-level name registered under it lives in your TLD's registry. One BCH transaction,
no ICANN. Renewals? Your TLD, your policy.< / p >
< / header >
< div class = "wrap" >
< section id = "search-section" >
< h2 > Search a TLD< / h2 >
< p class = "muted" > Type a label (a– z, 0– 9, hyphen; up to 16 chars). Available TLDs get a Register
button that opens the shared wallet-choice modal — the same flow name registration uses.
As TLD owner you earn < b style = "color:var(--ok)" > 90 %< / b > of every name registered under
your TLD. Renewals are your call — set them per TLD, or don't.< / p >
< div class = "search" >
< div class = "searchrow" >
< input id = "q" placeholder = "your-tld" spellcheck = "false" autocomplete = "off" autofocus maxlength = "16" >
< / div >
< div class = "searchhint" > Register minting to your token address; you become the registry operator.< / div >
< / div >
< div id = "result" > < / div >
< / section >
< section id = "listing" >
< h2 > Registered TLDs< / h2 >
< p class = "muted" > Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.< / p >
< div id = "tlds-status" class = "status" > Loading…< / div >
< table class = "tlds" id = "tlds-table" style = "display:none" >
< thead > < tr > < th > TLD< / th > < th > Mint price< / th > < th > Category< / th > < / tr > < / thead >
< tbody > < / tbody >
< / table >
< / section >
< / div >
< footer id = "site-footer" > < / footer >
< script >
// Simple oracle stub: static chipnet rate for testing. Same number the
// portal uses. Mainnet swaps for a real price feed.
const CHIPNET_SATS_PER_USD = 400_000; // first-paint fallback only; pricing.js serves the live rate
const DEFAULT_USD = 5;
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[& < >"']/g, (c) => ({"&":"& ","< ":"< ",">":"> ",'"':"" ","'":"' "}[c]));
const validLabel = (s) => /^[a-z0-9-]{1,16}$/.test(s);
const normLabel = (s) => String(s).toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 16);
// ---------- registered-TLD list ----------
let registeredTlds = null;
async function loadTldList() {
const status = $("tlds-status"), tbody = $("tlds-table").querySelector("tbody");
try {
const r = await fetch("https://navigate.st/api/tlds");
if (!r.ok) throw new Error("api " + r.status);
const j = await r.json();
const tlds = (j.tlds || []).map((t) => (typeof t === "string" ? { tld: t } : t));
tlds.sort((a, b) => a.tld.localeCompare(b.tld));
tbody.innerHTML = tlds.map((t) => {
const p = window.siriusPricing?.priceForTld(t.tld);
const priceCell = p ? `< span class = "price" title = "${esc(p.tier)}" > ${esc(window.siriusPricing.formatUsd(p.usd))}< / span > ` : "—";
return `< tr >
< td class = "tld" > .${esc(t.tld)}< / td >
< td class = "price-cell" > ${priceCell}< / td >
< td class = "cat" > ${esc(t.certificate || t.category || "")}< / td >
< / tr > `;
}).join("");
$("tlds-table").style.display = "";
status.className = "status ok";
status.textContent = `${tlds.length} TLDs registered on chipnet.`;
registeredTlds = tlds.map((t) => t.tld);
refreshSearch();
} catch (e) {
status.className = "status err";
status.textContent = "Could not load TLD list: " + (e.message || e);
}
}
loadTldList();
// ---------- search result renderer ----------
function renderResult(label, state) {
const res = $("result");
if (!label) { res.innerHTML = ""; return; }
if (state === "checking") {
res.innerHTML = `< div class = "result-card" >
< div class = "lbl" > < span class = "dot" > .< / span > ${esc(label)}< / div >
< span class = "badge b-check" > checking…< / span > < span > < / span > < / div > `;
return;
}
if (state === "taken") {
res.innerHTML = `< div class = "result-card" >
< div class = "lbl" > < span class = "dot" > .< / span > ${esc(label)}< / div >
< span class = "badge b-taken" > taken< / span > < span > < / span > < / div >
< p class = "dim" style = "margin-top:8px" > Someone already minted < code > .${esc(label)}< / code > . Try a
different label — TLDs are first-come, first-served.< / p > `;
return;
}
const p = window.siriusPricing?.priceForTld(label);
const priceBadge = p
? `< span class = "price" title = "${esc(p.tier)}" > ${esc(window.siriusPricing.formatUsd(p.usd))}< / span > `
: "";
res.innerHTML = `< div class = "result-card" >
< div class = "lbl" > < span class = "dot" > .< / span > ${esc(label)}< / div >
< span class = "badge b-ok" > available< / span >
${priceBadge}
< button class = "btn acid" id = "go-register" > Register .${esc(label)} →< / button >
< / div > `;
$("go-register").onclick = () => beginRegister(label);
}
// ---------- search wiring ----------
let currentLabel = "";
function refreshSearch() {
const raw = normLabel($("q").value);
currentLabel = raw;
if (!raw) { renderResult("", null); return; }
if (!validLabel(raw)) { renderResult(raw, "invalid"); return; }
if (registeredTlds !== null) {
renderResult(raw, registeredTlds.includes(raw) ? "taken" : "ok");
return;
}
renderResult(raw, "checking");
}
$("q").addEventListener("input", () => {
$("q").value = normLabel($("q").value);
refreshSearch();
});
$("q").addEventListener("keydown", (e) => {
if (e.key === "Enter" & & currentLabel & & registeredTlds & & !registeredTlds.includes(currentLabel)) {
beginRegister(currentLabel);
}
});
// ---------- mint delegation ----------
// Register button hands the label off to the shared modal (register-flow.js
// — window.siriusRegisterTld). That modal owns the wallet-choice, fund,
// confirm, and mint steps — same UX as name registration.
function beginRegister(label) {
// Label-based tier pricing lives in siriusPricing (js/pricing.js) so
// landing / tld / mint agree. Fall back to the flat DEFAULT_USD if the
// pricing module hasn't loaded for some reason.
const p = window.siriusPricing?.priceForTld(label);
const fee = p ? p.sats : BigInt(DEFAULT_USD * (window.siriusPricing?.SATS_PER_USD || CHIPNET_SATS_PER_USD));
const call = () => window.siriusRegisterTld(label, { serviceFeeSats: fee });
if (typeof window.siriusRegisterTld === "function") { call(); return; }
// Module still loading — retry until it lands.
const btn = $("go-register");
const orig = btn?.textContent;
if (btn) { btn.disabled = true; btn.textContent = "loading…"; }
const t = setInterval(() => {
if (typeof window.siriusRegisterTld === "function") {
clearInterval(t);
if (btn) { btn.disabled = false; btn.textContent = orig; }
call();
}
}, 100);
}
// ---------- ?q= deep-link (from landing links etc.) ----------
(() => {
const q = normLabel(new URLSearchParams(location.search).get("q") || "");
if (!q) return;
$("q").value = q;
const wait = setInterval(() => {
if (registeredTlds === null) return;
clearInterval(wait);
refreshSearch();
setTimeout(() => $("q").scrollIntoView({ behavior: "smooth", block: "start" }), 100);
}, 150);
})();
< / script >
2026-09-20 19:20:30 +02:00
< script type = "module" src = "./js/register-flow.js?v=20260920usd" > < / script >
2026-09-20 18:33:01 +02:00
< script src = "./js/pricing.js?v=20260920bits" > < / script >
< script src = "./js/session.js?v=20260917dash" > < / script >
< script src = "./js/pin-escrow.js?v=20260909pin" > < / script >
< script defer src = "./js/theme.js?v=20260920compact" > < / script >
< script defer src = "./js/site-footer.js?v=20260917market" > < / script >
< script defer src = "./js/profile-menu.js?v=20260920bits" > < / script >
< script >
2026-09-20 19:20:30 +02:00
// Sidenav scroll-spy: highlight the section currently in view.
// Uses scroll-position tracking so short sections at the end of the page
// still activate their link when the reader scrolls to them.
2026-09-20 18:33:01 +02:00
(() => {
const links = document.querySelectorAll(".sidenav a[href^='#']");
if (!links.length) return;
2026-09-20 19:20:30 +02:00
const entries = [];
links.forEach((a) => { const el = document.querySelector(a.getAttribute("href")); if (el) entries.push({ el, link: a }); });
if (!entries.length) return;
const setActive = (link) => { links.forEach((l) => l.classList.remove("active")); link.classList.add("active"); };
const update = () => {
const doc = document.documentElement;
const scrollBottom = window.scrollY + window.innerHeight;
if (scrollBottom >= (doc.scrollHeight - 4)) { setActive(entries[entries.length - 1].link); return; }
const line = window.scrollY + window.innerHeight * 0.35;
let active = entries[0].link;
for (const e of entries) {
if (e.el.getBoundingClientRect().top + window.scrollY < = line) active = e.link;
else break;
}
setActive(active);
};
window.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
update();
2026-09-20 18:33:01 +02:00
})();
< / script >
< / body >
< / html >