hermes.x: standalone site + sidebar addon side:left + mark v2 (tapered trails)

New site-hermes-x/ — standalone .x site (own nav, own assets, own OG tags),
sibling to site-theseus-x and site-sirius-x. Internal nav stays on hermes.x:
Overview, Messenger (preview + UI mockup), Branding (brand kit). The only
cross-link is 'Get Theseus' pointing at theseus.x where appropriate.

Mark redesigned: tilted winged envelope with three tapered speed-trails on
the back-left (top longest, bottom shortest). Default colour sky #38BDF8 —
swappable via --sky in site-hermes-x/assets/shared.css. Alternate orange
palette documented but not applied by default. Mark propagated to:
  - site-hermes-x/assets/mark.svg + mark-stroke.svg (16-20px variant)
  - site/hermes/{index.html, branding/{index.html, mark.svg, mark-stroke.svg}}
  - TheseusNavigator/bundled-addons/hermes/{addon.json, panel.html}

Theseus addon moves out of the top-right extensions dock and into the
left-strip sidebar: panels[].side = 'left' + registerSidebarPanel({side:'left'}).
Appears alongside Mail/Pithos/Telegram, excluded from rightPanels() so the
extensions dock no longer lists it. Verified via sidebarState() CDP query —
hermes:main is no longer in the right-panels list.

site/hermes/ (the nested silentmode.st/hermes page) also updated to the new
mark for consistency; both the sovereign hermes.x and the silentmode-nested
page now show the same winged envelope.
This commit is contained in:
Local Dev 2026-10-21 02:19:58 +03:00
commit f73b35c349
7 changed files with 745 additions and 0 deletions

7
assets/favicon.svg Normal file
View file

@ -0,0 +1,7 @@
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="#38BDF8" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)">
<rect x="20" y="26" width="30" height="18" rx="1.5"/>
<path d="M20 27 L35 37 L50 27"/>
<path d="M20 36 L4 36"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 328 B

8
assets/mark-stroke.svg Normal file
View file

@ -0,0 +1,8 @@
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Hermes">
<title>Hermes</title>
<g fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)">
<rect x="20" y="26" width="30" height="18" rx="1.5"/>
<path d="M20 27 L35 37 L50 27"/>
<path d="M20 36 L4 36"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 388 B

10
assets/mark.svg Normal file
View file

@ -0,0 +1,10 @@
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Hermes">
<title>Hermes</title>
<g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)">
<rect x="20" y="26" width="30" height="18" rx="1.5"/>
<path d="M20 27 L35 37 L50 27"/>
<path d="M20 30 L2 30"/>
<path d="M20 36 L10 36"/>
<path d="M20 42 L14 42"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 448 B

112
assets/shared.css Normal file
View file

@ -0,0 +1,112 @@
/* hermes.x — standalone brand site, not derived from silentmode.st shared.css.
Primary accent is sky-mid #38BDF8 (default; swap --sky in :root to re-skin). */
:root{
--bg:#0b0e14;
--panel:#141a24;
--panel2:#18202c;
--panel3:#1d2634;
--line:rgba(255,255,255,.09);
--line2:rgba(255,255,255,.14);
--ink:#e7eaf1;
--mut:#8b98a9;
--dim:#5e6678;
--sky:#38BDF8; /* primary accent — the Hermes mark colour */
--sky-soft:#60A5FA;
--sky-deep:#0EA5E9;
--warn:#ffc75f;
--ok:#4fd1a5;
--err:#f6768a;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
margin:0;
background:radial-gradient(1100px 560px at 50% -12%,#121a26,var(--bg));
color:var(--ink);
font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
min-height:100vh;
}
a{color:var(--sky)}
a:hover{color:var(--sky-soft)}
/* ---- top nav ---- */
.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,.85);
backdrop-filter:blur(10px);
border-bottom:1px solid var(--line);
}
.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:8px;
}
.topnav .brand svg{width:20px;height:20px;color:var(--sky)}
.topnav .brand .x{color:var(--sky)}
.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(--sky);background:rgba(56,189,248,.08)}
.topnav .get{margin-left:auto;background:rgba(56,189,248,.14);color:var(--sky);font-weight:500}
.topnav .get:hover{background:rgba(56,189,248,.22)}
/* ---- layout ---- */
.wrap{max-width:980px;margin:0 auto;padding:0 1.2rem}
.wrap.narrow{max-width:780px}
header.hero{text-align:center;padding:4.5rem 1.2rem 2.4rem}
header.hero .mark{display:inline-flex;color:var(--sky);line-height:0}
header.hero .mark svg{width:120px;height:120px}
h1{font-size:clamp(2.2rem,5vw,3.2rem);margin:.8rem 0 .3rem;letter-spacing:.4px;font-weight:600}
h1 .x{color:var(--sky)}
.tag{color:var(--mut);font-size:1.1rem;max-width:660px;margin:.4rem auto 0}
.tag kbd{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:4px;padding:1px 7px;font-family:ui-monospace,monospace;font-size:13px;color:var(--ink)}
section{padding:2.8rem 0;border-top:1px solid var(--line)}
section.plain{border-top:none}
h2{font-size:1.55rem;margin:0 0 .4rem;font-weight:600}
h3{font-size:1.05rem;margin:0 0 .3rem;font-weight:600}
.lede{color:var(--mut);margin:0 0 1.6rem;max-width:680px}
/* ---- cards ---- */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.card{
background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px;
}
.card h3{display:flex;align-items:center;gap:8px;margin-bottom:.5rem}
.card p{margin:0;color:var(--mut);font-size:14px;line-height:1.55}
.src{display:inline-block;font-size:11px;padding:1px 7px;border-radius:999px;background:var(--panel2);color:var(--mut);text-transform:uppercase;letter-spacing:.4px;font-weight:600}
.src.ok{color:var(--ok);background:rgba(79,209,165,.12)}
.src.next{color:var(--sky);background:rgba(56,189,248,.12)}
.src.plan{color:var(--mut)}
/* ---- notes ---- */
.note{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px;font-size:14px;color:var(--mut)}
.note b{color:var(--ink)}
.note.warn{background:rgba(255,199,95,.06);border-color:rgba(255,199,95,.22);color:var(--ink)}
.note.warn b{color:var(--warn)}
/* ---- buttons / CTAs ---- */
.cta{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:1.7rem}
.btn{display:inline-flex;align-items:center;gap:8px;text-decoration:none;padding:11px 20px;border-radius:999px;font-weight:600;font-size:14px}
.btn.primary{background:var(--sky);color:#06111a}
.btn.primary:hover{filter:brightness(1.08)}
.btn.ghost{background:var(--panel);color:var(--ink);border:1px solid var(--line)}
.btn.ghost:hover{background:var(--panel2);border-color:var(--line2)}
code.inline{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:rgba(255,255,255,.05);padding:1px 6px;border-radius:5px;font-size:.92em}
/* ---- steps list ---- */
.steps{list-style:none;padding:0;margin:0;counter-reset:step}
.steps li{display:flex;gap:14px;padding:14px 0;border-top:1px solid var(--line)}
.steps li:first-child{border-top:none;padding-top:0}
.steps li::before{counter-increment:step;content:counter(step);flex-shrink:0;width:28px;height:28px;border-radius:50%;background:rgba(56,189,248,.12);color:var(--sky);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600}
.steps li b{display:block;margin-bottom:4px}
.steps li span{color:var(--mut);font-size:14px}
footer{text-align:center;padding:2.5rem 1.2rem 3rem;color:var(--mut);font-size:13px;border-top:1px solid var(--line)}
footer .fine{color:var(--dim);font-size:12px;margin-top:.5rem}

193
branding/index.html Normal file
View file

@ -0,0 +1,193 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hermes.x — brand kit</title>
<meta name="description" content="Hermes brand kit: mark, palette, name, voice. Not Hermès the fashion house; Hermes the messenger god.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="../assets/shared.css">
<style>
.mark-xl{color:var(--sky); line-height:0; display:inline-flex}
.mark-xl svg{width:160px; height:160px}
.mark-row{display:flex;gap:16px;align-items:center;flex-wrap:wrap;margin:1rem 0 2rem}
.mark-row .cell{display:flex;flex-direction:column;align-items:center;gap:10px;padding:16px;background:var(--panel);border:1px solid var(--line);border-radius:12px;min-width:130px}
.mark-row .cell small{color:var(--mut);font-size:11px;text-align:center}
.mark-row .cell svg{display:block}
.mark-16{color:var(--ink);line-height:0}
.mark-16 svg{width:16px;height:16px}
.mark-32{color:var(--ink);line-height:0}
.mark-32 svg{width:32px;height:32px}
.mark-64{color:var(--sky);line-height:0}
.mark-64 svg{width:64px;height:64px}
.mark-neg{color:#06111a;line-height:0;padding:14px 18px;border-radius:12px;background:var(--sky)}
.mark-neg svg{width:48px;height:48px}
.swatches{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin:1rem 0 2rem}
.sw{background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.sw .block{height:70px}
.sw .meta{padding:10px 12px;font-size:12px;color:var(--mut)}
.sw .meta b{display:block;color:var(--ink);font-size:13px;font-weight:600;margin-bottom:2px}
.sw .meta code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.tbl{width:100%;border-collapse:collapse;margin:1rem 0 2rem;font-size:14px}
.tbl th,.tbl td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}
.tbl th{color:var(--mut);font-weight:500;font-size:12px;text-transform:uppercase;letter-spacing:.4px}
.tbl td.y{color:var(--ok)} .tbl td.n{color:var(--err)}
.dl-row{display:flex;gap:10px;flex-wrap:wrap;margin:1rem 0}
.dl-row a{display:inline-flex;align-items:center;gap:8px;text-decoration:none;padding:10px 14px;border-radius:999px;background:var(--panel);color:var(--ink);border:1px solid var(--line);font-size:13px}
.dl-row a:hover{background:var(--panel2);border-color:var(--line2)}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">
<svg viewBox="0 0 64 64" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 36 L4 36"/></g></svg>
hermes<span class="x">.x</span>
</a>
<a href="../">Overview</a>
<a href="../messenger/">Messenger</a>
<a href="./" class="here">Branding</a>
<a href="https://theseus.x/" class="get">Get Theseus</a>
</nav>
<header class="hero">
<div class="mark mark-xl" aria-hidden="true">
<svg viewBox="0 0 64 64"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg>
</div>
<h1>Brand kit</h1>
<p class="tag">Mark, palette, name, voice. One page so client builds, add-on
chrome, screenshots and third-party press stay consistent.</p>
</header>
<div class="wrap narrow">
<section class="plain">
<h2>The name</h2>
<p>In English the product is <b>Hermes</b> — after the Greek god of
messengers, travellers, and crossings. In modern Greek the same name is
<b>Ermis</b> (Ἑρμῆς). Written form is always Hermes outside Greek contexts.</p>
<p>The keyboard shortcut inside Theseus is <code class="inline">Ctrl+Shift+E</code>
— E for Ermis, off the collision path with Chrome's own Ctrl+Shift+M.</p>
<div class="note warn" style="margin-top:1rem"><b>Not Hermès.</b> The French
fashion house owns the mental model for the word with the grave accent and
the orange leather. We spell it <b>Hermes</b> (no accent). Our mark is a
winged envelope mid-flight, not a horse-drawn carriage. If a visitor
confuses the two, the mark alone should set them straight.</div>
</section>
<section>
<h2>The mark</h2>
<p class="lede">A tilted envelope with three speed-trails on the back edge
— a letter mid-flight. Monochrome, scales from 16 px (sidebar icon) to
160 px (hero) without legibility loss. SVG uses
<code class="inline">currentColor</code> so it inherits whatever text
colour it sits in.</p>
<div class="mark-row">
<div class="cell">
<div class="mark-16"><svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 36 L4 36"/></g></svg></div>
<small>16 px — stroke variant (one trail)</small>
</div>
<div class="cell">
<div class="mark-32"><svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg></div>
<small>32 px — standard (3 tapered trails)</small>
</div>
<div class="cell">
<div class="mark-64"><svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg></div>
<small>64 px — in-panel</small>
</div>
<div class="cell">
<div class="mark-neg"><svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg></div>
<small>on sky background</small>
</div>
</div>
<div class="dl-row">
<a href="../assets/mark.svg" download>⬇️ mark.svg (standard, 3 trails)</a>
<a href="../assets/mark-stroke.svg" download>⬇️ mark-stroke.svg (16–20 px variant)</a>
</div>
<table class="tbl">
<thead><tr><th>Do</th><th>Don't</th></tr></thead>
<tbody>
<tr>
<td class="y">Keep the envelope tilted ~22°, trails on the back-left.</td>
<td class="n">Mirror the mark or tilt it the opposite direction.</td>
</tr>
<tr>
<td class="y">Let the mark inherit text colour (currentColor).</td>
<td class="n">Hard-code a colour inside the SVG; it limits reuse.</td>
</tr>
<tr>
<td class="y">Use the stroke variant below 24 px display size.</td>
<td class="n">Scale the standard mark below 20 px — trails merge.</td>
</tr>
<tr>
<td class="y">Pair with the wordmark "hermes.x" when context is unclear.</td>
<td class="n">Pair with the Hermès logotype or any horsey mascot.</td>
</tr>
</tbody>
</table>
</section>
<section>
<h2>Palette</h2>
<p class="lede">Hermes rides on a sky-blue primary — fast, airborne, legible
on both dark and light. The deep navy background is the natural pairing;
the dim tones are for muted type.</p>
<div class="swatches">
<div class="sw"><div class="block" style="background:#0b0e14"></div><div class="meta"><b>bg</b><code>#0b0e14</code> — primary surface</div></div>
<div class="sw"><div class="block" style="background:#141a24"></div><div class="meta"><b>panel</b><code>#141a24</code> — cards, sidebar</div></div>
<div class="sw"><div class="block" style="background:#38BDF8"></div><div class="meta"><b>sky</b><code>#38BDF8</code> — primary accent (mark)</div></div>
<div class="sw"><div class="block" style="background:#60A5FA"></div><div class="meta"><b>sky-soft</b><code>#60A5FA</code> — hover, secondary</div></div>
<div class="sw"><div class="block" style="background:#0EA5E9"></div><div class="meta"><b>sky-deep</b><code>#0EA5E9</code> — pressed / active</div></div>
<div class="sw"><div class="block" style="background:#e7eaf1"></div><div class="meta"><b>ink</b><code>#e7eaf1</code> — body text</div></div>
<div class="sw"><div class="block" style="background:#8b98a9"></div><div class="meta"><b>mut</b><code>#8b98a9</code> — muted text</div></div>
<div class="sw"><div class="block" style="background:#ffc75f"></div><div class="meta"><b>warn</b><code>#ffc75f</code> — warnings, unread accents</div></div>
</div>
<div class="note"><b>Alternate: Hermès-palette orange.</b> The brand file also
carries a warm orange variant (<code class="inline">#FF6D00</code>,
<code class="inline">#FF8C1A</code>, <code class="inline">#E65100</code>)
for third parties who prefer the Hermes-god colour association. Pick one
or the other — never both in the same build. Sky-mid is the default.</div>
</section>
<section>
<h2>Voice</h2>
<ul class="steps">
<li><b>Blunt about limits.</b>
<span>"Relays still see recipient and timing" is the tone, not "fully
anonymous messaging". Say what the design does and does not solve.</span></li>
<li><b>No evangelism about Nostr.</b>
<span>Nostr is the transport, not the product. Mention it where it
matters (relays, pubkeys, NIP-17) and don't elsewhere.</span></li>
<li><b>"Message by name" is the one-line pitch.</b>
<span>Everything else is supporting detail.</span></li>
<li><b>Lowercase for product nouns in body copy.</b>
<span>hermes.x, messenger, panel. Capital Hermes for titles and the first
mention per page.</span></li>
</ul>
</section>
<section>
<h2>Attribution + reuse</h2>
<p>Mark + palette are MPL-2.0 along with the rest of the Hermes client source.
Use for reviews, press, interoperability docs and the client's own chrome.
Don't apply to products that aren't actually Hermes (forks with different
protocols or trust models included).</p>
</section>
</div>
<footer>
<div>hermes.x — a <a href="https://silentmode.st/">Silent Mode</a> project.</div>
<div class="fine">Named for the messenger of the gods. Ermis in modern Greek. Spelled Hermes in English.</div>
</footer>
</body>
</html>

173
index.html Normal file
View file

@ -0,0 +1,173 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hermes.x — message anyone by their .bch name</title>
<meta name="description" content="Hermes: end-to-end encrypted messaging where your Bitcoin Cash name is your identity. NIP-17 sealed DMs over Nostr. No email, no phone number, no company account.">
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="assets/favicon.svg" color="#38BDF8">
<meta property="og:type" content="website">
<meta property="og:site_name" content="hermes.x">
<meta property="og:title" content="hermes.x — message anyone by their .bch name">
<meta property="og:description" content="End-to-end encrypted DMs over Nostr, addressed by your .bch name. No email, no phone, no server that can delete your account.">
<meta property="og:url" content="https://hermes.x/">
<meta property="og:image" content="https://hermes.x/assets/mark.svg">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="hermes.x — message anyone by their .bch name">
<meta name="twitter:description" content="Sealed-sender DMs over Nostr, addressed by .bch name.">
<link rel="stylesheet" href="assets/shared.css">
</head>
<body>
<nav class="topnav">
<a class="brand" href="./">
<svg viewBox="0 0 64 64" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 36 L4 36"/></g></svg>
hermes<span class="x">.x</span>
</a>
<a href="./" class="here">Overview</a>
<a href="messenger/">Messenger</a>
<a href="branding/">Branding</a>
<a href="https://theseus.x/" class="get">Get Theseus</a>
</nav>
<header class="hero">
<div class="mark" aria-hidden="true">
<svg viewBox="0 0 64 64"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg>
</div>
<h1>Message by name<span class="x">.</span></h1>
<p class="tag">End-to-end encrypted DMs over Nostr, addressed by your
<code class="inline">.bch</code> name instead of a public-key string.
Your name owns your key. No email, no phone number, no company, no server
that can delete your account.</p>
<div class="cta">
<a class="btn primary" href="messenger/">Open Messenger</a>
<a class="btn ghost" href="https://theseus.x/">Get Theseus (desktop)</a>
</div>
</header>
<div class="wrap narrow">
<section class="plain">
<h2>What ships today</h2>
<p class="lede">Hermes is live inside the Theseus desktop browser. Web
messenger and Android follow.</p>
<div class="grid">
<div class="card">
<h3>Threaded chat <span class="src ok">live</span></h3>
<p>Contact list on the left (search + unread badges), selected
conversation on the right, inline reply. Enter to send.</p>
</div>
<div class="card">
<h3>Send by name <span class="src ok">live</span></h3>
<p>Type <code class="inline">alice.bch</code>. The client resolves the
name on-chain, wraps NIP-17 to the recipient's Nostr key, publishes
to their declared relays. Sealed-sender — the relay never sees who
sent what to whom.</p>
</div>
<div class="card">
<h3>Address book <span class="src ok">live</span></h3>
<p>Local contact list — add names, nicknames, import vCards. Nothing
uploaded; the book is on your device.</p>
</div>
<div class="card">
<h3>History on your device <span class="src ok">live</span></h3>
<p>Messages persist to disk per identity. Close and reopen the panel —
your threads are still there, unread marks included.</p>
</div>
<div class="card">
<h3>Web Messenger <span class="src next">next</span></h3>
<p><a href="messenger/">hermes.x/messenger</a> — browser-side messenger
for anyone without the desktop app. Same crypto, same identity.</p>
</div>
<div class="card">
<h3>Mobile (Ariadne) <span class="src plan">planned</span></h3>
<p>Inside the Ariadne Android app: same wallet seed, same Nostr identity,
zero extra onboarding.</p>
</div>
</div>
</section>
<section>
<h2>The one idea that makes this different</h2>
<p class="lede">Every existing Nostr client has the same wart: identity is
<code class="inline">npub1q8s7f3k…</code> gibberish. The human-name fix —
NIP-05 — resolves <code class="inline">alice@example.com</code> through a
DNS domain and a web server. That is exactly the ICANN + server chain
Bitcoin Cash names exist to escape.</p>
<div class="note">
<b>The Hermes pitch.</b><br>
<code class="inline">alice.bch</code> publishes her Nostr pubkey as an
on-chain record. Her name certificate <i>is</i> her verified,
seizure-resistant identity. Message anyone by their
<code class="inline">.bch</code> name — no phone number, no email, no ICANN,
no company, no server that can delete your account.
</div>
</section>
<section>
<h2>How it works</h2>
<ol class="steps">
<li><b>Your name owns your key.</b>
<span>Register any name on the chain, publish your Nostr pubkey as an
<code class="inline">np</code> record. The key is derived from the
same wallet seed as the name, so one seed backs both.</span></li>
<li><b>Find people by name.</b>
<span>Type <code class="inline">bob.bch</code>. The client resolves
it against the chain, pulls <code class="inline">np</code>
(Nostr pubkey) and <code class="inline">nr</code> (preferred relays).
No directory server involved.</span></li>
<li><b>Send the message sealed.</b>
<span>NIP-17 gift-wrapped DMs — the relay sees neither sender nor
content, only that a wrap addressed to some pubkey exists. Route over
Tor to also hide your IP.</span></li>
<li><b>The name shows, not the pubkey.</b>
<span>Incoming messages reverse-resolve pubkey → name where possible,
so your chat list looks like a normal chat list — not a wall of hex.</span></li>
</ol>
</section>
<section>
<h2>Honest boundaries</h2>
<div class="grid">
<div class="card">
<h3>Messaging, not email</h3>
<p>No Gmail interop — by design. A separate anonymous-mailbox product
covers "sign up on services without leaking a real address".</p>
</div>
<div class="card">
<h3>Metadata resistance is good, not perfect</h3>
<p>NIP-17 hides sender and content from relays. Relays still see the
recipient pubkey, timing, and your connection IP unless you route
over Tor.</p>
</div>
<div class="card">
<h3>Relays are Nostr's soft spot</h3>
<p>A message lives only while some relay keeps it. We run one relay +
write to a handful of public relays for reach and redundancy.</p>
</div>
</div>
</section>
<section class="plain" style="text-align:center">
<h2>Try it</h2>
<p class="lede" style="margin-left:auto;margin-right:auto">
Open the web messenger right here, or install Theseus for the full
experience (persistent history, sidebar entry, keyboard shortcut).</p>
<div class="cta">
<a class="btn primary" href="messenger/">Open Messenger</a>
<a class="btn ghost" href="https://theseus.x/">Get Theseus</a>
<a class="btn ghost" href="branding/">Brand kit</a>
</div>
</section>
</div>
<footer>
<div>hermes.x — a <a href="https://silentmode.st/">Silent Mode</a> project.</div>
<div class="fine">Named for the messenger of the gods. Ermis in modern Greek.
Not Hermès (no accent, no horse, no orange luggage).</div>
</footer>
</body>
</html>

242
messenger/index.html Normal file
View file

@ -0,0 +1,242 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hermes.x/messenger — browser messenger (preview)</title>
<meta name="description" content="The web version of Hermes: encrypted DMs over Nostr, addressed by .bch name, running in your browser. Preview of the UI; functional release pending.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="../assets/shared.css">
<style>
/* ---- status banner ---- */
.status-banner{
background:rgba(255,199,95,.08);
border:1px solid rgba(255,199,95,.26);
border-radius:12px;
padding:14px 18px;
margin:1.5rem auto;
max-width:780px;
font-size:14px;
color:var(--ink);
display:flex;gap:14px;align-items:flex-start;
}
.status-banner .dot{
width:10px;height:10px;border-radius:50%;background:var(--warn);
margin-top:6px;flex-shrink:0;animation:pulse 2s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity:.4 } }
.status-banner b{color:var(--warn)}
/* ---- mockup frame ---- */
.mockup{
background:var(--panel);border:1px solid var(--line2);border-radius:16px;
overflow:hidden;margin:1.5rem auto;max-width:860px;
box-shadow:0 20px 60px rgba(0,0,0,.4);
}
.mockup .window-bar{
display:flex;align-items:center;gap:8px;padding:10px 14px;
background:var(--panel2);border-bottom:1px solid var(--line);
}
.mockup .window-bar .dot{width:11px;height:11px;border-radius:50%;background:#444a56}
.mockup .window-bar .dot:nth-child(1){background:#ff5f57}
.mockup .window-bar .dot:nth-child(2){background:#febc2e}
.mockup .window-bar .dot:nth-child(3){background:#28c840}
.mockup .window-bar .title{color:var(--mut);font-size:12px;margin-left:10px}
.mockup .window-bar .status{margin-left:auto;font-size:11px;color:var(--ok);padding:2px 10px;border-radius:999px;background:rgba(79,209,165,.14)}
.mockup .window-bar .npub{color:var(--mut);font-size:11px;font-family:ui-monospace,monospace;margin-left:12px}
.mockup .npub b{color:var(--sky)}
.mockup .app{display:grid;grid-template-columns:220px 1fr;min-height:420px}
.mockup .side{background:var(--panel2);border-right:1px solid var(--line);display:flex;flex-direction:column}
.mockup .side-head{padding:10px;display:flex;gap:6px;border-bottom:1px solid var(--line)}
.mockup .side-head input{flex:1;background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:6px 10px;color:var(--mut);font-size:12px}
.mockup .side-head button{background:var(--sky);color:#06111a;border:none;border-radius:6px;padding:6px 10px;font-weight:600;cursor:pointer;font-size:13px}
.mockup .contact{display:flex;gap:10px;align-items:center;padding:9px 12px;border-bottom:1px solid rgba(255,255,255,.03);cursor:pointer}
.mockup .contact.active{background:var(--panel3)}
.mockup .contact .avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#2a3a4a,#1a2432);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--mut);font-weight:600;text-transform:uppercase}
.mockup .contact .meta{flex:1;min-width:0}
.mockup .contact .name{font-size:12.5px;color:var(--ink);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mockup .contact .last{font-size:11px;color:var(--mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mockup .contact .badge{background:var(--sky);color:#06111a;font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px}
.mockup .thread{display:flex;flex-direction:column;background:var(--bg)}
.mockup .thread-head{padding:12px 16px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:12px}
.mockup .thread-head .name{font-weight:600;font-size:13px}
.mockup .thread-head .pk{font-family:ui-monospace,monospace;font-size:10.5px;color:var(--mut)}
.mockup .thread-body{flex:1;padding:14px 16px;display:flex;flex-direction:column;gap:6px}
.mockup .bubble{max-width:70%;padding:7px 11px;border-radius:14px;font-size:13px;line-height:1.4}
.mockup .bubble.in{background:#1d2634;align-self:flex-start;border-bottom-left-radius:4px}
.mockup .bubble.out{background:#0d2a3a;align-self:flex-end;border-bottom-right-radius:4px;color:#d9ecfa}
.mockup .bubble .time{display:block;font-size:10px;color:var(--dim);margin-top:3px}
.mockup .compose{display:flex;gap:8px;padding:10px 14px;border-top:1px solid var(--line);background:var(--panel)}
.mockup .compose input{flex:1;background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:9px 11px;color:var(--mut);font-size:13px}
.mockup .compose button{background:var(--sky);color:#06111a;border:none;padding:0 18px;border-radius:8px;font-weight:600;cursor:pointer}
.plan-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:700px){.plan-grid{grid-template-columns:1fr}}
.plan{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px}
.plan h3{display:flex;align-items:center;gap:8px}
.plan ul{margin:.5rem 0 0;padding:0 0 0 1.2rem;color:var(--mut);font-size:14px;line-height:1.7}
.mockup-caption{text-align:center;color:var(--dim);font-size:12px;margin-top:-.5rem;margin-bottom:1.5rem}
</style>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">
<svg viewBox="0 0 64 64" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 36 L4 36"/></g></svg>
hermes<span class="x">.x</span>
</a>
<a href="../">Overview</a>
<a href="./" class="here">Messenger</a>
<a href="../branding/">Branding</a>
<a href="https://theseus.x/" class="get">Get Theseus</a>
</nav>
<header class="hero">
<div class="mark" style="color:var(--sky); line-height:0; display:inline-flex" aria-hidden="true">
<svg viewBox="0 0 64 64" width="96" height="96"><g fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" transform="rotate(-22 32 32)"><rect x="20" y="26" width="30" height="18" rx="1.5"/><path d="M20 27 L35 37 L50 27"/><path d="M20 30 L2 30"/><path d="M20 36 L10 36"/><path d="M20 42 L14 42"/></g></svg>
</div>
<h1>Messenger</h1>
<p class="tag">Hermes in a browser tab — end-to-end encrypted DMs over Nostr,
addressed by <code class="inline">.bch</code> name. The desktop client has
the richest flavour; the web messenger meets you where you are.</p>
</header>
<div class="status-banner">
<div class="dot"></div>
<div>
<b>Preview.</b> The desktop messenger inside <a href="https://theseus.x/">Theseus</a>
is live today — threaded chat, persistent history, address book, keyboard
shortcut <code class="inline">Ctrl+Shift+E</code>. The web-only client
(what this page becomes) is in development: BIP-39 → Nostr key derivation,
BCH-name resolution via gateway, NIP-17 wrap/unwrap, WebSocket to relays,
IndexedDB inbox. Everything client-side, nothing uploaded.
</div>
</div>
<div class="mockup" aria-label="Messenger UI preview">
<div class="window-bar">
<div class="dot"></div><div class="dot"></div><div class="dot"></div>
<div class="title">Hermes · hermes.x/messenger</div>
<span class="npub">your npub: <b>npub1ab…z89</b></span>
<span class="status">1/1 relay</span>
</div>
<div class="app">
<aside class="side">
<div class="side-head"><input value="Search contacts…" readonly><button>+</button></div>
<div class="contact">
<div class="avatar">AL</div>
<div class="meta"><div class="name">alice</div><div class="last">you: see you tomorrow</div></div>
</div>
<div class="contact active">
<div class="avatar">BO</div>
<div class="meta"><div class="name">bob</div><div class="last">great, send me the link</div></div>
<div class="badge">2</div>
</div>
<div class="contact">
<div class="avatar">TE</div>
<div class="meta"><div class="name">test</div><div class="last">chipnet is working</div></div>
</div>
</aside>
<section class="thread">
<div class="thread-head">
<div>
<div class="name">bob</div>
<div class="pk">023bf8c1…9ad2</div>
</div>
</div>
<div class="thread-body">
<div class="bubble in">hey, did you register your name yet?<span class="time">11:38</span></div>
<div class="bubble out">just now — bob.bch is live<span class="time">11:40</span></div>
<div class="bubble in">nice. send me the hermes.x link<span class="time">11:42</span></div>
<div class="bubble out">https://hermes.x/messenger<span class="time">11:43</span></div>
<div class="bubble in">great, send me the link<span class="time">11:44</span></div>
</div>
<div class="compose">
<input value="Message…" readonly>
<button>Send</button>
</div>
</section>
</div>
</div>
<div class="mockup-caption">Non-interactive preview — live build pending (see roadmap below).</div>
<div class="wrap narrow">
<section>
<h2>Two clients, one identity</h2>
<div class="plan-grid">
<div class="plan">
<h3>Desktop (Theseus) <span class="src ok">live</span></h3>
<ul>
<li>Full crypto in-process (NIP-17, nip44 v2)</li>
<li>Persistent inbox + read-state on disk</li>
<li>Address book (local JSON + vCard import)</li>
<li>Sidebar panel, Ctrl+Shift+E shortcut</li>
<li>Vault-bind: no re-typing the mnemonic</li>
<li>Reverse-resolve pk → .bch name</li>
</ul>
<div class="cta" style="justify-content:flex-start;margin-top:1.2rem">
<a class="btn primary" href="https://theseus.x/">Get Theseus</a>
</div>
</div>
<div class="plan">
<h3>Web (this page) <span class="src next">building</span></h3>
<ul>
<li>Same crypto, same identity (same wallet seed derivation)</li>
<li>BCH name resolution via public gateway</li>
<li>WebSocket to Nostr relays from the browser</li>
<li>IndexedDB inbox — survives tab close, scoped to this origin</li>
<li>No download, no install, no account</li>
<li>Mnemonic entry only — never stored in plaintext</li>
</ul>
<div class="cta" style="justify-content:flex-start;margin-top:1.2rem">
<a class="btn ghost" href="../">Why Hermes</a>
</div>
</div>
</div>
</section>
<section>
<h2>Why wait for the web client</h2>
<p class="lede">The web messenger isn't ready yet because of three things we
want to get right before shipping:</p>
<ol class="steps">
<li><b>Key handling in a tab.</b>
<span>A wallet mnemonic is the most sensitive bit of data a user has. In
the desktop app it lives in main-process memory; in a tab it has to
survive page reloads without ever landing in plaintext anywhere. We're
wiring a WebCrypto-backed non-extractable key path with the vault PIN
as the gate.</span></li>
<li><b>Resolver gateway.</b>
<span>The desktop talks to a chipnet Fulcrum directly. A browser can't
— it needs an HTTPS gateway that answers <code class="inline">np</code>
/ <code class="inline">nr</code> for a name. The gateway is live
(<code class="inline">navigate.st/api/dns/alice.bch</code>) but the
client-side cache + signature-verification path still has an edge case
with lapsed names.</span></li>
<li><b>Relay persistence.</b>
<span>Desktop keeps a long-lived WebSocket to each relay. A tab doesn't,
because browsers throttle background sockets. The web client needs
offline queueing and a well-defined "catch-up" fetch on return —
otherwise you re-open the tab and the inbox feels empty.</span></li>
</ol>
<p>Until the three are solid, <b>install Theseus</b> for the real thing.
The web client will land here when the above are green.</p>
<div class="cta">
<a class="btn primary" href="https://theseus.x/">Get Theseus</a>
<a class="btn ghost" href="../branding/">Brand kit</a>
</div>
</section>
</div>
<footer>
<div>hermes.x — a <a href="https://silentmode.st/">Silent Mode</a> project.</div>
<div class="fine">Preview only. The functional web client is being built.</div>
</footer>
</body>
</html>