site(hephaestus.x): redesign landing to Sirius design language + source section

Answers a community question ("how would one run this if it's not on GitHub?")
by putting the source repo front and centre, plus a runnable docker-compose
recipe for self-hosting.

- Palette + typography (Fraunces / DM Sans / JetBrains Mono / Ubuntu) and
  layout (topnav, radial-stack background, .card, .steps, .verify, .note)
  aligned with site-sirius-x. Adds js/theme.js (copied from sirius-x) for
  the Fraunces↔Ubuntu font toggle.
- Sticky topnav: brand, section links, Explore repos, wallet dropdown at right.
- Hero: "The forge on Bitcoin Cash" — BCH-green accent, matched serif hierarchy.
- New "See the source. Verify the deploy." section — three cards for the repo,
  auth-proxy, and PROTOCOL.md; below that a docker-compose run-your-own recipe
  with git clone + cp .env.example + docker compose up.
- Pantheon and Verify-against-the-chain sections mirror Sirius.X's structure so
  the seven .x pillars feel like one product.
- Browse repos link fixed to be absolute (https://code.silentmode.st/explore/repos)
  so it works through navigate.st gateway too, not just BCNR-aware browsers.
This commit is contained in:
Local Dev 2026-09-10 00:38:48 +02:00
parent 089805c498
commit 08d1879959
2 changed files with 416 additions and 58 deletions

View file

@ -3,45 +3,111 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hephaestus — the forge</title> <title>Hephaestus.X — the forge on Bitcoin Cash</title>
<meta name="description" content="A code host you sign in to with a Bitcoin Cash wallet. Repos hosted, cold blobs on Sia. No email, no password reset, no middleman."> <meta name="description" content="Hephaestus is the code forge for the Bitcoin Cash ecosystem. Sign in with your wallet — no email, no password reset. Repos on a fast local disk, cold blobs on Sia. Open source, verifiable, self-hostable.">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Hephaestus.X">
<meta property="og:title" content="Hephaestus.X — the forge on Bitcoin Cash">
<meta property="og:description" content="A code forge you sign in to with a Bitcoin Cash wallet. Open source, self-hostable, backed by Sia.">
<meta property="og:url" content="https://hephaestus.x/">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hephaestus.X — the forge on Bitcoin Cash">
<meta name="twitter:description" content="Sign in with a Bitcoin Cash wallet. Open source, self-hostable, backed by Sia.">
<!-- Silent Mode family fonts (Fraunces editorial + DM Sans body + JetBrains
Mono for code/hashes) plus Ubuntu as the Bitcoin Cash brand alt. -->
<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> <style>
:root{ :root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09); /* Shared with Sirius.X / silentmode.st/deviant — one Silent Mode palette. */
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d; --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;
/* Bitcoin Cash brand green — used for chain-native badges + a warm forge accent. */
--chain-native:#0AC18E;
--forge:#ff8c00;
--chain:#d6ff3d; --sia:#b39ddb; --srv:#4fd1a5; --ok:#4fd1a5; --taken:#f6768a;
--warn:#ffc75f;
--serif:'Fraunces',Georgia,serif;
--sans:'DM Sans','Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
} }
*{box-sizing:border-box} *{box-sizing:border-box}
html{scroll-behavior:smooth} html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg)); body{margin:0;
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh; background:radial-gradient(ellipse 1200px 600px at 50% -5%,var(--sky-rim) 0%,transparent 60%),
display:flex;flex-direction:column} 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)}
/* Ubuntu reader-alt — swap when <html data-font-cmp="ubuntu"> (js/theme.js) */
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 pill (lives inside .topnav — same styling as Sirius) */
.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}
.font-picker-float{position:fixed;bottom:20px;right:20px;z-index:99;
backdrop-filter:blur(10px);box-shadow:0 6px 20px rgba(0,0,0,.35)}
a{color:var(--acid)} a{color:var(--acid)}
.wrap{max-width:820px;margin:0 auto;padding:0 1.2rem;width:100%;flex:1} .wrap{max-width:980px;margin:0 auto;padding:0 1.2rem}
header.hero{text-align:center;padding:6rem 1.2rem 1rem} /* Sticky topnav — brand on the left, sign-in dropdown on the right */
.mark{font-size:64px;line-height:1} .topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
h1{font-size:clamp(2.2rem,6vw,3.4rem);margin:.5rem 0 .3rem;letter-spacing:-0.01em} padding:10px 1.2rem;background:rgba(5,8,16,.82);backdrop-filter:blur(10px);
h1 .g{color:var(--acid)} border-bottom:1px solid var(--line)}
.tag{color:var(--mut);font-size:1.1rem;max-width:600px;margin:0 auto} .topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px;display:inline-flex;align-items:center;gap:6px}
.cta{margin-top:2rem;display:flex;gap:10px;justify-content:center;flex-wrap:wrap;align-items:flex-start} .topnav .brand .g{color:var(--forge)}
.btn{display:inline-block;text-decoration:none;padding:12px 22px;border-radius:10px;font-size:14.5px;font-weight:500; .topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
border:1px solid var(--line);color:var(--ink);background:transparent;transition:filter .1s,background .1s} .topnav a:hover{color:var(--ink);background:var(--panel)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600;border-color:var(--acid)} .topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.btn:hover{filter:brightness(1.12);background:var(--panel)} .topnav .spacer{margin-left:auto}
.btn.acid:hover{background:var(--acid)} header.hero{text-align:center;padding:5rem 1.2rem 1rem}
/* wallet dropdown */ .mark{font-size:56px;line-height:1}
h1{font-size:clamp(2rem,5.5vw,3rem);margin:.4rem 0 .3rem}
h1 .g{color:var(--forge)}
h1 .b{color:var(--chain-native)}
.tag{color:var(--mut);font-size:1.05rem;max-width:660px;margin:0 auto;line-height:1.55}
.cta{margin-top:1.8rem;display:flex;gap:10px;justify-content:center;flex-wrap:wrap;align-items:flex-start}
.btn{display:inline-block;text-decoration:none;padding:11px 20px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit;transition:filter .1s}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.ghost:hover{background:var(--panel)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn:hover{filter:brightness(1.12)}
/* Wallet dropdown — same widget as before, restyled to match Sirius chrome */
details.wallet-dd{position:relative;display:inline-block;text-align:left} details.wallet-dd{position:relative;display:inline-block;text-align:left}
details.wallet-dd > summary{ details.wallet-dd > summary{
list-style:none;cursor:pointer;user-select:none; list-style:none;cursor:pointer;user-select:none;
background:var(--acid);color:#0b0e14;font-weight:600; background:var(--acid);color:#0b0e14;font-weight:600;
padding:12px 22px;border-radius:10px;font-size:14.5px; padding:11px 20px;border-radius:10px;font-size:14px;
border:1px solid var(--acid);display:inline-flex;align-items:center;gap:8px; border:1px solid var(--acid);display:inline-flex;align-items:center;gap:8px;
font-family:inherit;
} }
details.wallet-dd > summary::-webkit-details-marker{display:none} details.wallet-dd > summary::-webkit-details-marker{display:none}
details.wallet-dd > summary::marker{content:""} details.wallet-dd > summary::marker{content:""}
details.wallet-dd > summary .chev{transition:transform .15s;display:inline-block;font-size:11px} details.wallet-dd > summary .chev{transition:transform .15s;display:inline-block;font-size:11px}
details.wallet-dd[open] > summary .chev{transform:rotate(180deg)} details.wallet-dd[open] > summary .chev{transform:rotate(180deg)}
details.wallet-dd .menu{ details.wallet-dd .menu{
position:absolute;top:calc(100% + 8px);left:0;min-width:280px;z-index:20; position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);min-width:300px;z-index:30;
background:var(--panel);border:1px solid var(--line);border-radius:12px; background:var(--panel);border:1px solid var(--line);border-radius:12px;
padding:6px;display:flex;flex-direction:column;gap:2px; padding:6px;display:flex;flex-direction:column;gap:2px;
box-shadow:0 12px 32px rgba(0,0,0,.35); box-shadow:0 12px 32px rgba(0,0,0,.35);
@ -52,43 +118,114 @@
} }
details.wallet-dd .menu a:hover{background:var(--panel2)} details.wallet-dd .menu a:hover{background:var(--panel2)}
details.wallet-dd .menu .ico{font-size:18px;line-height:1.2} details.wallet-dd .menu .ico{font-size:18px;line-height:1.2}
details.wallet-dd .menu b{display:block;font-size:14px;font-weight:600;color:var(--ink)} details.wallet-dd .menu b{display:block;font-size:14px;font-weight:600;color:var(--ink);font-family:var(--sans)}
details.wallet-dd .menu .sub{display:block;font-size:12px;color:var(--mut);margin-top:2px;line-height:1.4} details.wallet-dd .menu .sub{display:block;font-size:12px;color:var(--mut);margin-top:2px;line-height:1.4}
details.wallet-dd .menu .pill{ details.wallet-dd .menu .pill{
display:inline-block;font-size:10px;padding:0 6px;margin-left:6px;border-radius:999px; display:inline-block;font-size:10px;padding:0 6px;margin-left:6px;border-radius:999px;
background:rgba(214,255,61,.15);color:var(--acid);font-weight:500;text-transform:lowercase;letter-spacing:.02em;vertical-align:middle; background:rgba(214,255,61,.15);color:var(--acid);font-weight:500;text-transform:lowercase;letter-spacing:.02em;vertical-align:middle;
} }
section.facts{padding:3rem 0 1rem} /* Topnav wallet dropdown is smaller and menu opens to the right edge */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px} .topnav details.wallet-dd > summary{padding:6px 14px;font-size:13.5px;border-radius:8px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px} .topnav details.wallet-dd .menu{right:0;left:auto;transform:none}
.card h3{margin:0 0 .35rem;font-size:15px;color:var(--ink);letter-spacing:.01em} /* Sections */
.card p{margin:0;color:var(--mut);font-size:13.5px;line-height:1.6} section{padding:2.6rem 0;border-top:1px solid var(--line);margin-top:2.5rem}
section:first-of-type{border-top:none;margin-top:1.5rem}
h2{font-size:1.5rem;margin:0 0 .4rem}
h3{font-size:1.1rem;margin:0 0 .35rem}
.lede{color:var(--mut);margin:0 0 1.6rem;max-width:720px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:18px 20px}
.card h3{margin:0 0 .5rem;display:flex;align-items:center;gap:8px}
.card p{margin:0;color:var(--mut);font-size:14px;line-height:1.55}
.card b{color:var(--ink)} .card b{color:var(--ink)}
section.stack{padding:2rem 0} .card .cta{margin-top:14px;justify-content:flex-start}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block}
.d-chain{background:var(--chain-native)} .d-sia{background:var(--sia)} .d-srv{background:var(--srv)}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin-top:1.4rem}
.note.warn{border-left-color:var(--warn)}
.note b{color:var(--ink)}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:13px}
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:12px 14px;overflow-x:auto;
font-family:var(--mono);font-size:13px;color:var(--ink);margin:1rem 0}
pre .cm{color:var(--dim)}
ol.steps{counter-reset:s;list-style:none;padding:0;margin:1.2rem 0 0;display:grid;gap:10px}
ol.steps li{counter-increment:s;display:grid;grid-template-columns:30px 1fr;gap:14px;align-items:start;
background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:13px 16px}
ol.steps li::before{content:counter(s);grid-column:1;grid-row:1;
display:grid;place-items:center;width:24px;height:24px;border-radius:50%;
background:rgba(214,255,61,.14);color:var(--acid);font-size:12.5px;font-weight:700}
ol.steps li > *{grid-column:2;min-width:0}
ol.steps b{color:var(--ink)} ol.steps span{color:var(--mut);font-size:14px}
.pill{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.07);color:var(--dim);margin-left:8px;vertical-align:middle;font-weight:500}
.pill.soon{background:rgba(214,255,61,.13);color:var(--acid)}
.pill.bch{background:rgba(10,193,142,.14);color:var(--chain-native)}
.verify dt{color:var(--mut);font-size:12.5px;text-transform:uppercase;letter-spacing:.3px;margin-top:12px}
.verify dt:first-of-type{margin-top:0}
.verify dd{margin:2px 0 0;font-family:var(--mono);font-size:12.5px;word-break:break-all;color:var(--ink)}
dl.spec{display:grid;grid-template-columns:auto 1fr;gap:8px 22px;margin:0;font-size:13.5px} dl.spec{display:grid;grid-template-columns:auto 1fr;gap:8px 22px;margin:0;font-size:13.5px}
dl.spec dt{color:var(--dim);white-space:nowrap;font-family:ui-monospace,monospace} dl.spec dt{color:var(--dim);white-space:nowrap;font-family:var(--mono)}
dl.spec dd{margin:0;color:var(--mut)} dl.spec dd{margin:0;color:var(--mut)}
dl.spec dd b{color:var(--ink)} dl.spec dd b{color:var(--ink)}
dl.spec a{color:var(--acid)} footer{border-top:1px solid var(--line);padding:2.4rem 0 3.5rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
section.stack h2{font-size:1.15rem;margin:0 0 .8rem;color:var(--ink);font-weight:500} footer a{color:var(--mut)} footer a:hover{color:var(--ink)}
footer{border-top:1px solid var(--line);padding:2.4rem 1.2rem 3.4rem;color:var(--dim);font-size:13px;text-align:center;margin-top:3rem} @media (max-width:640px){
footer a{color:var(--mut)} .topnav{padding:8px 1rem;gap:0}
footer a:hover{color:var(--ink)} .topnav a{padding:6px 8px;font-size:13px}
code{background:#0e131b;border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:12.5px} .topnav .font-picker{margin:0 4px}
header.hero{padding:3.5rem 1rem 1rem}
}
</style> </style>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
</head> </head>
<body> <body>
<nav class="topnav">
<a class="brand" href="./">⚒️ <span class="g">Hephaestus</span>.X</a>
<a href="#how">How it works</a>
<a href="#source">Source</a>
<a href="#pantheon">Pantheon</a>
<a href="https://code.silentmode.st/explore/repos" rel="noopener">Explore repos</a>
<span class="spacer"></span>
<details class="wallet-dd">
<summary>🔑 Sign in <span class="chev"></span></summary>
<div class="menu" role="menu">
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#import" role="menuitem">
<span class="ico">🔑</span>
<span>
<b>Sign in</b>
<span class="sub">Import a wallet — 12- or 24-word recovery phrase.</span>
</span>
</a>
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#create" role="menuitem">
<span class="ico"></span>
<span>
<b>Sign up<span class="pill">easiest</span></b>
<span class="sub">Generate a fresh wallet in your browser.</span>
</span>
</a>
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#connect" role="menuitem">
<span class="ico">🪄</span>
<span>
<b>WizardConnect<span class="pill">most private</span></b>
<span class="sub">Sign with Cashonize or Paytaca — keys stay in your wallet.</span>
</span>
</a>
</div>
</details>
</nav>
<div class="wrap"> <div class="wrap">
<header class="hero"> <header class="hero">
<div class="mark">⚒️</div> <div class="mark">⚒️</div>
<h1><span class="g">Hephaestus</span></h1> <h1>The forge on <span class="b">Bitcoin Cash</span>.</h1>
<p class="tag">A code host you sign in to with a Bitcoin Cash wallet. No email, no password reset, no middleman.</p> <p class="tag">Hephaestus is the code host for the BCH ecosystem — Cauldron contributors, Sirius developers, wallet
authors, indexer maintainers. Sign in with a wallet, push a repo, host a release. <b>No email, no password reset,
no middleman.</b></p>
<div class="cta"> <div class="cta">
<details class="wallet-dd"> <details class="wallet-dd">
<summary>Bitcoin Cash wallet <span class="chev"></span></summary> <summary>🔑 Sign in with wallet <span class="chev"></span></summary>
<div class="menu" role="menu"> <div class="menu" role="menu">
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#import" role="menuitem"> <a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#import" role="menuitem">
<span class="ico">🔑</span> <span class="ico">🔑</span>
@ -113,44 +250,202 @@
</a> </a>
</div> </div>
</details> </details>
<a class="btn" href="/explore/repos">Browse repos</a> <a class="btn ghost" href="https://code.silentmode.st/explore/repos">Browse repos</a>
<a class="btn" href="https://silentmode.st/hephaestus/">Read the docs</a> <a class="btn ghost" href="#source">See the source</a>
</div> </div>
</header> </header>
<section class="facts"> <section id="how">
<h2>How it works</h2>
<p class="lede">Three moving parts, no magic. Forgejo does the git and issue tracking, an auth-proxy translates
Bitcoin Cash message signatures into OpenID Connect tokens Forgejo understands, and Caddy fronts the whole
thing behind the two hostnames — <code>hephaestus.x</code> for BCNR-aware browsers, <code>code.silentmode.st</code>
as a public DNS mirror.</p>
<div class="grid"> <div class="grid">
<div class="card"> <div class="card">
<h3>Your wallet is your account</h3> <h3>🔑 Wallet is the account</h3>
<p>Generate or import a BCH wallet in the browser. Sign one challenge, you're in. <b>Nothing to remember except your recovery phrase.</b></p> <p>Generate or import a BCH wallet in the browser. Sign one BIP-137 <em>"Bitcoin Signed Message"</em> challenge,
and Forgejo auto-provisions <code>bch_&lt;first-20-of-your-cashaddr&gt;</code>. Rename it later — even to a
plain name like <code>BitcoinCash</code>. <b>The private key never leaves your device.</b></p>
</div> </div>
<div class="card"> <div class="card">
<h3>Storage on Sia</h3> <h3>💾 Cold blobs on Sia</h3>
<p>LFS, releases, packages, attachments — all sharded and encrypted across independent Sia hosts worldwide. <b>Live git stays on a fast local disk</b> for speed.</p> <p>Live git repos + Postgres stay on the VPS SSD for speed. LFS objects, release archives, container images,
package registry blobs and issue attachments spill to the <a href="https://sia.storage/" rel="noopener">Sia
network</a> via <code>s3.silentmode.st:8600</code>. Encrypted client-side, sharded across independent hosts.</p>
</div> </div>
<div class="card"> <div class="card">
<h3>Standard git, nothing weird</h3> <h3>🌐 Two hostnames, one instance</h3>
<p><code>git clone</code>, <code>git push</code>, PRs, issues, releases, container/npm registries. Bring your existing muscle memory.</p> <p><b>hephaestus.x</b> is the primary — an on-chain BCNR certificate, chipnet, owner-controlled, TLS via the
Silent Mode CA. <b>code.silentmode.st</b> is the public-DNS mirror for browsers without a BCNR resolver.
Same Forgejo, same accounts, same repos.</p>
</div>
<div class="card">
<h3>🧭 Standard git, nothing weird</h3>
<p><code>git clone</code>, <code>git push</code>, PRs, issues, releases, container/npm registries, the
Forgejo API. Bring your existing muscle memory — the only unusual bit is that you signed in with a wallet
instead of an email.</p>
</div> </div>
</div> </div>
</section> </section>
<section class="stack"> <section id="signin">
<h2>Where it lives</h2> <h2>Sign in in three steps</h2>
<dl class="spec"> <p class="lede">Nothing to install, nothing to remember except your recovery phrase.</p>
<dt>forge</dt> <dd><a href="https://code.silentmode.st/">code.silentmode.st</a> (mirror) · <b>hephaestus.x</b> (primary) — same Forgejo 10, dual-hostname</dd> <ol class="steps">
<dt>this name</dt> <dd><b>hephaestus.x</b> — on-chain BCNR certificate, chipnet, owner-controlled, TLS via Silent Mode CA</dd> <li><b>Pick your route.</b> <span>Sign up (create a new wallet in the browser), Sign in (import a 12/24-word
<dt>storage</dt> <dd>Sia network via <code>s3.silentmode.st:8600</code>, encrypted client-side · static landing mirrored to Sia bucket as DR backup</dd> phrase you already have), or WizardConnect (sign with an external wallet — Cashonize, Paytaca — over an
<dt>source</dt> <dd><a href="https://code.silentmode.st/silentmode/hephaestus">silentmode/hephaestus</a> — the docker-compose + auth-proxy + Caddyfile</dd> encrypted relay).</span></li>
<dt>protocol</dt> <dd>BIP-137 "Bitcoin Signed Message" over BCH secp256k1 — any wallet that speaks Sign Message can log in</dd> <li><b>Set a browser passphrase.</b> <span>Used to encrypt the wallet in your browser's <code>localStorage</code>.
Minimum 8 characters. Never leaves your device.</span></li>
<li><b>Sign the challenge.</b> <span>Your browser signs a one-time message, the auth-proxy verifies the signature
against your Bitcoin Cash address, and Forgejo hands you a session cookie. You land in the dashboard.</span></li>
</ol>
<div class="cta" style="justify-content:flex-start;margin-top:1.4rem">
<details class="wallet-dd">
<summary>Start now <span class="chev"></span></summary>
<div class="menu" role="menu">
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#create" role="menuitem"><span class="ico"></span><span><b>Sign up</b><span class="sub">Create a new wallet.</span></span></a>
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#import" role="menuitem"><span class="ico">🔑</span><span><b>Sign in</b><span class="sub">Import an existing wallet.</span></span></a>
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet#connect" role="menuitem"><span class="ico">🪄</span><span><b>WizardConnect</b><span class="sub">Cashonize / Paytaca.</span></span></a>
</div>
</details>
</div>
</section>
<section id="source">
<h2>See the source. Verify the deploy.</h2>
<p class="lede">The whole forge — the Docker Compose stack, the Caddyfile, the auth-proxy that verifies wallet
signatures, the Forgejo Dockerfile with our CA baked in, every helper script — is on Hephaestus itself.
Clone it, read it, run it.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-srv"></span> 📖 silentmode/hephaestus</h3>
<p>The full stack. <code>docker-compose.yml</code>, <code>caddy/Caddyfile</code>,
<code>auth-proxy/</code> (Fastify OIDC provider), <code>forgejo/Dockerfile</code>,
<code>scripts/</code>, <code>PROTOCOL.md</code>.</p>
<div class="cta"><a class="btn acid" href="https://code.silentmode.st/silentmode/hephaestus" rel="noopener">Open repo →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> 🔐 auth-proxy</h3>
<p>The wallet-to-OIDC bridge. ~250 lines of TypeScript that produces an Ed25519-signed <code>id_token</code>
after verifying a BIP-137 signature against a claimed CashAddr. The whole crypto path is in
<code>src/verify.ts</code>.</p>
<div class="cta"><a class="btn ghost" href="https://code.silentmode.st/silentmode/hephaestus/src/branch/master/auth-proxy" rel="noopener">Read →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> 📜 PROTOCOL.md</h3>
<p>Wallet-auth flow, message format, replay-protection, prefix handling (bitcoincash / bchtest / bchreg).
The document a third-party wallet needs to add native support.</p>
<div class="cta"><a class="btn ghost" href="https://code.silentmode.st/silentmode/hephaestus/src/branch/master/PROTOCOL.md" rel="noopener">Read →</a></div>
</div>
</div>
<h3 style="margin-top:1.8rem">Run your own</h3>
<p class="lede">Nothing here needs Hephaestus.X's operator — the same compose stack runs on any Linux box with
Docker. Bring your own domain, a TLS cert, and a Sia bucket (the sia.storage free tier is enough for a small
forge). Then <code>docker compose up</code>.</p>
<pre><span class="cm"># 1. clone</span>
git clone https://code.silentmode.st/silentmode/hephaestus.git
cd hephaestus
<span class="cm"># 2. configure — copy .env.example, fill in your domain, Sia S3 creds, and OIDC secret</span>
cp .env.example .env
$EDITOR .env
<span class="cm"># 3. run — Caddy + Postgres + Forgejo + auth-proxy come up together</span>
docker compose up -d
<span class="cm"># 4. first wallet signs in and takes the admin seat</span>
open https://your-domain.example/user/oauth2/hephaestus-wallet</pre>
<div class="note"><b>Open source, MIT.</b> Every commit is signed, every dependency is pinned. If you find
something you want to fix or improve, open a PR — or just fork it and run your own instance. That is the
point.</div>
</section>
<section id="pantheon">
<h2>The Silent Mode pantheon</h2>
<p class="lede">Hephaestus is one of seven sibling <b>.x</b> names. Each project is its own on-chain certificate,
each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> ⛓️ Silentmode.X</h3>
<p>The project umbrella. Redirects to <code>silentmode.st</code> where every pillar has its own landing.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/silentmode.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> ⭐ Sirius.X</h3>
<p>Names on Bitcoin Cash — register, resolve, verify, manage TLDs and names.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/sirius.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> 🧭 Theseus.X</h3>
<p>The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/theseus.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> ⚒️ Hephaestus.X <span class="pill">you're here</span></h3>
<p>The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. This site.</p>
<div class="cta"><a class="btn ghost" href="./">Home →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> 🔮 Prometheus.X</h3>
<p>Fire from the chain. Foresight and experimentation layer. Redirects to <code>silentmode.st/prometheus/</code>.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/prometheus.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> ☀️ Helios.X</h3>
<p>Public gaze — analytics, dashboards, transparency. Redirects to <code>silentmode.st/helios/</code>.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/helios.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> ✉️ Hermes.X</h3>
<p>Messenger. Nostr-based messaging bound to a BCNR name via the <code>np</code> + <code>nr</code> records.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/hermes.x/" rel="noopener">Open →</a></div>
</div>
</div>
</section>
<section id="verify">
<h2>Verify this page against the chain</h2>
<p class="lede">You do not have to trust that <code>hephaestus.x</code> is served by anyone specific. The name's
certificate is on the Bitcoin Cash chain; the records point to a specific IP and a specific Sia bucket; every
path is independently checkable.</p>
<h3>1. Reach this site via more than one route</h3>
<p class="lede">The same content should be served from at least two independent paths. If one mirror disappears,
the others still work. If two disagree, the on-chain record is the tiebreaker.</p>
<ul style="color:var(--mut);font-size:14px;margin:.6rem 0 0;padding-left:1.2rem;line-height:1.7">
<li>Via any BCNR resolver: <code>https://hephaestus.x/</code> (requires the local root CA)</li>
<li>Via the public gateway: <code>https://navigate.st/bns/hephaestus.x</code></li>
<li>Via silentmode.st mirror: <code>https://silentmode.st/hephaestus/</code></li>
<li>Public DNS mirror of the forge itself: <code>https://code.silentmode.st/</code></li>
</ul>
<h3>2. Where it lives</h3>
<dl class="spec" style="margin-top:.8rem">
<dt>forge</dt> <dd><b>hephaestus.x</b> (primary) · <a href="https://code.silentmode.st/">code.silentmode.st</a> (public-DNS mirror) — same Forgejo 10 instance, dual-hostname</dd>
<dt>this name</dt> <dd><b>hephaestus.x</b> — on-chain BCNR certificate, chipnet, owner-controlled, TLS via the Silent Mode CA</dd>
<dt>storage</dt> <dd>Sia network via <code>s3.silentmode.st:8600</code>, client-side encrypted · static landing mirrored to a Sia bucket as DR backup</dd>
<dt>source</dt> <dd><a href="https://code.silentmode.st/silentmode/hephaestus" rel="noopener">silentmode/hephaestus</a> — docker-compose, auth-proxy, Caddyfile, the whole stack</dd>
<dt>protocol</dt> <dd>BIP-137 <em>"Bitcoin Signed Message"</em> over BCH secp256k1 — any wallet that speaks Sign Message can log in</dd>
</dl> </dl>
</section> </section>
</div> </div>
<footer> <footer>
A tool from <a href="https://silentmode.st/">Silent Mode</a> · alpha on chipnet · one wallet, all of it <p>A pillar of <a href="https://silentmode.st/">Silent Mode</a> · alpha on chipnet · one wallet, all of it</p>
<p style="margin-top:.6rem;font-size:12px">
<a href="https://code.silentmode.st/silentmode/hephaestus" rel="noopener">Source</a> ·
<a href="https://silentmode.st/hephaestus/">Docs</a> ·
<a href="https://silentmode.st/bns/sirius.x/">Get a .x name</a>
</p>
</footer> </footer>
<script defer src="./js/theme.js"></script>
</body> </body>
</html> </html>

63
hephaestus.x/js/theme.js Normal file
View file

@ -0,0 +1,63 @@
// Sirius.X font picker — reader chooses between Fraunces (Silent Mode
// family — editorial serif, default) and Ubuntu (Bitcoin Cash brand
// font — humanist sans). Persisted in localStorage under 'sirius-font'.
//
// The runtime attribute goes on <html> — pages that want to opt out
// simply omit the include. The actual font-swap CSS is defined per
// page (in each page's <style> block) so it can override the page's
// own font-family declarations at high specificity; this script only
// toggles the attribute and paints the picker UI.
(function () {
var KEY = "sirius-font";
var saved = null;
try { saved = localStorage.getItem(KEY); } catch (e) { /* private mode */ }
var initial = saved === "ubuntu" ? "ubuntu" : "fraunces";
if (initial === "ubuntu") document.documentElement.setAttribute("data-font-cmp", "ubuntu");
// Inject the picker into the topnav's right side when one exists.
// Falls back to a fixed-position pill (bottom-right) for pages without
// a topnav, so the choice is always available.
function paintPicker() {
var nav = document.querySelector(".topnav");
var host = nav || document.body;
var mount = document.createElement("div");
mount.className = "font-picker";
mount.setAttribute("role", "group");
mount.setAttribute("aria-label", "Reading font");
mount.innerHTML =
'<button data-font="fraunces" title="Silent Mode family (Fraunces)">Fraunces</button>' +
'<button data-font="ubuntu" title="Bitcoin Cash brand font (Ubuntu)">Ubuntu</button>';
if (nav) {
// Put it just before the sign-in link if present, else append.
var portalLink = nav.querySelector("a.portal");
if (portalLink) nav.insertBefore(mount, portalLink);
else nav.appendChild(mount);
} else {
mount.classList.add("font-picker-float");
host.appendChild(mount);
}
var btns = mount.querySelectorAll("button");
function refresh(v) {
for (var i = 0; i < btns.length; i++) {
btns[i].classList.toggle("active", btns[i].dataset.font === v);
}
}
refresh(initial);
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function (e) {
var v = e.currentTarget.dataset.font;
if (v === "ubuntu") document.documentElement.setAttribute("data-font-cmp", "ubuntu");
else document.documentElement.removeAttribute("data-font-cmp");
try { localStorage.setItem(KEY, v); } catch (e2) { /* ignore */ }
refresh(v);
});
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", paintPicker);
} else {
paintPicker();
}
})();