Skip to content

API Reference

DooDesch edited this page Jul 27, 2026 · 2 revisions

API Reference

🛟 Need help or found a bug? Get support at support.doodesch.de/sideload.

The whole surface, both sides. Everything on the C# side is a no-op when Sideload is not installed, and every call must be made from the Unity main thread.

C# - Apps

AppHandle Apps.Register(string id, string bundlePrefix,
                        string title = null, string iconLabel = null,
                        Assembly hostAssembly = null)

Declares an app. It appears on the in-game phone with its own icon and renders index.html from your bundle.

Parameter Meaning
id Stable and unique. Also the folder name under Mods/ that overrides your embedded files, and the key for s1.storage.
bundlePrefix Embedded-resource prefix of your web files - the LogicalName prefix from your csproj.
title App title. Defaults to id.
iconLabel Caption under the home-screen icon. Defaults to the title.
hostAssembly The assembly holding the bundle. Defaults to the caller's; pass it if you wrap this call in a helper.

Load-order proof: registering before Sideload has loaded is fine, the call replays once the host appears.

bool Apps.Available

True only when the host is installed and bound. You rarely need it - the API is a safe no-op when absent. Use it to decide whether to build a fallback UI of your own.

C# - AppHandle

Every method returns the handle, so they chain.

AppHandle OnCall(string name, Func<string, string> handler)

Answers s1.call("<name>", arg). Runs on the Unity main thread in the same frame, so it may touch game state directly. Throwing is fine and surfaces as a logged error rather than taking the frame down.

void Emit(string name, string payload = "")

Pushes at s1.on("<name>", fn). Call it when something actually changed, from your update loop - never from inside an OnCall handler.

AppHandle AllowHost(string host)

Lets your page reach one host with fetch. The allowlist starts empty and only your mod can add to it. A bare host name; *.example.com covers one label under it but not example.com itself.

AppHandle Orientation(params string[] supported)

Which ways round the phone may hold the app, in preference order. The first is what it opens in; naming a second is what lets the player turn it. Saying nothing means landscape only.

AppHandle Badge(int count)

The unread count on the home-screen icon. Zero clears it, above 99 reads as "99+". Survives the phone being rebuilt.

AppHandle Notify(string title, string subtitle = "")

Raises one of the game's own phone notifications, carrying your app's icon. Nothing happens if the app is not on a phone yet.

bool IsOnScreen { get; }

True while your app is the one the phone shows. Ask before interrupting.

AppHandle Image(string name, byte[] png)

Registers a picture your mod produced at runtime, for the page to draw with src="s1://<name>". Null or empty bytes remove it. Supplying the same name again replaces the picture.

string Id { get; }

JavaScript - s1

s1.call(name, argument = '')   // -> string, synchronous, same frame
s1.on(name, handler)           // handler(payload)

s1.storage.get(key, fallback = '')
s1.storage.set(key, value)
s1.storage.remove(key)
s1.storage.clear()

s1.orientation                 // "landscape" | "portrait"
s1.setOrientation(value)       // refused unless the app declared it

s1.appId                       // the id the app was registered under

JavaScript - document and elements

See JavaScript, DOM and Events for the full list and the five event types.

document.getElementById(id)      document.querySelector(sel)
document.querySelectorAll(sel)   document.createElement(tag)
document.addEventListener(type, fn)

el.textContent   el.className   el.id   el.value
el.appendChild(child)   el.replaceChildren()   el.remove()
el.setAttribute(n, v)   el.getAttribute(n)     el.removeAttribute(n)
el.classList.add/remove/toggle/contains
el.style.setProperty(name, value)
el.querySelector(sel)   el.querySelectorAll(sel)
el.addEventListener(type, fn)
el.scrollToEnd()

JavaScript - globals

document, s1, console, fetch, Promise, setTimeout, setInterval, clearTimeout, clearInterval.

No window, no navigator, no localStorage.

Bundle files

File Required What it is
index.html yes The page. No <html>/<head>/<body> boilerplate needed.
app.css no Referenced with <link rel="stylesheet" href="app.css">. Any name works.
app.js no Referenced with <script src="app.js">. Any name works.
icon.png no The home-screen icon. Square, 256x256 is plenty.
s1.css - Ships inside Sideload. <link rel="stylesheet" href="s1.css"> resolves for every app and gives you the game's own design tokens as CSS variables.

Any file of the same name under Mods/<appId>/ wins over the embedded copy.

ABI

Sideload.Api finds the host through Sideload.Bridge.SideloadBridge by reflection and binds plain BCL delegates, so the two assemblies share no type. New capabilities are added as new delegate fields: an older shim simply leaves them null and those calls stay no-ops. AbiVersion is bumped only if an existing signature ever changes, at which point an old shim refuses to bind rather than failing halfway.

Clone this wiki locally