← Public packages
@kody/doomPublic
src/app/html.ts
140 lines · 6.6 KB · TypeScript/** HTML document for the KODOOM PWA. */
export function renderHtml(opts: {
appBasePath: string
hostedUrl: string
engineBase: string
freedoomZipUrl: string
sharewareWadUrl: string
cfgUrl: string
fflateUrl: string
}): string {
const base = opts.appBasePath.replace(/\/$/, '')
const boot = {
appBasePath: base,
hostedUrl: opts.hostedUrl,
engineBase: opts.engineBase,
freedoomZipUrl: opts.freedoomZipUrl,
sharewareWadUrl: opts.sharewareWadUrl,
cfgUrl: opts.cfgUrl,
fflateUrl: opts.fflateUrl,
}
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#070405" />
<meta name="description" content="KODOOM — play Freedoom in the browser as an installable PWA with WebMCP tools." />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<title>KODOOM</title>
<link rel="manifest" href="${base}/manifest.webmanifest" />
<link rel="icon" href="${base}/icon.png" type="image/png" />
<link rel="apple-touch-icon" href="${base}/icons/apple-touch-icon.png" />
<link rel="stylesheet" href="${base}/app.css" />
</head>
<body>
<header class="top">
<div class="brand">
<svg viewBox="0 0 128 128" aria-hidden="true"><defs><radialGradient id="g" cx="50%" cy="60%" r="60%"><stop offset="0%" stop-color="#ff5014"/><stop offset="55%" stop-color="#1a0a08"/><stop offset="100%" stop-color="#070405"/></radialGradient></defs><rect width="128" height="128" rx="24" fill="url(#g)"/><circle cx="64" cy="64" r="46" fill="none" stroke="#ffb020" stroke-width="4"/><path d="M40 78 V42 H52 L64 62 76 42 H88 V78 H76 V56 L64 74 52 56 V78 Z" fill="#ffc040"/></svg>
<div>
<div class="wordmark">KODOOM</div>
<div class="tag">Freedoom · Chocolate Doom WASM · WebMCP</div>
</div>
</div>
<span id="webmcp-badge" class="badge missing">Checking WebMCP…</span>
</header>
<div id="offline-note" class="offline-note">You are offline. The KODOOM shell may work from cache; engine/IWAD need a prior online visit.</div>
<main class="layout">
<section>
<div class="stage" id="stage">
<canvas id="canvas" width="800" height="600" tabindex="0" aria-label="KODOOM game canvas"></canvas>
<div class="overlay" id="overlay">
<div>
<h1 id="overlay-title">Enter the hellgate</h1>
<p id="overlay-body">Press Start to load Freedoom (BSD) on Chocolate Doom WASM. First run downloads the Freedoom zip.</p>
</div>
</div>
</div>
</section>
<aside class="panel">
<h2>Play</h2>
<label>IWAD
<select id="iwad-select">
<option value="freedoom" selected>Freedoom Phase 1 (default)</option>
<option value="shareware">DOOM shareware (doom1.wad)</option>
</select>
</label>
<div class="row">
<button type="button" id="btn-start">Start</button>
<button type="button" id="btn-pause">Pause / Menu</button>
<button type="button" id="btn-fullscreen">Fullscreen</button>
<button type="button" id="btn-help">Help</button>
</div>
<h2>Warp</h2>
<div class="row">
<label>Ep <input id="warp-ep" type="number" min="1" max="4" value="1" style="width:4rem" /></label>
<label>Map <input id="warp-map" type="number" min="1" max="9" value="1" style="width:4rem" /></label>
<button type="button" id="btn-warp">Start warped</button>
</div>
<h2>Quick input</h2>
<div class="row">
<button type="button" data-action="up">↑</button>
<button type="button" data-action="down">↓</button>
<button type="button" data-action="left">←</button>
<button type="button" data-action="right">→</button>
<button type="button" data-action="fire">Fire</button>
<button type="button" data-action="use">Use</button>
</div>
<h2>Status</h2>
<pre class="status" id="status">boot</pre>
<h2>WebMCP forms</h2>
<div class="mcp-forms">
<form toolname="get_status" tooldescription="Get KODOOM game status">
<button type="submit">get_status</button>
</form>
<form toolname="start_game" tooldescription="Start Freedoom or shareware">
<label>iwad <select name="iwad" toolparamdescription="IWAD pack"><option value="freedoom">freedoom</option><option value="shareware">shareware</option></select></label>
<button type="submit">start_game</button>
</form>
<form toolname="pause_or_resume" tooldescription="Toggle pause/menu">
<button type="submit">pause_or_resume</button>
</form>
<form toolname="toggle_fullscreen" tooldescription="Toggle fullscreen">
<button type="submit">toggle_fullscreen</button>
</form>
<form toolname="send_input" tooldescription="Send a key action to the canvas">
<label>action <select name="action" toolparamdescription="Named action"><option>up</option><option>down</option><option>left</option><option>right</option><option>fire</option><option>use</option><option>escape</option></select></label>
<button type="submit">send_input</button>
</form>
<form toolname="select_episode_or_map" tooldescription="Start with episode/map warp">
<label>episode <input name="episode" type="number" value="1" toolparamdescription="Episode" /></label>
<label>map <input name="map" type="number" value="1" toolparamdescription="Map" /></label>
<button type="submit">select_episode_or_map</button>
</form>
<form toolname="get_controls" tooldescription="List controls">
<button type="submit">get_controls</button>
</form>
<form toolname="open_help" tooldescription="Open help dialog">
<button type="submit">open_help</button>
</form>
</div>
<p class="help">Click the canvas after start so keys reach the engine. WebMCP tools call the same handlers as these buttons.</p>
</aside>
</main>
<dialog id="help-dialog">
<form method="dialog">
<h2>KODOOM help</h2>
<p class="help">Move with arrows. <kbd>Ctrl</kbd> fire, <kbd>Space</kbd> use, <kbd>Shift</kbd> run, <kbd>Esc</kbd> menu, <kbd>Tab</kbd> map.</p>
<p class="legal">Not affiliated with id Software or Bethesda. Classic DOOM is their trademark. This app runs open Freedoom content (BSD) on Chocolate Doom WASM (GPLv2).</p>
<button value="close">Close</button>
</form>
</dialog>
<footer>
KODOOM · Freedoom (BSD) · Chocolate Doom WASM (GPLv2) · Engine artifacts via justinh-rahb/webui-doom (cloudflare/doom-wasm lineage). Source offer in package README / COPYING.GPL.
</footer>
<script>window.__KODOOM__ = ${JSON.stringify(boot)};</script>
<script src="${base}/app.js"></script>
</body>
</html>`
}