Skip to main content
Version: 2026.0.311 🚧

Building for Web - Godot

Overview​

The Skillz SDK for Godot includes a Web backend, so a Godot game can be played in a browser window hosted by Skillz with the same API you use for your iOS and Android builds. A Godot Web build runs inside the Skillz web portal, which loads it in an iframe; the SDK's Web backend is pure GDScript talking to the portal through a small bridge script, and there is no native extension on Web.

This guide walks through the export preset, how to test in the editor and in a browser, and how to package the build for the Skillz Developer Console.

Features​

All features of the mobile SDK are available on the web except for:

  1. Brackets and Real-time Tournaments
  2. Chat
  3. Progressive Leagues
  4. Payment support for Master Card, Discover, and Apple Pay
  5. Audio API (games will use the SFX and background music of the mobile version)
  6. Seasons API
  7. Bot matches (abort_bot_match() aborts the match instead)
  8. The progression room (launch_progression_room() returns to the portal)
  9. Match metadata and sync play

Each unsupported call logs a warning instead of failing, so shared game code keeps working.

Integration​

Your game code does not change between mobile and web: the same Skillz facade, signals and score reporting apply. The steps to enable a web version are:

  1. Add a Web export preset. In Project > Export, add a Web preset. The Skillz export plugin applies three settings to every Web preset itself, so they do not appear in the preset's Options tab and there is nothing for you to set:

    • HTML > Custom HTML Shell is res://addons/skillz/web/skillz_shell.html. This shell is how your game communicates with the Skillz portal.
    • Variant > Thread Support is off. Threads need cross-origin isolation, which the embedding Skillz page cannot provide.
    • Variant > Extensions Support is off. The Skillz Web backend is GDScript, so Skillz itself needs no extension; but this switch is for the whole export, so no GDExtension of any kind loads in a Skillz Web build. Godot's Web extension support needs the same cross-origin isolation headers as threads (Exporting for the Web), and the Skillz page cannot send them, so there is no supported way to turn it on. If your game uses another GDExtension, give it a GDScript fallback and branch on OS.has_feature("web").

    Two settings are yours to make:

    • Resources > Filters to exclude files/folders: addons/skillz/skillz.gdextension, addons/skillz/skillz_export.gd*, addons/skillz/sidekick/editor/*. The native extension is not used on Web; the plugin also skips skillz.gdextension on Web exports, so the filter mainly keeps the editor-only scripts out of the pack.
    • Application > Config > Version in Project Settings: set it. It is part of the build fingerprint.

Web preset, Resources tab, with the exclude filter set

  1. Environment is not a build setting on Web. The Skillz page that loads the build decides whether it talks to sandbox or production, so one build can be uploaded to either. The export prints a line saying that skillz/environment is not applied to Web builds.

  2. Call launch_skillz() on start-up if you do not already. The Skillz Web SDK assumes your game is ready to receive match_will_begin as soon as it has loaded.

note

Be sure to skip any pre-Skillz launch user experience flows, such as a First Time User Experience (FTUE) or game tutorial. As described in our Tutorial Best Practices, we recommend games have this occur just before the player's first match.

  1. Optional: tab-hidden behaviour. Browsers stop rendering a hidden tab, and on return the engine would deliver one frame covering the whole time away. The SDK freezes game time while the tab is hidden and resumes it afterwards (skillz/web_freeze_when_hidden, on by default). If your game keeps its own wall-clock timer, handle NOTIFICATION_APPLICATION_FOCUS_OUT and NOTIFICATION_APPLICATION_FOCUS_IN yourself. Two details of the freeze: the first frame after the tab returns runs _process(0.0) and _physics_process(0.0), so guard any division by delta; and SceneTree.paused is never touched, so your own pause menu keeps working. Engine.time_scale is global: if your game changes it (slow motion, say) while the tab is hidden, your value is kept rather than restored. Set skillz/web_freeze_when_hidden to false to opt out.

Testing​

Testing in the Editor​

Press Play in the editor: Skillz SIDEkick for Godot simulates the whole tournament loop with no server, which covers the game logic you share with the mobile builds.

Testing in a Browser​

Export the Web preset to a folder and serve it from a local web server (Godot's Remote Debug > Run in Browser works). Without a Skillz page around it the shell shows no lobby: the game loads, logs [SkillzShell] game <id>, SDK <version>, host none (not embedded by a Skillz page) in the browser console, and Skillz.get_instance().is_available() is false. That is expected; it verifies the export itself. A real match requires the build to be loaded by the Skillz portal, which is what the sandbox upload below gives you.

Browser Lifecycle​

These behaviours are defined by the SDK and need no code:

CaseBehaviour
Page refresh mid-matchThe match is dropped and the game starts with none; the next entry starts a new match. The interrupted match stays open on the server until its abandon timeout.
Tab hiddenGame time freezes and resumes where it stopped.
Tab closedResolved on the server by the abandon timeout.
Back navigation in the portalYour game receives skillz_will_exit; reset your scene there.
Cannot start (no WebGL2 or WebAssembly)The shell shows "This game can't start in this browser" and reports the reason to the portal.
Any other load failure (missing file, bad download)The shell shows "This game couldn't load" and reports the reason to the portal. Both load failures are logged as [SkillzShell] ... in the browser console.

Packaging for the Developer Console​

The Developer Console takes the exported Web build as a zip:

  1. In Project > Export, export the Web preset into an empty folder with the file name index.html. Godot writes index.html, index.js, index.wasm, index.pck and the audio worklet scripts there; the Skillz export plugin adds skillz_web_bridge.js next to them and stamps your skillz/game_id into index.html.
  2. Zip the contents of that folder, so those files sit at the root of the zip with no enclosing folder.
  3. Upload the zip through the Developer Console as the game's Web build.
caution

The fingerprint rule. The Developer Console fingerprints the sizes of index.pck, index.js and index.wasm inside the zip; the Skillz portal fingerprints the sizes it is served. They must be the same files, so always upload the zip through the Developer Console and let it deploy the files; do not copy a different export, or a recompressed one, to the hosting location by hand. Sandbox skips the check; production rejects every score on a mismatch.

Troubleshooting​

  • Scores rejected on production but fine on sandbox. A fingerprint mismatch: the files served are not the ones in the zip the Developer Console registered. Export again and upload the new zip through the Developer Console, so the registered sizes and the served files come from the same export.
  • Blank canvas, or the game never starts. Open the browser console and look for [SkillzShell] lines: the load-failure reason is printed there and also sent to the portal. skillz_web_bridge.js did not load means the file is missing next to index.html.

With that, your game is ready to publish on https://games.skillz.com. Please have a look at our Web Publishing guide for details on how to get your game hosted on the Skillz web site, and review our Web Best Practices for tips on how to ensure a great player experience.

If you encounter any issues, please export your browser console log, and reach out to us at integrations@skillz.com.