Vuetale is a library mod that allows developers to create complex UI systems using a modern webdev environment (TypeScript + Vue + Vite) and bridges it cleanly to Java
🧙 Sponsord by Hytale Modding Grant Program
Build Hytale mod UIs with Vue 3, TypeScript, and Kotlin/Java.
Vuetale is a Hytale mod library that brings modern frontend development to Hytale mod interfaces. Write reactive, component-based UIs in Vue SFCs, compile them through Vite, and drive them from your Kotlin/Java mod code — all with full type safety.
Vuetale embeds a Node.js/V8 engine inside your mod's JVM process. Vue components are compiled by Vite at build time and output as JavaScript bundles into your mod's src/main/resources/vuetale/ folder. At runtime, Vue's render output is translated through a custom bridge into native Hytale UI elements — no HTML, no CSS parsing, no browser involved.
Vue SFC → Vite build → resources/vuetale/<module>/ → loaded by JVM mod → native Hytale UI.vue files with <script setup>, composables, and full reactivityFor an in-depth guide, see the Getting Started Guide.
Download from either
git clone [email protected]:KelpyCode/vuetale-starter.git --recurse-submodules my-mod-project
cd my-mod-project
rm -rf .git
rm -rf src/ui/.gitCopy Vuetale-*.jar to lib/Vuetale.jar.
runServer.Vuetale.jar into run/mods/./vuetale in chat — you should see the test UI.src/ui)pnpm install
pnpm vt config server-mods <absolute-path-to-run/mods>
pnpm vt config resources <path-to-src/main/resources>
pnpm vt extract
pnpm vt dev true
pnpm watchThat's it. Vite watches your Vue files and outputs compiled bundles into src/main/resources/vuetale/<module>/, which the server picks up automatically.
// In your plugin setup function
ModuleRegistry.registerModule("myMod", Plugin::class.java)val ui = PlayerUiManager.openPage(
playerRef,
ref as Ref<EntityStore>,
store as Store<EntityStore>,
"myMod", // matches vuetale-plugin.json name
"TestPage" // matches src/ui/lib/pages/TestPage.vue
)
// Push data to the Vue page
ui.setData("playerName", "Steve")
ui.setData("health", 20)
ui.setData("items", listOf("Sword", "Shield", "Potion"))Any serializable value works — primitives, lists, maps, and data classes.
<script setup lang="ts">
import { useData } from 'vt:@core/composables/useData'
import { Common } from 'vt:@core/components/Common'
const playerName = useData<string>('playerName', 'Unknown')
const items = useData<string[]>('items', [])
</script>
<template>
<Common.DecoratedContainer :anchor="{ Width: 500, Height: 300 }">
<template #title>
<Common.Title :text="`${playerName}'s Inventory`"/>
</template>
<template #content>
<Group layout-mode="TopScrolling" :anchor="{ Full: 1 }">
<Common.TextButton
v-for="item in items"
:key="item"
:text="item"
@activating="() => console.log(item)"
/>
</Group>
</template>
</Common.DecoratedContainer>
</template>| Tool | Version |
|---|---|
| Java | 25 |
| Kotlin | 2.x |
| Node.js | 20+ |
| pnpm | any |
| Vue | 3.5+ |
| Vite | 7+ |
| Project | Description |
|---|---|
| <a href="https://github.com/KelpyCode/vuetale-starter" target="_blank" rel="nofollow">vuetale-starter</a> | Starter template with Gradle + Vite setup |
| <a href="https://github.com/KelpyCode/vuetale-companion" target="_blank" rel="nofollow">vuetale-companion</a> | CLI for project setup, type extraction, and hot reload |
| <a href="https://github.com/KelpyCode/vuetale-docs" target="_blank" rel="nofollow">vuetale-docs</a> | Full documentation site |
Full guides, API reference, and CLI docs at the documentation site.
0 Comments