Search documentation

Find pages, sections, and content across all docs.

WavedashDocs

Ren'Py

Publish Ren'Py visual novels with the built-in HTML5 web build target.

View example project on GitHub Playtest the example project

Ren'Py supports web builds through its Emscripten-based HTML5 export. The output is a folder of HTML, JS, WASM, and game data that Wavedash can host directly.

Prerequisites

  • Ren'Py SDK (8.x)
  • The Ren'Py web platform package installed into the SDK (download from the same page; it unpacks a web/ folder into the SDK root)

Build for web

From the Ren'Py launcher: select your project → Build Distributions → check Web → build to a destination folder.

From the command line:

"$RENPY_SDK/renpy.sh" launcher web_build ./my-project --destination ./build

The output contains index.html, renpy.wasm, renpy.js, game.zip, and icons. Point upload_dir at that folder.

SDK integration

Ren'Py exposes renpy.emscripten.run_script(...) on the web platform — it evals JavaScript on the host page, so you can reach window.Wavedash directly. The host installs it synchronously at the top of <head>, so it's already the SDK by the time Ren'Py's wasm runs. The Promise.resolve(...) wrap below is defensive in case that ever changes.

game/00_wavedash.rpy

default wavedash_first_playable_reported = False

init -100 python:
    import renpy.store as store

    def wavedash_report_first_playable():
        if store.wavedash_first_playable_reported:
            return
        store.wavedash_first_playable_reported = True

        if not renpy.emscripten:
            return

        renpy.emscripten.run_script("""
            Promise.resolve(window.Wavedash).then(function (sdk) {
                sdk.updateLoadProgressZeroToOne(1);
                sdk.init({ debug: true });
            });
        """)

label before_main_menu:
    $ wavedash_report_first_playable()
    return

renpy.emscripten is the documented Ren'Py module for web JS interop; on desktop builds it's None, so the truthy check doubles as a platform guard.

Adding more SDK methods

Inline more JS in the same run_script block (or add a separate function for each beat). For example, unlocking an achievement:

$ renpy.emscripten.run_script("""
    Promise.resolve(window.Wavedash).then(function (sdk) {
        sdk.setAchievement('first_chapter_complete', true);
    });
""")

Load progress

The snippet above reports 1.0 right before main_menu is shown, which is the earliest moment the game is visible and interactive — the before_main_menu label is Ren'Py's hook for exactly this. For intermediate progress, call updateLoadProgressZeroToOne from earlier init hooks the same way.

wavedash.toml

game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"
entrypoint = "index.html"

Notes

  • main_menu label vs screen: Ren'Py checks for a main_menu label before using the main_menu screen. If you only define a screen, add an explicit label main_menu: call screen main_menu so Ren'Py actually mounts it.
  • Web build size: Ren'Py web builds can be 50MB+ with audio/image assets. Compress audio to OGG and resize images for web before building.