🧙 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 3 SFCs — write
.vuefiles with<script setup>, composables, and full reactivity - Kotlin/Java API — open pages and push reactive data from server-side mod code
- TypeScript types — companion CLI extracts type definitions from JARs for IDE support
- Hot reload — iterate on UI without restarting the server
- Tailwind CSS — Tailwind v4 supported out of the box in the starter project
- Per-player isolation — each player gets their own Vue app instance
For an in-depth guide, see the Getting Started Guide.
Download from either
git clone git@github.com: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.
- Sync Gradle dependencies.
- Run
runServer. - Copy
Vuetale.jarintorun/mods/. - Rerun the server and type
/vuetalein chat — you should see the test 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 |
|---|---|
| vuetale-starter | Starter template with Gradle + Vite setup |
| vuetale-companion | CLI for project setup, type extraction, and hot reload |
| vuetale-docs | Full documentation site |
Full guides, API reference, and CLI docs at the documentation site.