One library for the WebGUI Minecraft mod. A framework-agnostic core, plus React, Vue and Svelte bindings that are thin wrappers over it.
Replaces @webgui/react, @webgui/vue and @webgui/svelte, which were three parallel
implementations of the same logic and had to be updated in lockstep every time the mod
gained an event. Those packages still work and now re-export this one.
npm install @webgui/clientReact, Vue and Svelte are optional peer dependencies — importing the core pulls in none of them.
import { clientStore, deathStore, runCommand, respawn, isInMod } from '@webgui/client';
if (isInMod()) {
clientStore.subscribe(() => {
const c = clientStore.get();
document.querySelector('#hp').textContent = `${c.health} / ${c.maxHealth}`;
});
}Every store has the same three members:
| Member | Purpose |
|---|---|
subscribe(listener) |
Registers a no-argument listener; returns the unsubscribe function. |
get() |
The current value, or null before the mod has sent anything. |
getServerSnapshot() |
Always null — there is no mod during server rendering. |
import { useWebGUIClient, useWebGUIDeath, useRespawn } from '@webgui/client/react';
function DeathScreen() {
const death = useWebGUIDeath();
const respawn = useRespawn();
if (!death) return null;
return (
<div>
<h1>You died</h1>
<p>{death.deathMessage}</p>
{death.canRespawn && <button onClick={respawn}>Respawn</button>}
</div>
);
}<script setup lang="ts">
import { useWebGUIDeath, respawn } from '@webgui/client/vue';
const death = useWebGUIDeath();
</script>
<template>
<div v-if="death">
<h1>You died</h1>
<p>{{ death.deathMessage }}</p>
<button v-if="death.canRespawn" @click="respawn">Respawn</button>
</div>
</template><script lang="ts">
import { webguiDeath, respawn } from '@webgui/client/svelte';
</script>
{#if $webguiDeath}
<h1>You died</h1>
<p>{$webguiDeath.deathMessage}</p>
{#if $webguiDeath.canRespawn}
<button on:click={respawn}>Respawn</button>
{/if}
{/if}| Core | React | Vue | Svelte |
|---|---|---|---|
clientStore |
useWebGUIClient() |
useWebGUIClient() |
webguiClient |
entityStore |
useWebGUIEntity() |
useWebGUIEntity() |
webguiEntity |
deathStore |
useWebGUIDeath() |
useWebGUIDeath() |
webguiDeath |
selectorStore(fn) |
useWebGUISelector(fn) |
useWebGUISelector(fn) |
webguiSelector(fn) |
Use a selector when a component needs one field. The mod pushes client updates several
times a second, so a component reading only health should not re-render every time the
player walks.
postToGame, closeGui, runCommand, respawn — plain functions in every entry point.
React also exports usePostToGame, useCloseGui, useRunCommand and useRespawn, which
return the same functions with stable identity for dependency arrays.
All four are no-ops outside the mod, so a page can run in a normal browser tab without guards at every call site.
| Core | React | Vue | Svelte |
|---|---|---|---|
isInMod() |
— | — | — |
isReady(value) |
— | — | — |
getToken(param?) |
useWebGUIToken(param?) |
useWebGUIToken(param?) |
webguiToken(param?) |
onWebGUIEvent(name, fn) |
useWebGUIEvent(name, fn) |
useWebGUIEvent(name, fn) |
onWebGUIEvent(name, fn) |
The mod sends webgui:death once, immediately after the document loads, and sets
window.webgui.client / .entity / .death before that. Every store reads those
snapshots at import time, so a component that mounts a tick late still sees the value —
a bare addEventListener in a component would miss it.
The hook and store names are unchanged, so the import path is usually the only edit:
- import { useWebGUIClient } from '@webgui/react'
+ import { useWebGUIClient } from '@webgui/client/react'- import { webguiClient } from '@webgui/svelte'
+ import { webguiClient } from '@webgui/client/svelte'One rename: Svelte's onWebGUIEvent and webguiToken now also exist under those names in
the core, and the React/Vue entries expose them as useWebGUIEvent / useWebGUIToken as
before.
MIT