# KNI

Ship MonoGame-compatible games to the web with KNI's BlazorGL WebAssembly target.

Source: https://docs.wavedash.com/engines/kni

<GithubLink href="https://github.com/wvdsh/examples/tree/main/example-kni" />
<PlaytestLink href="https://wavedash.com/playtest/kni-example/ac90400d-9531-4b45-ab7e-6e3ed43b2ebc" />

[KNI](https://github.com/kniEngine/kni) is a MonoGame-compatible fork that adds a Blazor WebAssembly target (`BlazorGL`). If you already have a MonoGame project, KNI lets you publish it to the web with minimal changes — you keep writing idiomatic `Game` / `Initialize` / `Update` / `Draw` C#, and Blazor handles the wasm plumbing.

<Note>
For desktop-only MonoGame setups, see the [MonoGame guide](/engines/monogame). This page covers KNI's web target specifically.
</Note>

## Toolchain

- .NET 8 SDK (or newer) — [dotnet.microsoft.com/download](https://dotnet.microsoft.com/download/dotnet/8.0)
- A Blazor WebAssembly project using KNI's `BlazorGL` target (see the example's `Pong.csproj` for references)

## Build for web

Publish in Release mode — the Blazor publish output is in `bin/Release/net8.0/publish/wwwroot`. Copy that folder to whatever path you set as `upload_dir`:

```bash
dotnet publish -c Release
cp -R bin/Release/net8.0/publish/wwwroot/. build/
```

The example ships a `build.sh` that wraps this.

## SDK integration

C# can call `Wavedash` through `IJSRuntime`. The recommended pattern is a small `wavedash-bridge.js` in `wwwroot/` that waits for the SDK to be injected and exposes thin wrappers C# invokes:

```javascript
// wwwroot/wavedash-bridge.js
(function () {
  const Wavedash = window.Wavedash;

  window.wavedashInit = () => Wavedash.init({ debug: true });

  window.wavedashUpdateLoadProgress = (v) => {
    Wavedash.updateLoadProgressZeroToOne(Math.max(0, Math.min(1, Number(v) || 0)));
  };
})();
```

Load it from your Blazor page, inject `IJSRuntime`, and call it from `Initialize`:

```csharp
[Inject] private IJSRuntime JS { get; set; } = default!;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await JS.InvokeVoidAsync("wavedashUpdateLoadProgress", 1.0);
        await JS.InvokeVoidAsync("wavedashInit");
    }
}
```

Add a `window.wavedashX` function to the bridge for every SDK method you need (leaderboards, achievements, cloud saves, etc.) and invoke it from C#. The [Functions reference](/sdk/functions) lists every public SDK method.

## wavedash.toml

```toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"
```

<Note>
`entrypoint` defaults to `index.html` — the Blazor publish output already includes one, so you can omit `entrypoint` from your `wavedash.toml`.
</Note>
