IF Hub serves games in-place from their own GitHub Pages deployments. There is no deploy script, no file copying, and no games/ directory. Each game project is a separate repository that owns its own pages, assets, and binaries.
The hub simply references each game by URL. The split-pane player (app.html) loads the game in an iframe pointing directly at the game’s own play.html, fetches source code from the game’s own source.html or story.ni, and loads walkthroughs from the game’s own walkthrough.html.
All game repos deploy under johnesco.github.io/*, making everything same-origin. This means iframes, fetch(), and postMessage all work freely between the hub and game pages.
| Component | Location | Purpose |
|---|---|---|
games.json |
Hub repo (ifhub/) |
Game registry — ids, titles, URLs, sound flags |
cards.json |
Hub repo (ifhub/) |
Landing page card metadata — descriptions, versions |
app.html |
Hub repo (ifhub/) |
Split-pane player — iframes game pages by URL |
play.html |
Game repo root (or vN/) |
Parchment player page — owned by the game |
source.html |
Game repo root (or vN/) |
Source browser — owned by the game |
walkthrough.html |
Game repo root (or vN/) |
Walkthrough viewer — owned by the game |
Before adding a game to IF Hub, the game project must have:
| File | Purpose | Status |
|---|---|---|
play.html |
Parchment player page (loads the compiled game binary) | required |
source.html or story.ni |
Source browser page or raw Inform 7 source file | required |
index.html |
Landing page for the game | required |
walkthrough.html |
Walkthrough viewer page | optional |
| GitHub Pages enabled | Pages must be live at johnesco.github.io/<game>/ |
required |
Use the shared compilation tools:
# Standard compilation (no sound):
python /c/code/ifhub/tools/compile.py game-name
# With native blorb sound (embeds .ogg audio in .gblorb):
python /c/code/ifhub/tools/compile.py game-name --sound
This compiles the source, base64-encodes the binary, generates play.html, and validates the result — all in one command.
Place story.ni in projects/mygame/ and compile:
python /c/code/ifhub/tools/compile.py mygame
This compiles the source, base64-encodes the binary, generates play.html and walkthrough.html, and validates the result.
Extract walkthrough commands from the game’s source (if it has Test me with “...”) or from a TRANSCRIPT file recorded during play.
# From Test me in source:
mkdir -p projects/mygame/tests/inform7
python /c/code/ifhub/tools/extract_commands.py --from-source \
projects/mygame/story.ni \
-o projects/mygame/tests/inform7/walkthrough.txt
# Or from a TRANSCRIPT file (recorded by typing TRANSCRIPT in-game):
python /c/code/ifhub/tools/extract_commands.py transcript.txt \
-o projects/mygame/tests/inform7/walkthrough.txt
Now that walkthrough commands exist, recompiling auto-generates the transcript, annotated guide, and copies everything to the web root:
python /c/code/ifhub/tools/compile.py mygame
python /c/code/ifhub/tools/web/generate_pages.py \
--title "My Game" \
--meta "An Interactive Fiction" \
--description "A brief description of the game." \
--out projects/mygame
Generates index.html (landing page with Play/Source/Walkthrough links) and source.html (syntax-highlighted source browser).
python /c/code/ifhub/tools/register_game.py \
--name mygame \
--title "My Game" \
--meta "An Interactive Fiction" \
--description "A brief description of the game."
Adds entries to games.json and cards.json automatically. Optional flags: --sound blorb for sound-enabled games.
python /c/code/ifhub/tools/publish.py mygame
First run: creates a Johnesco/mygame GitHub repo, pushes all files, and enables GitHub Pages via a GitHub Actions workflow (auto-generated if missing). Subsequent runs: commits and pushes to trigger redeployment.
python /c/code/ifhub/tools/push_hub.py mygame
Stages games.json and cards.json, commits with a message referencing the game name, and pushes to the hub repo. Skips if no changes.
Wait for Pages to deploy (~1 minute), then check:
johnesco.github.io/mygame/play.html — game loadsjohnesco.github.io/ifhub/app.html?game=mygame — hub shows game, source, and walkthroughDrives the split-pane player (app.html). Each entry defines URL-based fields:
| Field | Type | Description |
|---|---|---|
id |
string | Unique identifier used in URL params (e.g. ?game=mygame) |
title |
string | Display name in the game selector dropdown |
sourceLabel |
string | Filename shown in the source pane toolbar |
sourceBrowser |
boolean? | If true, source is loaded in an iframe instead of the code viewer |
playUrl |
string | Absolute URL path to the game’s play page |
sourceUrl |
string | Absolute URL path to source.html or story.ni |
walkthroughUrl |
string? | Absolute URL path to walkthrough.html |
landingUrl |
string? | Absolute URL path to the game’s landing page |
sound |
string? | Sound mode: "blorb" for native Glk sound |
overlayLabel |
string? | Label for the game’s native CSS overlay (e.g. "Fever Dream Overlay"). When present, the style dropdown shows this as the default option alongside platform themes. |
Drives the landing page (index.html). Each card groups a game with its versions:
| Field | Type | Description |
|---|---|---|
id | string | Game ID (primary version) |
base | string | Base name (used for source/walkthrough URLs on landing page) |
title | string | Display title for the card |
meta | string | Subtitle / author info |
description | string | Card description text |
playUrl | string | Absolute URL to primary play page |
landingUrl | string | Absolute URL to landing page |
versions | array? | Version entries with id, label, playUrl |
The walkthrough viewer is a self-contained HTML page that fetches three data files via relative paths. It supports three modes: Commands (annotated step list), Game Text (full transcript), and Replay (animated playback).
| File | Purpose | Modes enabled |
|---|---|---|
walkthrough.txt |
One command per line, in play order | Commands (raw fallback) |
walkthrough-guide.txt |
Annotated guide with ## sections and > commands |
Commands (with sections + sidebar nav) |
walkthrough_output.txt |
Game transcript from running walkthrough commands | Game Text, Replay |
walkthrough.html |
The viewer page itself | — |
walkthrough.txt exists, Commands mode shows a raw numbered list. If the transcript is missing, Game Text and Replay buttons are disabled. If the guide is missing, Commands mode works but without section headers or sidebar navigation.
compile.py handles this automatically. When tests/inform7/walkthrough.txt exists and glulxe.exe is available, it:
walkthrough_output.txtgenerate-guide.py → walkthrough-guide.txtTo create the initial walkthrough commands:
# From "Test me with ..." in story.ni:
python /c/code/ifhub/tools/extract_commands.py --from-source story.ni \
-o tests/inform7/walkthrough.txt
# From a TRANSCRIPT file (recorded in Parchment, IDE, or any interpreter):
python /c/code/ifhub/tools/extract_commands.py transcript.txt \
-o tests/inform7/walkthrough.txt
# Then recompile to generate the transcript and guide:
python /c/code/ifhub/tools/compile.py mygame
The dev server at tools/dev_server.py maps URL prefixes to local directories, providing production-equivalent URLs without deploying to GitHub Pages:
python tools/dev_server.py [--port 8000]
# /ifhub/* → site/
# /mygame/* → projects/mygame/
# Open http://127.0.0.1:8000/ifhub/app.html
The server auto-discovers game projects from the projects/ directory. It binds to 127.0.0.1 (not "") to avoid IPv6 issues on Windows.
| Check | How to verify |
|---|---|
| Game Pages are live | Visit johnesco.github.io/mygame/play.html in a browser |
| Game appears in dropdown | Open IF Hub app.html, check the game selector |
| Game is playable | Select it, type a command in the game pane |
| Source code loads | Source tab shows highlighted code with line numbers (or source browser iframe) |
| Walkthrough loads (if added) | Walkthrough tab shows Commands mode with numbered steps |
| Card appears on landing page | Open index.html, verify the card renders with correct links |
| Sound controls appear (if sound) | Mute button and volume slider appear in toolbar for sound-enabled games |
| URL parameter works | app.html?game=mygame loads the correct game on page load |