Overview
LiquidBounce features a powerful theme system that allows complete customization of the client’s user interface. Themes are built using Svelte and compiled to modern web components that integrate seamlessly with the client’s browser-based UI.
Themes are stored in the themes/ directory and can be loaded from local files, the marketplace, or bundled resources
Theme Manager
The ThemeManager handles theme loading, activation, and browser integration:
object ThemeManager : Config ( "theme" ) {
internal val themesFolder = File (ConfigSystem.rootFolder, "themes" )
val themes: List < Theme >
var theme: Theme ?
var shaderEnabled by boolean ( "Shader" , false )
}
Source: integration/theme/ThemeManager.kt:47-90
Theme Architecture
Themes follow a specific structure for organization and functionality:
Theme Directory
theme.json
Svelte Structure
themes/
└── my-theme/
├── theme.json # Theme metadata
├── src/ # Svelte source files
│ ├── App.svelte
│ ├── routes/
│ └── components/
├── public/ # Static assets
│ ├── logo.png
│ └── background.jpg
└── dist/ # Compiled output
└── bundle.js
{
"id" : "my-theme" ,
"name" : "My Custom Theme" ,
"version" : "1.0.0" ,
"author" : "YourName" ,
"description" : "A beautiful custom theme" ,
"routes" : [
"clickgui" ,
"hud" ,
"settings" ,
"marketplace"
],
"background" : {
"image" : "public/background.jpg" ,
"shader" : "shaders/background.glsl"
}
}
The theme uses Svelte components for the UI: src/
├── App.svelte # Main app component
├── routes/ # Route components
│ ├── clickgui/
│ ├── hud/
│ └── settings/
├── components/ # Reusable components
│ ├── Button.svelte
│ ├── Slider.svelte
│ └── Module.svelte
└── stores/ # Svelte stores
└── modules.js
The default LiquidBounce theme is located in src-theme/src
Theme Loading Priority
Themes are loaded in a specific priority order:
Local Themes (Highest Priority)
Themes in the themes/ folder (excluding “default”): themesFolder. listFiles { it.isDirectory }
?. forEach { file ->
if ( ! file.name. equals ( "default" , true )) {
Theme. load (Theme.Origin.LOCAL, file. relativeTo (themesFolder))
}
}
Reference: ThemeManager.kt:134-146
Marketplace Themes
Themes installed from the marketplace: MarketplaceManager. getSubscribedItemsOfType (MarketplaceItemType.THEME)
. forEach { item ->
val installationFolder = item. getInstallationFolder ()
Theme. load (Theme.Origin.MARKETPLACE, relativeFile)
}
Reference: ThemeManager.kt:149-158
Bundled Theme (Fallback)
The default LiquidBounce theme bundled with the client: suspend fun init () {
includedTheme = Theme. load (Theme.Origin.RESOURCE, File ( "liquidbounce" ))
}
Reference: ThemeManager.kt:117-120
Theme Origins
Themes can originate from three sources:
enum class Origin ( val external : Boolean ) {
RESOURCE ( false ), // Bundled with client
LOCAL ( true ), // User's themes folder
MARKETPLACE ( true ) // Downloaded from marketplace
}
External themes can be set as “temporary” for development purposes
Browser Integration
Themes render through an integrated browser backend:
Open Browser
Input-Aware Browser
fun openImmediate (
customScreenType: CustomScreenType ? = null ,
markAsStatic: Boolean = false ,
settings: BrowserSettings
): Browser {
val backend = BrowserBackendManager.backend
return backend. createBrowser (
getScreenLocation (customScreenType, markAsStatic).url,
settings = settings
)
}
Source: ThemeManager.kt:174-206
Screen Types
Themes can define routes for different screen types:
ClickGUI - Module configuration interface
HUD - Heads-up display elements
Settings - Client settings interface
Marketplace - Marketplace browser
Account Manager - Account management
Custom Screens - Plugin-defined screens
fun getScreenLocation (
customScreenType: CustomScreenType ? = null ,
markAsStatic: Boolean = false
): ScreenLocation {
val theme = theme. takeIf { theme ->
customScreenType == null || theme?. isSupported (customScreenType.routeName) == true
} ?: includedTheme // Fallback to default theme
return ScreenLocation (theme, theme. getUrl (customScreenType?.routeName, markAsStatic))
}
Reference: ThemeManager.kt:216-227
Background System
Themes can provide custom backgrounds with optional shader support:
Image Background
Shader Background
fun loadBackgroundAsync (): CompletableFuture < Unit > = renderScope. future {
theme?. loadBackgroundImage ()
}
fun drawBackground (context: GuiGraphics , width: Int , height: Int ,
mouseX: Int , mouseY: Int , delta: Float ): Boolean {
val background = theme?.backgroundImage ?: return false
background. draw (context, width, height, mouseX, mouseY, delta)
return true
}
var shaderEnabled by boolean ( "Shader" , false )
. onChange { enabled ->
if (enabled) {
renderScope. launch {
theme?. compileShader ()
includedTheme?. compileShader ()
}
}
return @onChange enabled
}
fun drawBackground ( .. .): Boolean {
val background = if (shaderEnabled) {
theme?.backgroundShader
} else {
theme?.backgroundImage
} ?: return false
background. draw (context, width, height, mouseX, mouseY, delta)
return true
}
Reference: ThemeManager.kt:96-106, 237-246
Building Themes
Themes are built using standard web development tools:
Install Dependencies
cd themes/my-theme
npm install
Required dependencies:
svelte - Component framework
vite - Build tool
typescript - Type safety (optional)
Develop Theme
This starts a development server with hot reload at http://localhost:5173
Build Production Bundle
Creates optimized bundle in dist/ directory
Test in Client
Place the theme in the themes/ folder and reload:
Default Theme Structure
The bundled LiquidBounce theme serves as a reference implementation:
src-theme/
├── public/ # Static assets
├── src/
│ ├── App.svelte # Root component
│ ├── app.scss # Global styles
│ ├── colors.scss # Color palette
│ ├── integration/ # Client integration
│ ├── routes/ # Screen routes
│ │ ├── clickgui/
│ │ ├── hud/
│ │ ├── settings/
│ │ └── marketplace/
│ ├── theme/ # Theme utilities
│ └── util/ # Helper functions
├── svelte.config.js
├── vite.config.ts
└── package.json
Reference: src-theme/src/ directory structure
Client Integration API
Themes can interact with the client through the integration API:
Module Access
Events
Client State
// Get all modules
const modules = await window . client . getModules ();
// Toggle module
await window . client . toggleModule ( "KillAura" );
// Get module settings
const settings = await window . client . getModuleSettings ( "KillAura" );
// Update setting
await window . client . updateSetting ( "KillAura" , "Range" , 4.5 );
Svelte Stores
Use Svelte stores for reactive state management:
import { writable , derived } from 'svelte/store' ;
// Module store
export const modules = writable ([]);
// Filter enabled modules
export const enabledModules = derived (
modules ,
$modules => $modules . filter ( m => m . enabled )
);
// Load modules from client
async function loadModules () {
const data = await window . client . getModules ();
modules . set ( data );
}
Theme Customization
Customize colors, fonts, and styles:
Color Palette
Component Styles
// colors.scss
$primary : #00a8ff ;
$secondary : #6c757d ;
$success : #28a745 ;
$danger : #dc3545 ;
$warning : #ffc107 ;
$info : #17a2b8 ;
$background : #0a0e27 ;
$surface : #1a1f3a ;
$text : #ffffff ;
$text-secondary : #a0aec0 ;
Resource Management
The theme manager handles resource reloading:
internal val reloader = ResourceManagerReloadListener { resourceManager ->
themes. forEach { it. onResourceManagerReload (resourceManager) }
logger. info ( "Reloaded ${ themes.size } themes." )
}
Reference: ThemeManager.kt:108-111
Best Practices
Use Reactive Stores Leverage Svelte’s reactivity for automatic UI updates
Optimize Assets Compress images and minify CSS/JS for faster loading
Support All Routes Implement all required screen types for full compatibility
Test Responsively Ensure themes work at different resolutions
Follow Design System Maintain consistent spacing, colors, and typography
Document Features Include README with theme features and customization
Themes have access to the client integration API. Only load themes from trusted sources.
Publishing Themes
Share your theme on the LiquidBounce Marketplace:
Build production bundle
Create theme.json with metadata
Package theme directory
Submit to marketplace with:
Screenshots
Description
Version info
Supported routes
Development Tips
Hot Reload During Development
Use temporary theme loading for rapid iteration: ThemeManager.theme = Theme. load (Theme.Origin.LOCAL, File ( "dev-theme" ))
Access browser DevTools for debugging:
Press F12 to open DevTools
Use console.log() for debugging
Inspect elements and network requests
Enable type safety for better development experience: interface Module {
name : string ;
category : string ;
enabled : boolean ;
settings : Record < string , any >;
}
Next Steps
Modules Learn about the module system
Scripts Extend themes with custom scripts
Theme Examples Explore complete theme examples
API Reference Complete theme API documentation