reckfellENGINE

Custom HTML shell for a Web build

Export tokens, executed startup example, canvas and pending-start diagnosis.

On this page

Custom HTML shell for a Web build

A custom shell controls the page, canvas and startup UI around a compatible Web export. It does not add Web support to the installed C# exporter 1.0.0. Verify that you have a working native Web template and supported project first; this guide does not claim an exported C# browser game.

Use the exported placeholders

Set html/custom_html_shell to your HTML file in the Web export preset. The exporter replaces tokens; opening the unexported template directly is not a launch test.

TokenMeaning
$RECKFELL_URLGenerated loader .js filename; load this before using Engine.
$RECKFELL_CONFIGGenerated JavaScript config object; insert as an expression, not a quoted string.
$RECKFELL_THREADS_ENABLEDtrue/false for feature detection matching this export variant.
$RECKFELL_HEAD_INCLUDEExport-generated head metadata plus html/head_include; retain it if using those features.
$RECKFELL_PROJECT_NAMEProject name, not an already escaped universal HTML fragment.
$RECKFELL_SPLASH / $RECKFELL_SPLASH_COLOR / $RECKFELL_SPLASH_CLASSESGenerated splash path, color and styling classes.

The example uses a fixed title and explicit canvas. Its exact inline script was tested with substituted config/threads values and mock DOM/Engine outcomes:

XML
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Reckfell project</title>
  $RECKFELL_HEAD_INCLUDE
</head>
<body>
  <p id="status" role="status" aria-live="polite">Loading…</p>
  <canvas id="game" tabindex="0" aria-label="Game"></canvas>
  <script src="$RECKFELL_URL"></script>
  <script>
    const status = document.getElementById('status');
    const missing = Engine.getMissingFeatures({ threads: $RECKFELL_THREADS_ENABLED });
    if (missing.length) {
      status.textContent = missing.join('\n');
    } else {
      const config = $RECKFELL_CONFIG;
      const engine = new Engine({ ...config, canvas: document.getElementById('game') });
      const timer = setTimeout(() => {
        status.textContent = 'Startup is still pending. Check network and console; reload before retrying.';
      }, 30000);
      engine.startGame().then(() => {
        status.textContent = 'Runtime started. Game readiness is reported separately.';
      }).catch(error => {
        console.error(error);
        status.textContent = 'Startup failed. Check network and console; reload before retrying.';
      }).finally(() => clearTimeout(timer));
    }
  </script>
</body>
</html>

The 30-second timer only reports a pending startup. It does not cancel network work, stop WASM or prove failure. A late successful startup can still replace the message. The success text means the loader invoked main, not that the first gameplay scene or first frame is ready. Add an explicit game-to-page readiness message through JavaScriptBridge if the page needs that distinction.

Startup paths

For a normal project, create one Engine with exported config and call startGame once. It loads executable + .wasm, preloads mainPack (or executable + .pck), adds --main-pack and invokes start. Do not pass the .wasm suffix as executable/basePath: init('game') loads game.wasm; init('game.wasm') asks for game.wasm.wasm.

For custom preloading, init uses an extensionless engine base path; preloadFile loads the pack and other files; start uses the prepared virtual filesystem and explicit args. start does not preload the main pack for you. Wait for every required preload before starting. Supply a virtual destination path explicitly when preloading a buffer rather than a URL.

Do not call startGame twice to retry: it prepends --main-pack again, and current loader state is shared through closure-level load/init promises. Concurrent instances can share initialization without both receiving a module; this was reproduced with mock modules. Use one instance/startup owner per page. After a failed or abandoned attempt, inspect diagnostics and reload before retrying; a timeout is not cancellation.

Hosting and presentation

Serve the exported HTML, loader, WASM, pack and any generated companion files together under their expected URLs. Use HTTP(S), appropriate WASM response handling and the headers required by the threaded variant. Feature detection is a prerequisite check, not proof that the WASM/pack downloaded or the game rendered. Test the actual deployed origin; file:// is not an acceptance environment.

Choose canvasResizePolicy deliberately: 0 leaves resizing to page code, 1 uses project-driven sizing, 2 adapts to the browser window. Embedded layout normally needs its own size handling when using 0. Avoid two independent resize owners. locale selects game localization, not translation of arbitrary DOM labels. experimentalVK means virtual keyboard, not Vulkan.

onProgress(current,total) tracks download bytes; total may be zero. Show indeterminate loading in that case rather than dividing by zero. onPrint/onPrintError receive runtime output; use textContent for visible messages. Network, native errors, game readiness, save durability and service-worker registration are separate states.

Current init code does not forward every nested promise rejection to the outer promise, and it ignores a resolved FS initialization error value. A catch handler alone cannot establish a completed failure path or persistence. Inspect network/console and see storage and backup. startGame also does not wait for service-worker registration.

Verification scope

Twenty checks executed actual Engine/config JavaScript with mock preloader, module, Response and canvas, plus the exact shell script with substituted placeholders and mock startup outcomes. Paths, pack handling, missing canvas, shared init state, pending UI and configuration mapping were checked. No actual template export, WASM, headers/server, browser rendering, accessibility interaction, storage/PWA completion or C# Web execution was accepted. Engine Source, Runtime and SDK were unchanged.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.