From 84e45b5c402c2d309a3e0f7a12749652e76f359c Mon Sep 17 00:00:00 2001
From: teknium1
Date: Mon, 2 Mar 2026 22:03:43 -0800
Subject: [PATCH] feat: tabbed platform installer on landing page
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add an interactive OS selector widget to the hero section and install
steps, inspired by OpenClaw's install UI:
- macOS-style window chrome with red/yellow/green dots
- Three clickable tabs: Linux/macOS, PowerShell, CMD
- Command text, shell prompt, and note update on tab click
- Auto-detects visitor's OS and selects the right tab on page load
- Install steps section also gets synced platform tabs
- Simplified Windows note section (tabs above now cover all platforms)
- Fully responsive — icons hidden on mobile, tabs wrap properly
---
landingpage/index.html | 59 +++++++++++------
landingpage/script.js | 74 ++++++++++++++++++++-
landingpage/style.css | 141 +++++++++++++++++++++++++++++++++++++----
3 files changed, 242 insertions(+), 32 deletions(-)
diff --git a/landingpage/index.html b/landingpage/index.html
index bc1aa859e..2d1f99972 100644
--- a/landingpage/index.html
+++ b/landingpage/index.html
@@ -69,14 +69,38 @@
-
-
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
-
+
-
Works on Linux & macOS · No Python prerequisite · Installs everything automatically
+
Works on Linux, macOS & WSL · No prerequisites · Installs everything automatically
@@ -330,12 +354,16 @@
Install
-
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
+
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
-
Installs uv, Python 3.11, clones the repo, sets up everything. No sudo needed.
+
Installs uv, Python 3.11, clones the repo, sets up everything. No sudo needed.
@@ -394,14 +422,7 @@ hermes gateway install
-
Windows? Use WSL or PowerShell:
-
-
-
irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex
-
+
🪟 Windows requires Git for Windows — Hermes uses Git Bash internally for shell commands.
diff --git a/landingpage/script.js b/landingpage/script.js
index 6f1c6c105..422ba3bea 100644
--- a/landingpage/script.js
+++ b/landingpage/script.js
@@ -2,11 +2,79 @@
// Hermes Agent Landing Page — Interactions
// =========================================================================
+// --- Platform install commands ---
+const PLATFORMS = {
+ linux: {
+ command: 'curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash',
+ prompt: '$',
+ note: 'Works on Linux, macOS & WSL · No prerequisites · Installs everything automatically',
+ stepNote: 'Installs uv, Python 3.11, clones the repo, sets up everything. No sudo needed.',
+ },
+ powershell: {
+ command: 'irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex',
+ prompt: 'PS>',
+ note: 'Windows PowerShell · Requires Git for Windows · Installs everything automatically',
+ stepNote: 'Requires Git for Windows. Installs uv, Python 3.11, sets up everything.',
+ },
+ cmd: {
+ command: 'curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.cmd -o install.cmd && install.cmd && del install.cmd',
+ prompt: '>',
+ note: 'Windows CMD · Requires Git for Windows · Installs everything automatically',
+ stepNote: 'Requires Git for Windows. Downloads and runs the installer, then cleans up.',
+ },
+};
+
+function detectPlatform() {
+ const ua = navigator.userAgent.toLowerCase();
+ if (ua.includes('win')) return 'powershell';
+ return 'linux';
+}
+
+function switchPlatform(platform) {
+ const cfg = PLATFORMS[platform];
+ if (!cfg) return;
+
+ // Update hero install widget
+ const commandEl = document.getElementById('install-command');
+ const promptEl = document.getElementById('install-prompt');
+ const noteEl = document.getElementById('install-note');
+
+ if (commandEl) commandEl.textContent = cfg.command;
+ if (promptEl) promptEl.textContent = cfg.prompt;
+ if (noteEl) noteEl.textContent = cfg.note;
+
+ // Update active tab in hero
+ document.querySelectorAll('.install-tab').forEach(tab => {
+ tab.classList.toggle('active', tab.dataset.platform === platform);
+ });
+
+ // Sync the step section tabs too
+ switchStepPlatform(platform);
+}
+
+function switchStepPlatform(platform) {
+ const cfg = PLATFORMS[platform];
+ if (!cfg) return;
+
+ const commandEl = document.getElementById('step1-command');
+ const copyBtn = document.getElementById('step1-copy');
+ const noteEl = document.getElementById('step1-note');
+
+ if (commandEl) commandEl.textContent = cfg.command;
+ if (copyBtn) copyBtn.setAttribute('data-text', cfg.command);
+ if (noteEl) noteEl.textContent = cfg.stepNote;
+
+ // Update active tab in step section
+ document.querySelectorAll('.code-tab').forEach(tab => {
+ tab.classList.toggle('active', tab.dataset.platform === platform);
+ });
+}
+
// --- Copy to clipboard ---
function copyInstall() {
const text = document.getElementById('install-command').textContent;
navigator.clipboard.writeText(text).then(() => {
- const btn = document.querySelector('.hero-install .copy-btn');
+ const btn = document.querySelector('.install-widget-body .copy-btn');
const original = btn.querySelector('.copy-text').textContent;
btn.querySelector('.copy-text').textContent = 'Copied!';
btn.style.color = 'var(--gold)';
@@ -243,6 +311,10 @@ class TerminalDemo {
// --- Initialize ---
document.addEventListener('DOMContentLoaded', () => {
+ // Auto-detect platform and set the right install command
+ const detectedPlatform = detectPlatform();
+ switchPlatform(detectedPlatform);
+
initScrollAnimations();
// Terminal demo - start when visible
diff --git a/landingpage/style.css b/landingpage/style.css
index f75057d62..cf05a7a8b 100644
--- a/landingpage/style.css
+++ b/landingpage/style.css
@@ -245,33 +245,132 @@ strong {
margin-bottom: 32px;
}
-.install-box {
- display: flex;
- align-items: center;
- gap: 0;
+/* --- Install Widget (hero tabbed installer) --- */
+.install-widget {
+ max-width: 740px;
+ margin: 0 auto;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
+ overflow: hidden;
+ transition: border-color 0.3s;
+}
+
+.install-widget:hover {
+ border-color: var(--border-hover);
+}
+
+.install-widget-header {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ padding: 10px 16px;
+ background: rgba(255, 255, 255, 0.02);
+ border-bottom: 1px solid var(--border);
+}
+
+.install-dots {
+ display: flex;
+ gap: 6px;
+ flex-shrink: 0;
+}
+
+.install-dots .dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+}
+
+.install-tabs {
+ display: flex;
+ gap: 4px;
+ flex-wrap: wrap;
+}
+
+.install-tab {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 5px 14px;
+ border: none;
+ border-radius: 6px;
+ font-family: var(--font-sans);
+ font-size: 12px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s;
+ background: transparent;
+ color: var(--text-muted);
+}
+
+.install-tab:hover {
+ color: var(--text-dim);
+ background: rgba(255, 255, 255, 0.04);
+}
+
+.install-tab.active {
+ background: rgba(255, 215, 0, 0.12);
+ color: var(--gold);
+}
+
+.install-tab svg {
+ flex-shrink: 0;
+}
+
+.install-widget-body {
+ display: flex;
+ align-items: center;
+ gap: 10px;
padding: 14px 16px;
- max-width: 680px;
- margin: 0 auto;
font-family: var(--font-mono);
font-size: 13px;
color: var(--text);
overflow-x: auto;
- transition: border-color 0.3s;
}
-.install-box:hover {
- border-color: var(--border-hover);
+.install-prompt {
+ color: var(--gold);
+ font-weight: 600;
+ flex-shrink: 0;
+ opacity: 0.7;
}
-.install-box code {
+.install-widget-body code {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
+ transition: opacity 0.15s;
+}
+
+/* --- Code block tabs (install step section) --- */
+.code-tabs {
+ display: flex;
+ gap: 2px;
+}
+
+.code-tab {
+ padding: 3px 10px;
+ border: none;
+ border-radius: 4px;
+ font-family: var(--font-mono);
+ font-size: 11px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s;
+ background: transparent;
+ color: var(--text-muted);
+}
+
+.code-tab:hover {
+ color: var(--text-dim);
+ background: rgba(255, 255, 255, 0.04);
+}
+
+.code-tab.active {
+ background: rgba(255, 215, 0, 0.1);
+ color: var(--gold);
}
.copy-btn {
@@ -948,17 +1047,35 @@ strong {
margin: 0 auto 28px;
}
- .install-box {
+ .install-widget-body {
font-size: 10px;
padding: 10px 12px;
}
- .install-box code {
+ .install-widget-body code {
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
+ .install-widget-header {
+ padding: 8px 12px;
+ gap: 10px;
+ }
+
+ .install-tabs {
+ gap: 2px;
+ }
+
+ .install-tab {
+ padding: 4px 10px;
+ font-size: 11px;
+ }
+
+ .install-tab svg {
+ display: none;
+ }
+
.copy-btn {
padding: 3px 6px;
}