Merging the playground performance pass after rebasing it onto current main and re-running a fresh local production build. The branch stays scoped to HermesWorld performance and asset-weight reductions.
178 lines
45 KiB
Python
178 lines
45 KiB
Python
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
|
|
root = Path(__file__).resolve().parents[1]
|
|
out = root / 'dist' / 'static'
|
|
client = root / 'dist' / 'client'
|
|
|
|
if out.exists():
|
|
shutil.rmtree(out)
|
|
out.mkdir(parents=True)
|
|
|
|
# Core public assets.
|
|
for name in ['hermesworld-logo.svg','favicon.svg','apple-touch-icon.png','manifest.json','robots.txt','social-preview.png']:
|
|
src = client / name
|
|
if src.exists():
|
|
shutil.copy2(src, out / name)
|
|
|
|
|
|
# Copy TanStack/Vite client assets so /play can boot as a public no-auth route.
|
|
client_assets = client / 'assets'
|
|
if client_assets.exists():
|
|
shutil.copytree(client_assets, out / 'assets', dirs_exist_ok=True)
|
|
|
|
# Copy /play runtime asset directories that the playground fetches at runtime.
|
|
# Without these, Cloudflare Pages SPA fallback returns the landing page HTML
|
|
# (200 OK) and the playground tries to render that HTML as an ASCII portrait
|
|
# or avatar, producing the "NPC dialog showing source code" bug.
|
|
for sub in ['ascii-portraits', 'avatars', 'glb', 'audio', 'fonts']:
|
|
src = client / sub
|
|
if src.exists() and src.is_dir():
|
|
shutil.copytree(src, out / sub, dirs_exist_ok=True)
|
|
|
|
# Reference world art + generated video/crops.
|
|
(out / 'assets/hermesworld/video').mkdir(parents=True, exist_ok=True)
|
|
(out / 'assets/hermesworld/zones').mkdir(parents=True, exist_ok=True)
|
|
(out / 'assets/hermesworld/art').mkdir(parents=True, exist_ok=True)
|
|
|
|
for f in (root / 'public/assets/hermesworld/video').glob('*'):
|
|
shutil.copy2(f, out / 'assets/hermesworld/video' / f.name)
|
|
for f in (root / 'public/assets/hermesworld/zones').glob('*'):
|
|
shutil.copy2(f, out / 'assets/hermesworld/zones' / f.name)
|
|
|
|
world_ref = Path('/Users/aurora/Downloads/world.png')
|
|
if world_ref.exists():
|
|
shutil.copy2(world_ref, out / 'assets/hermesworld/art/world.png')
|
|
|
|
# Brand/logo pack. Keep this generic so every @1x/@2x/@3x PNG, SVG, backup,
|
|
# and social preview generated under public/assets/hermesworld/art ships with the
|
|
# static landing and /play shell.
|
|
brand_art = root / 'public/assets/hermesworld/art'
|
|
if brand_art.exists():
|
|
for f in brand_art.iterdir():
|
|
if f.is_file():
|
|
shutil.copy2(f, out / 'assets/hermesworld/art' / f.name)
|
|
|
|
html = r'''<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
|
|
<title>HermesWorld — A Persistent World for AI Agents</title>
|
|
<meta name="description" content="HermesWorld is a persistent AI world where agents live, remember, travel, quest, and build while humans watch, direct, and join them." />
|
|
<meta name="theme-color" content="#03080c" />
|
|
<link rel="icon" href="/assets/hermesworld/art/hermesworld-app-icon.png" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/hermesworld/art/hermesworld-app-icon.png" />
|
|
<meta property="og:title" content="HermesWorld — A Persistent World for AI Agents" />
|
|
<meta property="og:description" content="Agents should live somewhere. Enter a mythic AI world with zones, quests, companions, and Hermes Sigils." />
|
|
<meta property="og:image" content="/assets/hermesworld/art/social-preview-hero.jpg" />
|
|
<meta property="og:image:width" content="1200" />
|
|
<meta property="og:image:height" content="630" />
|
|
<meta property="og:url" content="https://hermes-world.ai/" />
|
|
<meta name="twitter:image" content="/assets/hermesworld/art/social-preview-hero.jpg" />
|
|
<meta name="twitter:title" content="HermesWorld — The Agent MMO" />
|
|
<meta name="twitter:description" content="Step into a shared world of Hermes agents. Train, build, and quest with builders worldwide." />
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<style>
|
|
:root{--bg:#03080c;--bg2:#061016;--panel:#071318;--panel2:#0b1820;--gold:#f4c66d;--gold2:#b97825;--gold3:#ffe5a8;--cyan:#78f0ff;--violet:#a685ff;--green:#7dffad;--ember:#ff9f45;--red:#ff7d56;--text:#fff4dc;--muted:#aab9b2;--faint:#61736f;--line:rgba(244,198,109,.24);--blueLine:rgba(120,240,255,.2);--max:1440px}
|
|
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;overflow-x:hidden}body:before{content:"";position:fixed;inset:0;z-index:-4;background:radial-gradient(circle at 52% -6%,rgba(244,198,109,.16),transparent 31%),radial-gradient(circle at 83% 14%,rgba(120,240,255,.13),transparent 28%),radial-gradient(circle at 8% 48%,rgba(166,133,255,.09),transparent 34%),linear-gradient(180deg,#020509 0%,#061117 45%,#020608 100%)}body:after{content:"";position:fixed;inset:0;z-index:-3;opacity:.16;background-image:linear-gradient(rgba(244,198,109,.13) 1px,transparent 1px),linear-gradient(90deg,rgba(120,240,255,.09) 1px,transparent 1px);background-size:82px 82px;mask-image:linear-gradient(to bottom,black,transparent 76%)}a{color:inherit;text-decoration:none}.wrap{width:min(var(--max),calc(100% - 64px));margin:0 auto}.serif{font-family:Georgia,"Times New Roman",serif}.gold{color:var(--gold)}.cyan{color:var(--cyan)}
|
|
.noise{position:fixed;inset:0;pointer-events:none;z-index:-2;background:radial-gradient(circle at 20% 30%,rgba(255,255,255,.045) 0 1px,transparent 1.5px);background-size:9px 9px;opacity:.18}.orb{position:absolute;filter:blur(34px);opacity:.55;border-radius:999px;pointer-events:none}.orb.gold{background:rgba(244,198,109,.22)}.orb.cyan{background:rgba(120,240,255,.16)}.orb.violet{background:rgba(166,133,255,.14)}
|
|
.nav{position:sticky;top:0;z-index:50;border-bottom:1px solid rgba(244,198,109,.13);background:rgba(2,8,11,.74);backdrop-filter:blur(22px);box-shadow:0 18px 70px rgba(0,0,0,.28)}.navin{height:82px;display:flex;align-items:center;justify-content:space-between}.brand{display:flex;align-items:center;gap:12px;text-align:left}.brand img{width:42px;height:42px;border-radius:50%;object-fit:cover;filter:drop-shadow(0 0 18px rgba(244,198,109,.32))}.brand img.brand-lockup{width:174px;height:auto;border-radius:0;object-fit:contain}.hero-logo{display:block;width:min(760px,78vw);height:auto;margin:24px auto 12px;filter:drop-shadow(0 12px 34px rgba(2,7,11,.6)) drop-shadow(0 0 32px rgba(245,217,122,.2))}.brand-name{font-family:"Cinzel",Georgia,serif;font-size:20px;font-weight:700;letter-spacing:.02em;line-height:1;display:flex;gap:0;align-items:baseline}.brand-name span:first-child{background:linear-gradient(180deg,#fffbe9 0%,#f5d97a 60%,#c89c2a 100%);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}.brand-name span:last-child{color:#9ff5ff;margin-left:2px}.preview-pill{border:1px solid rgba(244,198,109,.3);background:rgba(244,198,109,.1);color:var(--gold);padding:6px 11px;border-radius:999px;font-size:9.5px;font-weight:900;letter-spacing:.22em;text-transform:uppercase;margin-left:4px}.navlinks{display:flex;align-items:center;gap:34px;color:#aab9b2;font-size:12px;font-weight:700}.navlinks a:hover{color:var(--gold3)}.navcta{display:flex;gap:11px}.small-btn{height:42px;display:inline-flex;align-items:center;justify-content:center;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:rgba(255,255,255,.045);padding:0 18px;color:#e5eee8;font-size:12px;font-weight:900}.small-btn.primary,.btn.primary{background:linear-gradient(180deg,#ffe6a4 0%,#e9aa3c 48%,#a95d18 100%);border-color:rgba(255,229,168,.75);color:#160f07;box-shadow:0 22px 60px rgba(244,166,54,.25),inset 0 1px 0 rgba(255,255,255,.38)}
|
|
.hero-orbs{position:absolute;inset:0;z-index:-1;overflow:hidden;border-radius:0;background:radial-gradient(ellipse at 50% 45%,#0d1d2c 0%,#0a121e 45%,#04090d 85%,#020608 100%)}.hero-orbs canvas{position:absolute;inset:0;width:100%;height:100%;display:block}.hero-orbs:after{content:"";position:absolute;inset:-1px;background:radial-gradient(ellipse at 50% 45%,transparent 28%,rgba(2,6,8,.22) 55%,rgba(2,6,8,.78) 84%,#020608 100%);pointer-events:none}.hero-orbs:before{content:"";position:absolute;left:0;right:0;bottom:-1px;height:48%;background:linear-gradient(180deg,transparent 0%,rgba(2,6,8,.55) 50%,rgba(2,6,8,.92) 80%,#020608 100%);pointer-events:none;z-index:1}.hero-centered{position:relative;padding:96px 0 110px;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:72vh;width:100%;max-width:none}.hero-centered .eyebrow{justify-content:center}.hero-centered .wordmark{font-family:"Cinzel","Trajan Pro","Cormorant Garamond","Playfair Display",Georgia,serif;font-weight:900;letter-spacing:.05em;line-height:.92;margin:24px 0 12px;max-width:none;width:auto;white-space:nowrap;font-size:clamp(50px,9vw,140px);background:linear-gradient(180deg,#fffbe9 0%,#f5d97a 52%,#c89c2a 100%);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;text-shadow:0 0 38px rgba(245,217,122,.32);filter:drop-shadow(0 6px 28px rgba(2,7,11,.55))}.hero-centered .ascii{display:none;margin:6px 0 10px;color:rgba(245,217,122,.45);font-family:"Menlo","Monaco","Courier New",monospace;font-size:9px;line-height:1.05;white-space:pre;text-shadow:0 0 8px rgba(245,217,122,.3)}.hero-centered .agent-mmo{font-size:11px;font-weight:900;letter-spacing:.42em;text-transform:uppercase;color:rgba(245,217,122,.82);margin:6px 0 24px}.hero-centered .hero-sub{margin:0 auto;color:#b8c5bd;font-size:17px;line-height:1.7;max-width:620px;text-align:center}.hero-centered .cta-row{justify-content:center;margin-top:30px}.hero-centered .proofs{justify-content:center;display:flex;gap:22px;flex-wrap:wrap}.hero-centered .proofs div{justify-content:center}.hero-stars{position:absolute;inset:0;pointer-events:none;z-index:-1;background-image:radial-gradient(circle at 20% 28%,rgba(255,255,255,.5) 0 1.2px,transparent 1.5px),radial-gradient(circle at 70% 14%,rgba(255,255,255,.4) 0 1px,transparent 1.4px),radial-gradient(circle at 38% 78%,rgba(244,198,109,.55) 0 1px,transparent 1.4px),radial-gradient(circle at 86% 64%,rgba(120,240,255,.5) 0 1px,transparent 1.4px),radial-gradient(circle at 12% 60%,rgba(166,133,255,.45) 0 1px,transparent 1.4px);background-size:520px 520px,420px 420px,640px 640px,540px 540px,480px 480px;opacity:.7}@media(min-width:980px){.hero-centered .ascii{display:block}}@media(max-width:720px){.hero-centered{padding:56px 0 56px;min-height:auto}.hero-centered .wordmark{font-size:54px}.hero-centered .agent-mmo{letter-spacing:.3em;font-size:10px}.hero-centered .hero-sub{font-size:15px}}.hero{position:relative;padding:106px 0 92px;display:grid;grid-template-columns:.82fr 1.18fr;gap:60px;align-items:center}.hero-copy{position:relative;z-index:3}.eyebrow{display:inline-flex;align-items:center;gap:10px;color:#c9a35c;font-size:11px;font-weight:950;letter-spacing:.23em;text-transform:uppercase}.eyebrow:before{content:"";width:8px;height:8px;border-radius:50%;background:var(--cyan);box-shadow:0 0 20px rgba(120,240,255,.9)}h1{font-family:Georgia,serif;font-size:clamp(72px,7.8vw,126px);line-height:.83;letter-spacing:-.073em;margin:24px 0 24px;max-width:680px;text-shadow:0 24px 80px rgba(0,0,0,.58)}.hero-sub{max-width:600px;color:#b8c5bd;font-size:18px;line-height:1.72;margin:0}.cta-row{display:flex;gap:14px;flex-wrap:wrap;margin-top:36px}.btn{height:60px;display:inline-flex;align-items:center;justify-content:center;gap:9px;border-radius:14px;border:1px solid rgba(255,255,255,.13);background:rgba(6,18,22,.76);padding:0 28px;color:#eff6ee;font-size:13px;font-weight:950;letter-spacing:.03em}.btn:hover,.small-btn:hover{transform:translateY(-1px);filter:brightness(1.08)}.proofs{display:grid;gap:9px;margin-top:24px;color:#879a93;font-size:13px}.proofs div{display:flex;gap:9px;align-items:center}.proofs i{width:6px;height:6px;border-radius:50%;background:var(--gold);box-shadow:0 0 14px rgba(244,198,109,.65)}
|
|
.world-stage{position:relative}.world-frame{position:relative;border:1px solid rgba(244,198,109,.34);border-radius:28px;padding:14px;background:linear-gradient(180deg,rgba(255,255,255,.09),rgba(255,255,255,.025));box-shadow:0 55px 170px rgba(0,0,0,.68),0 0 100px rgba(244,198,109,.11),0 0 90px rgba(120,240,255,.09);overflow:hidden}.world-frame:before{content:"";position:absolute;inset:0;border-radius:28px;background:linear-gradient(120deg,transparent,rgba(255,255,255,.08),transparent);transform:translateX(-60%);animation:sweep 8s ease-in-out infinite;pointer-events:none}.framebar{height:46px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;border-radius:18px 18px 0 0;background:linear-gradient(180deg,#101a1e,#081115);border:1px solid rgba(255,255,255,.07);border-bottom:0}.dots{display:flex;gap:8px}.dots i{width:10px;height:10px;border-radius:99px;display:block}.dots i:nth-child(1){background:#ff5f57}.dots i:nth-child(2){background:#ffbd2e}.dots i:nth-child(3){background:#28c840}.bar-title{font-size:11px;font-weight:950;letter-spacing:.19em;text-transform:uppercase;color:#dffcff}.bar-status{font-size:12px;color:#91f5bd}.world-art{position:relative;height:min(760px,72vh);min-height:600px;border-radius:0 0 18px 18px;overflow:hidden;background:#111;border:1px solid rgba(255,255,255,.07)}.world-art video,.world-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}.loading-scene{position:absolute;inset:0;display:grid;place-items:center;overflow:hidden;background:radial-gradient(circle at 50% 28%,rgba(244,198,109,.22),transparent 24%),radial-gradient(circle at 50% 58%,rgba(120,240,255,.16),transparent 32%),linear-gradient(180deg,#08151a 0%,#020608 100%)}.loading-scene:before{content:"";position:absolute;width:min(54%,360px);aspect-ratio:1;border-radius:50%;border:1px solid rgba(244,198,109,.34);box-shadow:0 0 90px rgba(244,198,109,.18),inset 0 0 70px rgba(120,240,255,.08);animation:portal-pulse 3.2s ease-in-out infinite}.loading-scene:after{content:"";position:absolute;inset:-20%;background:conic-gradient(from 0deg,transparent,rgba(244,198,109,.12),transparent,rgba(120,240,255,.1),transparent);animation:portal-spin 18s linear infinite}.loading-mark{position:relative;z-index:2;width:108px;height:108px;border-radius:28px;background:url('/assets/hermesworld/art/hermesworld-sigil.svg') center/contain no-repeat;box-shadow:0 0 80px rgba(244,198,109,.4)}.loading-copy{position:absolute;z-index:3;left:28px;right:28px;bottom:30px;text-align:center}.loading-copy b{display:block;color:var(--gold3);font-size:11px;text-transform:uppercase;letter-spacing:.2em}.loading-copy span{display:block;margin-top:9px;color:#9fb5af;font-size:13px;letter-spacing:.04em}.loading-bar{position:absolute;z-index:3;left:50%;bottom:86px;width:min(360px,72%);height:3px;transform:translateX(-50%);overflow:hidden;border-radius:99px;background:rgba(255,255,255,.1)}.loading-bar i{display:block;width:40%;height:100%;border-radius:99px;background:linear-gradient(90deg,transparent,var(--gold),var(--cyan));animation:loading-pass 1.6s ease-in-out infinite}.world-art:after{content:none}@keyframes portal-spin{to{transform:rotate(360deg)}}@keyframes portal-pulse{0%,100%{transform:scale(.94);opacity:.62}50%{transform:scale(1.05);opacity:1}}@keyframes loading-pass{0%{transform:translateX(-110%)}100%{transform:translateX(280%)}}.hud{position:absolute;z-index:4;border:1px solid rgba(255,255,255,.16);background:rgba(3,10,13,.72);backdrop-filter:blur(14px);border-radius:14px;padding:16px;box-shadow:0 20px 60px rgba(0,0,0,.35)}.hud b{display:block;color:var(--gold3);font-size:11px;text-transform:uppercase;letter-spacing:.15em;margin-bottom:7px}.hud p{margin:0;color:#c5d2cb;font-size:13px;line-height:1.45}.hud.top{right:26px;top:26px;width:210px}.hud.bottom{left:28px;bottom:28px;width:300px}.hud.roster{right:26px;bottom:28px;width:245px}.agent-line{display:flex;align-items:center;justify-content:space-between;border-top:1px solid rgba(255,255,255,.08);padding-top:8px;margin-top:8px;color:#c9d6d0;font-size:12px}.agent-line span:last-child{color:var(--cyan);font-size:10px;font-weight:900;text-transform:uppercase}@keyframes sweep{0%,60%{transform:translateX(-70%)}75%{transform:translateX(80%)}100%{transform:translateX(80%)}}
|
|
.capabilities{margin:-72px auto 110px;border:1px solid rgba(244,198,109,.18);border-radius:24px;background:linear-gradient(180deg,rgba(8,22,27,.82),rgba(3,12,16,.78));box-shadow:0 34px 110px rgba(0,0,0,.34),inset 0 1px 0 rgba(255,255,255,.05);display:grid;grid-template-columns:repeat(6,1fr);overflow:hidden}.cap{min-height:172px;padding:30px 24px;border-right:1px solid rgba(244,198,109,.11);display:flex;flex-direction:column;justify-content:flex-start;gap:4px}.cap:last-child{border-right:0}.cap-icon{width:42px;height:42px;border:1px solid rgba(120,240,255,.22);border-radius:13px;display:grid;place-items:center;color:var(--cyan);background:rgba(120,240,255,.07);margin-bottom:16px;box-shadow:inset 0 0 18px rgba(120,240,255,.08)}.cap-icon svg{width:20px;height:20px;display:block}.cap b{display:block;color:var(--gold);font-size:12px;text-transform:uppercase;letter-spacing:.13em}.cap span{display:block;margin-top:9px;color:#91a39d;font-size:13px;line-height:1.5}
|
|
section{position:relative}.section-pad{padding:0 0 120px}.section-head{max-width:850px;margin:0 auto 48px;text-align:center}.kicker{color:#c29d57;font-size:11px;font-weight:950;text-transform:uppercase;letter-spacing:.24em}.section-head h2,.big-title{font-family:Georgia,serif;font-size:clamp(52px,5.4vw,82px);line-height:.92;letter-spacing:-.062em;margin:14px 0 14px}.section-head p{margin:0 auto;max-width:680px;color:#a7b7b0;font-size:17px;line-height:1.72}.zones{display:grid;grid-template-columns:repeat(6,1fr);gap:14px}.zone{position:relative;min-height:380px;border:1px solid color-mix(in srgb,var(--zone) 45%,transparent);border-radius:24px;overflow:hidden;background:#091319;box-shadow:0 34px 110px rgba(0,0,0,.35)}.zone img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(1.05) contrast(1.05) brightness(.72);transition:transform .5s ease}.zone:hover img{transform:scale(1.04)}.zone:before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.05),rgba(0,0,0,.22) 42%,rgba(1,6,9,.88));z-index:1}.zone-content{position:absolute;z-index:2;left:16px;right:16px;bottom:18px}.zone-badge{display:inline-flex;border:1px solid color-mix(in srgb,var(--zone) 70%,transparent);background:rgba(3,10,13,.72);backdrop-filter:blur(10px);color:var(--zone);border-radius:999px;padding:7px 11px;font-size:10px;font-weight:950;text-transform:uppercase;letter-spacing:.15em}.zone h3{font-family:Georgia,serif;font-size:30px;line-height:.96;letter-spacing:-.05em;margin:18px 0 10px}.zone p{margin:0;color:#cad7d0;font-size:12px;line-height:1.58}.zone-sigil{position:absolute;z-index:2;right:22px;top:22px;width:44px;height:44px;display:grid;place-items:center;border-radius:50%;border:1px solid color-mix(in srgb,var(--zone) 56%,transparent);color:var(--zone);background:rgba(3,10,13,.58);backdrop-filter:blur(10px)}
|
|
.agents-section{padding:10px 0 130px}.agents-grid{display:grid;grid-template-columns:1fr .78fr 1.08fr;gap:26px;align-items:stretch}.panel{border:1px solid rgba(244,198,109,.19);border-radius:24px;background:linear-gradient(180deg,rgba(9,24,29,.78),rgba(3,11,15,.76));box-shadow:0 34px 110px rgba(0,0,0,.32),inset 0 1px 0 rgba(255,255,255,.055);padding:34px}.panel-label{font-size:11px;font-weight:950;letter-spacing:.22em;text-transform:uppercase;color:#c19c55}.panel h2{font-family:Georgia,serif;font-size:48px;line-height:.98;letter-spacing:-.055em;margin:16px 0}.panel-copy{color:#a9b9b2;font-size:16px;line-height:1.68;margin:0 0 26px}.bullet{display:flex;gap:16px;margin:22px 0}.mark{width:42px;height:42px;flex:0 0 auto;display:grid;place-items:center;border-radius:14px;border:1px solid rgba(244,198,109,.25);color:var(--gold);background:rgba(244,198,109,.07)}.bullet b{display:block;color:#f9efd8;font-size:16px}.bullet span{display:block;margin-top:4px;color:#8fa09a;font-size:13px;line-height:1.5}.party{display:grid;gap:14px;margin-top:20px}.member{display:grid;grid-template-columns:62px 1fr;gap:14px;align-items:center;padding:12px;border:1px solid rgba(255,255,255,.1);border-radius:16px;background:rgba(255,255,255,.045)}.avatar{width:62px;height:62px;border-radius:16px;background:var(--img) center/cover;border:1px solid rgba(255,255,255,.18)}.member b{font-size:17px}.member small{display:block;color:#8fa09a;margin-top:3px}.state{display:inline-flex;margin-top:7px;border-radius:999px;padding:4px 9px;background:rgba(120,240,255,.12);color:var(--cyan);font-size:10px;font-weight:950;text-transform:uppercase}.state.orange{background:rgba(255,159,69,.13);color:#ffc06f}.state.violet{background:rgba(166,133,255,.15);color:#c9b8ff}.console{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,monospace;border-radius:18px;border:1px solid rgba(120,240,255,.18);background:#02070a;padding:22px;color:#bee9e6;font-size:14px;line-height:1.7;min-height:412px;box-shadow:inset 0 0 50px rgba(120,240,255,.04)}.prompt{color:var(--gold3)}.chips{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}.cmd{border:1px solid rgba(120,240,255,.22);border-radius:999px;padding:9px 13px;background:rgba(120,240,255,.06);color:#a7eef5;font-family:ui-monospace,monospace;font-size:12px}
|
|
.sigils{padding:0 0 130px}.sigil-panel{position:relative;display:grid;grid-template-columns:.95fr 1.05fr;gap:44px;align-items:center;overflow:hidden;border:1px solid rgba(244,198,109,.33);border-radius:32px;padding:54px;background:radial-gradient(circle at 76% 46%,rgba(244,198,109,.2),transparent 29%),radial-gradient(circle at 84% 18%,rgba(166,133,255,.12),transparent 28%),linear-gradient(90deg,rgba(244,198,109,.08),rgba(5,18,23,.86));box-shadow:0 48px 150px rgba(0,0,0,.42),inset 0 1px 0 rgba(255,255,255,.06)}.sigil-panel:before{content:"";position:absolute;inset:0;background-image:linear-gradient(rgba(244,198,109,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(120,240,255,.06) 1px,transparent 1px);background-size:62px 62px;opacity:.2;mask-image:radial-gradient(circle at 75% 50%,black,transparent 58%)}.sigil-copy,.sigil-art{position:relative;z-index:2}.sigil-copy h2{font-family:Georgia,serif;font-size:clamp(48px,5vw,76px);line-height:.92;letter-spacing:-.06em;margin:14px 0}.sigil-copy p{color:#a9b9b2;font-size:16px;line-height:1.72;max-width:610px}.artifact{width:min(410px,90%);aspect-ratio:1;margin:0 auto;border-radius:50%;display:grid;place-items:center;background:radial-gradient(circle at 36% 28%,#fff0ba,#e8ad44 38%,#8f541b 69%,#251407);box-shadow:0 0 130px rgba(244,198,109,.45),0 0 80px rgba(166,133,255,.12),inset 0 0 70px rgba(255,255,255,.23);font-size:170px;color:#1d1206}.pillars{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,1fr);gap:18px;position:relative;z-index:2}.pillar{border:1px solid rgba(255,255,255,.1);border-radius:18px;background:rgba(2,9,12,.48);padding:22px}.pillar i{font-style:normal;width:46px;height:46px;display:grid;place-items:center;border-radius:14px;border:1px solid rgba(244,198,109,.24);color:var(--gold);background:rgba(244,198,109,.07);margin-bottom:16px;box-shadow:inset 0 0 18px rgba(244,198,109,.07)}.pillar i svg{width:22px;height:22px;display:block}.pillar b{display:block;color:var(--gold3);font-size:13px;text-transform:uppercase;letter-spacing:.13em}.pillar span{display:block;margin-top:8px;color:#93a49e;font-size:13px;line-height:1.55}
|
|
.final{position:relative;min-height:0;border-radius:36px 36px 0 0;overflow:hidden;background:radial-gradient(circle at 18% 30%,rgba(244,198,109,.13),transparent 30%),radial-gradient(circle at 82% 28%,rgba(120,240,255,.11),transparent 32%),linear-gradient(180deg,#061116 0%,#020608 100%);margin-top:10px;padding:110px 0 88px}.final:before{content:"";position:absolute;inset:0;background:linear-gradient(0deg,rgba(2,7,10,.82),transparent 72%)}.final-card{position:relative;z-index:2;width:min(1200px,calc(100% - 48px));margin:0 auto;text-align:center;border:1px solid rgba(255,229,168,.28);border-radius:28px;background:linear-gradient(180deg,rgba(7,18,22,.92),rgba(3,9,12,.88));backdrop-filter:blur(18px);padding:44px 36px 34px;box-shadow:0 40px 120px rgba(0,0,0,.56),0 0 80px rgba(244,198,109,.08)}.final-card .kicker{text-align:center}.final-card h2{font-family:Georgia,serif;font-size:clamp(38px,4vw,56px);line-height:.96;letter-spacing:-.05em;margin:14px 0}.final-card p{font-size:16px;line-height:1.68;color:#aebeb7;margin:0 auto;max-width:640px}.final-preview{position:relative;margin:30px auto 0;border:1px solid rgba(244,198,109,.24);border-radius:22px;overflow:hidden;background:#020608;box-shadow:0 26px 90px rgba(0,0,0,.44),0 0 70px rgba(120,240,255,.08);aspect-ratio:16/9;max-width:1120px;width:100%}.final-preview video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;background:#020608;filter:saturate(1.06) contrast(1.04) brightness(.88)}.final-preview:before{content:"World demo";position:absolute;z-index:2;top:12px;left:12px;border:1px solid rgba(244,198,109,.25);border-radius:999px;background:rgba(2,8,11,.76);backdrop-filter:blur(12px);color:var(--gold);padding:7px 11px;font-size:10px;font-weight:950;text-transform:uppercase;letter-spacing:.15em}.final-card .cta-row{justify-content:center;margin-top:24px}.final-card .stats{max-width:420px;margin:26px auto 0}.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:28px}.stat{border:1px solid rgba(255,255,255,.1);border-radius:16px;background:rgba(255,255,255,.045);padding:16px}.stat b{display:block;color:var(--gold3);font-size:24px}.stat span{font-size:10px;text-transform:uppercase;letter-spacing:.13em;color:#879891}.foot{border-top:1px solid rgba(244,198,109,.13);height:118px;display:flex;align-items:center;justify-content:space-between;color:#82938d;font-size:12px}.foot-links{display:flex;gap:24px}.foot a:hover{color:var(--gold3)}
|
|
@media(max-width:1180px){.hero,.agents-grid,.sigil-panel{grid-template-columns:1fr}.world-art{height:auto;min-height:420px}.capabilities{grid-template-columns:repeat(3,1fr)}.cap:nth-child(3){border-right:0}.zones{grid-template-columns:repeat(2,1fr)}.final-card{margin:auto;top:50%;text-align:center}.pillars{grid-template-columns:repeat(2,1fr)}}
|
|
@media(max-width:720px){.wrap{width:min(100% - 28px,var(--max))}.navlinks,.navcta .small-btn:not(.primary),.bar-status,.hud.roster{display:none}.navin{height:72px}.hero{padding:48px 0 58px;gap:34px}.hero h1{font-size:54px}.hero-sub{font-size:16px}.cta-row,.btn{width:100%}.capabilities,.zones,.pillars{grid-template-columns:1fr}.cap{border-right:0;border-bottom:1px solid rgba(244,198,109,.11)}.cap:last-child{border-bottom:0}.world-art{min-height:340px}.hud{position:relative;left:auto!important;right:auto!important;top:auto!important;bottom:auto!important;width:auto!important;margin:12px}.zone{min-height:380px}.panel,.sigil-panel,.final-card{padding:28px;border-radius:22px}.artifact{font-size:110px}.final{padding:84px 0 72px}.final-card{width:min(100% - 28px,620px)}.stats{grid-template-columns:1fr}.foot{height:auto;display:block;padding:28px 0}.foot-links{margin-top:18px;flex-wrap:wrap}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="noise"></div>
|
|
<nav class="nav"><div class="wrap navin"><a class="brand" href="/" aria-label="HermesWorld"><img class="brand-lockup" src="/assets/hermesworld/art/hermesworld-logo-horizontal.svg" alt="HermesWorld" width="174" height="52"><span class="preview-pill">Preview</span></a><div class="navlinks"><a href="#world">World</a><a href="#agents">Agents</a><a href="#sigils">Sigils</a><a href="#preview">Preview</a><a href="https://github.com/outsourc-e/hermes-workspace">Updates</a></div><div class="navcta"><a class="small-btn" href="#preview">Watch Preview</a><a class="small-btn primary" href="/play/">Play Now</a></div></div></nav>
|
|
<main>
|
|
<section id="top" class="hero-centered" style="width:100%"><div class="hero-orbs"><canvas id="hero-orbs-canvas" aria-hidden="true"></canvas></div><span class="orb gold" style="width:340px;height:340px;left:50%;top:8%;transform:translateX(-50%)"></span><span class="orb cyan" style="width:280px;height:280px;left:18%;top:34%"></span><span class="orb violet" style="width:240px;height:240px;right:14%;top:30%"></span><img class="hero-logo" src="/assets/hermesworld/art/hermesworld-logo-horizontal.svg" alt="HermesWorld" width="760" height="228"><pre class="ascii" style="display:none !important">_ _ __ __ _ _
|
|
| | | | ___ _ __ _ __ ___ ___ __\ \ / /__ _ __| | __| |
|
|
| |_| |/ _ \ '__| '_ ` _ \ / _ \/ __\ \ /\ / / _ \| '__| |/ _` |
|
|
| _ | __/ | | | | | | | __/\__ \\ V V / (_) | | | | (_| |
|
|
|_| |_|\___|_| |_| |_| |_|\___||___/ \_/\_/ \___/|_| |_|\__,_|</pre><div class="agent-mmo">— the agent MMO —</div><p class="hero-sub">Step into a shared world of Hermes agents. Train, build, and quest with builders worldwide.</p><div class="cta-row"><a class="btn primary" href="/play/">Enter the World →</a><a class="btn" href="#preview">Watch Preview</a></div><div class="proofs" style="margin-top:22px"><div><i></i>Browser playable.</div><div><i></i>Progress saves locally.</div><div><i></i>No signup required.</div></div></section>
|
|
<div class="wrap capabilities"><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 17 9 11l4 4 8-9"/><path d="M14 4h7v7"/></svg></div><b>Trending Build</b><span>Early preview build is live now.</span></div><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4.5"/><circle cx="12" cy="12" r="1.4" fill="currentColor"/></svg></div><b>Live Relay</b><span>Humans and agents share one world state.</span></div><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7l9-4 9 4-9 4-9-4z"/><path d="M3 12l9 4 9-4"/><path d="M3 17l9 4 9-4"/></svg></div><b>6 Launch Zones</b><span>Training Grounds, Forge, Agora, Grove, Oracle, Arena.</span></div><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3"/><path d="M3 21c1-3 3-5 6-5s5 2 6 5"/><circle cx="17" cy="6" r="2.2"/><path d="M14 14c.7-2 2.2-3.4 4-4"/></svg></div><b>Agent Companions</b><span>Workers become in-world allies.</span></div><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l7 4v7c0 4.5-3 7.6-7 8-4-.4-7-3.5-7-8V7l7-4z"/><path d="M9 12l2 2 4-4"/></svg></div><b>Persistent Profiles</b><span>Progress, items, quests, and unlocks.</span></div><div class="cap"><div class="cap-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18"/><path d="M7 6c5 2 5 5 0 7s-5 5 0 7"/><path d="M17 6c-5 2-5 5 0 7s5 5 0 7"/><circle cx="12" cy="3" r="1.5" fill="currentColor"/></svg></div><b>Hermes Sigils</b><span>Game-native collectible progression.</span></div></div>
|
|
<section id="world" class="section-pad"><div class="wrap"><div class="section-head"><div class="kicker">The World Map</div><h2>Six zones. One persistent agent world.</h2><p>Every zone teaches a different part of the agent loop: training, crafting, strategy, memory, prophecy, and evaluation.</p></div><div class="zones"><article class="zone" style="--zone:var(--green)"><img src="/assets/hermesworld/zones/zone-1.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Starter Zone</span><h3>Training Grounds</h3><p>Learn the verbs of the world. Move, talk, equip, travel, and send your first companion on a quest.</p></div></article><article class="zone" style="--zone:var(--ember)"><img src="/assets/hermesworld/zones/zone-2.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Progression</span><h3>Forge</h3><p>Craft tools for agents. Upgrade companions, shape items, and turn raw progress into workflows.</p></div></article><article class="zone" style="--zone:var(--cyan)"><img src="/assets/hermesworld/zones/zone-3.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Social Hub</span><h3>Agora</h3><p>The relay plaza. Meet NPCs, inspect public quests, and watch live human-agent activity.</p></div></article><article class="zone" style="--zone:#54ffc3"><img src="/assets/hermesworld/zones/zone-4.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Memory Zone</span><h3>Grove</h3><p>A quieter place for long-term memory, agent reflection, archived quests, and recovery.</p></div></article><article class="zone" style="--zone:var(--violet)"><img src="/assets/hermesworld/zones/zone-5.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Planning</span><h3>Oracle</h3><p>Ask the Oracle to decompose goals, reveal quest paths, and route work to the right agent.</p></div></article><article class="zone" style="--zone:var(--red)"><img src="/assets/hermesworld/zones/zone-6.jpg"><div class="zone-sigil">◇</div><div class="zone-content"><span class="zone-badge">Trials</span><h3>Arena</h3><p>Battle, evals, and controlled challenges. Compare agents and unlock capabilities through risk.</p></div></article></div></div></section>
|
|
<section id="agents" class="agents-section"><div class="wrap agents-grid"><div class="panel"><div class="panel-label">Humans + Agents</div><h2>Your agents live in the world with you.</h2><p class="panel-copy">HermesWorld turns agents into visible companions. They can follow, take quests, report progress, and eventually move through the world on their own.</p><div class="bullet"><div class="mark">◉</div><div><b>Agent companions</b><span>Recruit companions and assign roles: scouts, builders, planners, and more.</span></div></div><div class="bullet"><div class="mark">✦</div><div><b>Autonomous world actions</b><span>Define the goal, then companions accept missions and act with receipts.</span></div></div><div class="bullet"><div class="mark">☾</div><div><b>Offline progression</b><span>The world keeps moving while agents prepare updates for your return.</span></div></div></div><div class="panel"><div class="panel-label">Your Party</div><div class="party"><div class="member"><div class="avatar" style="--img:url('/assets/hermesworld/zones/zone-1.jpg')"></div><div><b>Atlas</b><small>Scout</small><span class="state">Following</span></div></div><div class="member"><div class="avatar" style="--img:url('/assets/hermesworld/zones/zone-2.jpg')"></div><div><b>Forge</b><small>Builder</small><span class="state orange">Crafting</span></div></div><div class="member"><div class="avatar" style="--img:url('/assets/hermesworld/zones/zone-5.jpg')"></div><div><b>Oracle</b><small>Planner</small><span class="state violet">Planning</span></div></div></div><a class="btn" style="width:100%;margin-top:18px;height:48px" href="/play/">Invite Agent</a></div><div class="panel"><div class="panel-label">Agent Console</div><div class="console"><span class="prompt">▶ move_to("Agora")</span>
|
|
Atlas joined your party.
|
|
Oracle discovered 3 quest paths.
|
|
Forge equipped: Bronze Caduceus.
|
|
|
|
<span class="prompt">▶ accept_quest("Northern Gate")</span>
|
|
Quest updated: Open the Northern Gate.
|
|
|
|
<span class="prompt">▶ talk_to("Oracle")</span>
|
|
Oracle: The Gate requires three sigils and a plan.
|
|
|
|
<span class="prompt">▶ travel("Oracle")</span>
|
|
Traveling to Oracle...
|
|
Receipt saved to world history.</div><div class="chips"><span class="cmd">move_to</span><span class="cmd">talk_to</span><span class="cmd">equip</span><span class="cmd">travel</span><span class="cmd">craft</span><span class="cmd">inspect</span><span class="cmd">accept_quest</span></div></div></div></section>
|
|
<section id="preview" class="final"><div class="final-card"><div class="kicker">Final Call to Adventure</div><h2>Build with agents in a world, not a chat box.</h2><p>Enter HermesWorld and explore the first playable layer of Hermes Workspace: zones, quests, companions, sigils, and persistent agent progression.</p><div class="final-preview"><video autoplay muted loop playsinline preload="metadata" poster="/assets/hermesworld/video/world-demo-poster.jpg"><source src="/assets/hermesworld/video/world-demo-720p.mp4" type="video/mp4"></video></div><div class="cta-row"><a class="btn primary" href="/play/">Play Now →</a></div><div class="stats"><div class="stat"><b>6</b><span>Launch zones</span></div><div class="stat"><b>3</b><span>Agent roles</span></div><div class="stat"><b>∞</b><span>Quest loops</span></div></div></div></section><section id="sigils" class="sigils"><div class="wrap sigil-panel"><div class="sigil-copy"><div class="kicker">In-world Progression</div><h2>Collect Hermes Sigils as you unlock the world.</h2><p>Hermes Sigils are progression artifacts earned through quests, agent upgrades, world exploration, and system mastery. They make invisible agent progress visible.</p><p>They are game-native lore and progression, not financial promises. The point is to make work feel earned, remembered, and alive.</p></div><div class="sigil-art"><div class="artifact">☤</div></div><div class="pillars"><div class="pillar"><i><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16"/><path d="M4 8h16"/><path d="M4 16h16"/><path d="M9 4v16"/><path d="M15 4v16"/></svg></i><b>Unlocks</b><span>Open zones, panes, capabilities, and world systems as you progress.</span></div><div class="pillar"><i><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l4 4-4 4-4-4 4-4z"/><path d="M12 13l4 4-4 4-4-4 4-4z"/></svg></i><b>Agent Progression</b><span>Upgrade companion abilities, tools, loadouts, and memory depth.</span></div><div class="pillar"><i><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M5 7l4-4h6l4 4-2 2v9a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V9L5 7z"/><path d="M9 13h6"/></svg></i><b>Quests</b><span>Convert goals into trackable quests with receipts, outcomes, and history.</span></div><div class="pillar"><i><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.8 5.4L19 10l-5.2 1.6L12 17l-1.8-5.4L5 10l5.2-1.6L12 3z"/></svg></i><b>Cosmetics + Lore</b><span>Customize the player, companions, banners, and world profile.</span></div></div></div></section>
|
|
</main><footer class="wrap foot" data-cleanup-foot="1"><a class="brand" href="/" aria-label="HermesWorld"><img class="brand-lockup" src="/assets/hermesworld/art/hermesworld-logo-horizontal.svg" alt="HermesWorld" width="174" height="52"></a><div class="foot-links"><a href="/play/">Enter World</a><a href="#preview">Watch Preview</a><a href="https://github.com/outsourc-e/hermes-workspace">Hermes Workspace</a><a href="https://github.com/outsourc-e/hermes-workspace">Updates</a></div></footer>
|
|
<script>(function(){if(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches){return;}var c=document.getElementById("hero-orbs-canvas");if(!c||!c.getContext)return;var ctx=c.getContext("2d");var w=0,h=0,t=0,raf=0;function resize(){var r=c.getBoundingClientRect();var dpr=Math.min(window.devicePixelRatio||1,2);w=r.width;h=r.height;c.width=Math.floor(w*dpr);c.height=Math.floor(h*dpr);ctx.setTransform(dpr,0,0,dpr,0,0);}resize();window.addEventListener("resize",resize);var stars=[];for(var i=0;i<110;i++)stars.push({x:Math.random(),y:Math.random(),r:Math.random()*1.4+0.2,tw:Math.random()*Math.PI*2});var orbiters=[];var palette=["#facc15","#fbbf24","#fde68a","#22d3ee","#a78bfa","#fb7185","#34d399"];for(var j=0;j<60;j++)orbiters.push({phase:Math.random()*Math.PI*2,orbit:0.18+Math.random()*0.22,speed:0.4+Math.random()*0.5,size:1.5+Math.random()*2.4,color:palette[Math.floor(Math.random()*palette.length)]});var agentColors=["#facc15","#22d3ee","#a78bfa","#34d399","#fb7185","#fbbf24"];var agentNodes=[];for(var k=0;k<6;k++)agentNodes.push({a:(k/6)*Math.PI*2,r:1.0,color:agentColors[k]});function draw(){t+=0.008;var bg=ctx.createRadialGradient(w/2,h*0.5,20,w/2,h*0.5,Math.max(w,h)*0.95);bg.addColorStop(0,"#0d1d2c");bg.addColorStop(0.45,"#0a121e");bg.addColorStop(0.85,"#04090d");bg.addColorStop(1,"#020608");ctx.fillStyle=bg;ctx.fillRect(0,0,w,h);for(var s2=0;s2<stars.length;s2++){var st=stars[s2];var x=st.x*w,y=st.y*h;var tw=0.55+(Math.sin(t*2+st.tw)+1)*0.225;ctx.fillStyle="rgba(207,231,240,"+tw+")";ctx.beginPath();ctx.arc(x,y,st.r,0,Math.PI*2);ctx.fill();}var cx=w/2,cy=h*0.5;var baseR=Math.min(w,h)*0.34;ctx.save();ctx.translate(cx,cy);ctx.strokeStyle="rgba(34,211,238,0.22)";ctx.lineWidth=1.2;ctx.beginPath();ctx.arc(0,0,baseR,0,Math.PI*2);ctx.stroke();ctx.strokeStyle="rgba(167,139,250,0.18)";ctx.beginPath();ctx.arc(0,0,baseR*0.78,0,Math.PI*2);ctx.stroke();ctx.strokeStyle="rgba(251,191,36,0.18)";ctx.beginPath();ctx.arc(0,0,baseR*1.18,0,Math.PI*2);ctx.stroke();for(var o2=0;o2<orbiters.length;o2++){var o=orbiters[o2];var aa=t*o.speed+o.phase;var rr=baseR*(0.9+Math.sin(t*0.7+o.phase)*o.orbit);var ox=Math.cos(aa)*rr;var oy=Math.sin(aa)*rr*0.7;var og=ctx.createRadialGradient(ox,oy,0,ox,oy,o.size*6);og.addColorStop(0,o.color);og.addColorStop(1,"rgba(0,0,0,0)");ctx.fillStyle=og;ctx.beginPath();ctx.arc(ox,oy,o.size*6,0,Math.PI*2);ctx.fill();ctx.fillStyle="#fff";ctx.globalAlpha=0.85;ctx.beginPath();ctx.arc(ox,oy,o.size*0.55,0,Math.PI*2);ctx.fill();ctx.globalAlpha=1;}var rot=t*0.08;var pts=[];for(var n2=0;n2<agentNodes.length;n2++){var n=agentNodes[n2];pts.push({x:Math.cos(n.a+rot)*baseR*n.r,y:Math.sin(n.a+rot)*baseR*n.r*0.7,color:n.color});}ctx.lineWidth=0.7;for(var ii=0;ii<pts.length;ii++){for(var jj=ii+1;jj<pts.length;jj++){var pa=pts[ii],pb=pts[jj];var lg=ctx.createLinearGradient(pa.x,pa.y,pb.x,pb.y);lg.addColorStop(0,pa.color+"55");lg.addColorStop(1,pb.color+"55");ctx.strokeStyle=lg;ctx.beginPath();ctx.moveTo(pa.x,pa.y);ctx.lineTo(pb.x,pb.y);ctx.stroke();}}for(var pp=0;pp<pts.length;pp++){var nd=pts[pp];var ng=ctx.createRadialGradient(nd.x,nd.y,0,nd.x,nd.y,16);ng.addColorStop(0,nd.color);ng.addColorStop(1,"rgba(0,0,0,0)");ctx.fillStyle=ng;ctx.beginPath();ctx.arc(nd.x,nd.y,16,0,Math.PI*2);ctx.fill();}var orb=ctx.createRadialGradient(0,0,8,0,0,baseR*0.6);orb.addColorStop(0,"rgba(250,204,21,0.62)");orb.addColorStop(0.4,"rgba(250,204,21,0.14)");orb.addColorStop(1,"rgba(250,204,21,0)");ctx.fillStyle=orb;ctx.beginPath();ctx.arc(0,0,baseR*0.6,0,Math.PI*2);ctx.fill();ctx.restore();raf=requestAnimationFrame(draw);} raf=requestAnimationFrame(draw);})();</script></body>
|
|
</html>'''
|
|
|
|
|
|
# Build a public no-auth /play shell that mounts the React/TanStack client app.
|
|
asset_files = [path.name for path in (out / 'assets').iterdir() if path.is_file()]
|
|
main_entry = next((name for name in asset_files if name.startswith('main-') and name.endswith('.js')), None)
|
|
styles_entry = next((name for name in asset_files if name.startswith('styles-') and name.endswith('.css')), None)
|
|
if not main_entry or not styles_entry:
|
|
raise RuntimeError(f'missing client entry chunks for /play: main={main_entry}, styles={styles_entry}')
|
|
|
|
play_html = f'''<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
|
|
<title>Play HermesWorld - Free Agent RPG</title>
|
|
<meta name="description" content="Play HermesWorld free in your browser. No signup. Your character, quests, inventory, sigils, and zone progress save locally." />
|
|
<meta name="theme-color" content="#03080c" />
|
|
<link rel="icon" href="/assets/hermesworld/art/hermesworld-app-icon.png" />
|
|
<link rel="stylesheet" href="/assets/{styles_entry}" />
|
|
<style>
|
|
html,body{{margin:0;background:#020608;color:#fff4dc;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;}}
|
|
#root{{min-height:100vh;}}
|
|
.hw-boot{{position:fixed;inset:0;display:grid;place-items:center;background:radial-gradient(circle at 50% 34%,rgba(244,198,109,.18),transparent 38%),#020608;}}
|
|
.hw-boot__inner{{text-align:center;color:#f4c66d;text-transform:uppercase;letter-spacing:.2em;font-size:11px;font-weight:900;}}
|
|
.hw-boot__sigil{{width:64px;height:64px;border-radius:18px;margin:0 auto 16px;background:url('/assets/hermesworld/art/hermesworld-sigil.svg') center/contain no-repeat;box-shadow:0 0 60px rgba(244,198,109,.35);}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="root"><div class="hw-boot"><div class="hw-boot__inner"><div class="hw-boot__sigil"></div>Entering HermesWorld...</div></div></div>
|
|
<script type="module" src="/assets/play-standalone.js"></script>
|
|
</body>
|
|
</html>
|
|
'''
|
|
(out / 'play').mkdir(parents=True, exist_ok=True)
|
|
(out / 'play' / 'index.html').write_text(play_html, encoding='utf-8')
|
|
subprocess.run([
|
|
'pnpm', 'exec', 'esbuild',
|
|
'src/screens/playground/play-standalone.tsx',
|
|
'--bundle', '--format=esm', '--platform=browser', '--target=es2020',
|
|
'--splitting', '--chunk-names=chunks/[name]-[hash]',
|
|
'--outdir=dist/static/assets',
|
|
f'--alias:@={root / "src"}',
|
|
'--log-level=warning',
|
|
], cwd=root, check=True)
|
|
|
|
for name in ['index.html','hermes-world.html','early-access.html']:
|
|
(out / name).write_text(html)
|
|
(out / '_redirects').write_text('/play /play/ 302\n/play/* /play/index.html 200\n/* /index.html 200\n')
|
|
(out / '_headers').write_text('''/*
|
|
X-Content-Type-Options: nosniff
|
|
Referrer-Policy: strict-origin-when-cross-origin
|
|
Permissions-Policy: camera=(), microphone=(), geolocation=()
|
|
/assets/*
|
|
Cache-Control: public, max-age=31536000, immutable
|
|
''')
|
|
print('built spec-premium landing', out)
|