Files
lifegame/public/index.html
T
2026-07-21 20:48:28 +00:00

118 lines
4.8 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Life Journey — Deployment Check</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700;800&family=Nunito+Sans:wght@400;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--page: #163a30; --page-2: #0f2a23; --paper: #f6edd8;
--ink: #2a2018; --ink-soft: #6b5d4a; --marigold: #e8a12a;
--good: #3f8f5f; --bad: #c1452f; --line: #d8c7a2;
}
* { box-sizing: border-box; }
body {
margin: 0; min-height: 100vh; padding: 24px 16px;
font-family: "Nunito Sans", system-ui, sans-serif; color: var(--ink);
background: radial-gradient(1200px 600px at 50% -10%, #1d493c 0%, var(--page) 45%, var(--page-2) 100%);
display: flex; align-items: center; justify-content: center;
}
.card {
background: var(--paper); border: 1px solid var(--line); border-radius: 16px;
box-shadow: 0 10px 30px rgba(0,0,0,.28); padding: 28px; max-width: 460px; width: 100%;
}
h1 { font-family: "Baloo 2"; color: var(--marigold); margin: 0 0 2px; font-size: 30px; font-weight: 800; }
.sub { color: var(--ink-soft); font-size: 13px; margin: 0 0 20px; }
.check {
display: flex; align-items: center; gap: 12px; padding: 12px 14px;
border: 1.5px solid var(--line); border-radius: 12px; background: #fffaf0; margin-bottom: 10px;
}
.dot { width: 14px; height: 14px; border-radius: 50%; background: var(--ink-soft); flex: none; }
.dot.ok { background: var(--good); } .dot.fail { background: var(--bad); }
.check .name { font-weight: 700; font-family: "Baloo 2"; }
.check .state { margin-left: auto; font-size: 13px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
button {
font-family: "Baloo 2"; font-weight: 700; font-size: 14px; color: var(--ink);
background: var(--marigold); border: none; border-radius: 10px; padding: 9px 16px;
cursor: pointer; box-shadow: 0 3px 0 #b97f18; margin-top: 8px;
}
button:active { transform: translateY(3px); box-shadow: 0 0 0 #b97f18; }
.note { font-size: 12px; color: var(--ink-soft); margin-top: 16px; line-height: 1.5; }
code { background: #efe5cc; padding: 1px 5px; border-radius: 5px; font-size: 12px; }
</style>
</head>
<body>
<div class="card">
<h1>Life Journey</h1>
<p class="sub">Deployment check · Phase 0 — no game here yet</p>
<div class="check">
<span class="dot" id="http-dot"></span>
<span class="name">Server (HTTP)</span>
<span class="state" id="http-state">checking…</span>
</div>
<div class="check">
<span class="dot" id="ws-dot"></span>
<span class="name">WebSocket</span>
<span class="state" id="ws-state">connecting…</span>
</div>
<button id="ping">Send WebSocket ping</button>
<p class="note">
Both dots green means the shell is deployed correctly and your reverse
proxy is passing WebSockets. If the WebSocket dot is red but HTTP is green,
enable <code>Websockets Support</code> on the proxy host in Nginx Proxy Manager.
</p>
</div>
<script>
// ---- HTTP health check ----
const httpDot = document.getElementById('http-dot');
const httpState = document.getElementById('http-state');
fetch('/api/health')
.then(r => r.json())
.then(d => {
httpDot.classList.add('ok');
httpState.textContent = `ok · v${d.version}`;
})
.catch(() => {
httpDot.classList.add('fail');
httpState.textContent = 'unreachable';
});
// ---- WebSocket check ----
const wsDot = document.getElementById('ws-dot');
const wsState = document.getElementById('ws-state');
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
let ws;
try {
ws = new WebSocket(`${proto}://${location.host}/ws`);
ws.onopen = () => { wsDot.classList.add('ok'); wsState.textContent = 'connected'; };
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
if (data.type === 'echo') wsState.textContent = 'echo received ✓';
else if (data.type === 'welcome') wsState.textContent = 'connected';
};
ws.onerror = () => { wsDot.classList.add('fail'); wsState.textContent = 'failed'; };
ws.onclose = () => { if (!wsDot.classList.contains('ok')) { wsDot.classList.add('fail'); wsState.textContent = 'closed'; } };
} catch {
wsDot.classList.add('fail'); wsState.textContent = 'unsupported';
}
document.getElementById('ping').onclick = () => {
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send('ping ' + new Date().toISOString());
wsState.textContent = 'ping sent…';
} else {
wsState.textContent = 'not connected';
}
};
</script>
</body>
</html>