Skip to content

kbkpbot/vxui

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

116 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

vxui

Build cross-platform desktop apps with V + HTML/CSS/JS

License: MIT Built with V Platforms Status: Alpha

Features β€’ Quick Start β€’ Examples β€’ Documentation β€’ Contributing


πŸ“Έ Screenshots

Gallery Demo Element Plus
Gallery Element Plus
Real-time Charts Todo App
Enchart Todo App
File Upload
File Upload

πŸš€ Features

  • ⚑ WebSocket-Powered β€” Real-time bidirectional communication without HTTP overhead
  • 🎨 Use Your Browser β€” Leverage modern web technologies for beautiful UIs
  • πŸ”’ Secure by Default β€” Token-based authentication, XSS protection, and path traversal prevention
  • 🌐 Cross-Platform β€” Linux, macOS, and Windows support with auto browser detection
  • πŸ“¦ Lightweight β€” Pure V implementation, no external dependencies
  • 🎯 htmx Integration β€” Seamless integration with official htmx (no modifications required)
  • πŸ”§ Backend-to-Frontend β€” Execute JavaScript from backend with run_js()
  • πŸ‘₯ Multi-Client Support β€” Optional support for multiple browser clients
  • πŸš€ Single Executable β€” Embed frontend files into binary for easy distribution

πŸ“‹ Table of Contents

πŸ“– Introduction

vxui is a lightweight, cross-platform desktop UI framework that uses your browser as the display and V as the backend. Unlike traditional web frameworks, vxui:

  • No HTTP/HTTPS server β€” Direct WebSocket communication
  • No build step β€” Just V code and HTML files
  • No framework lock-in β€” Use any frontend libraries you like
vxui = browser + htmx + websocket + V

πŸ’‘ Motivation

  1. Every desktop has a browser β€” Modern browsers offer better rendering than native GUI toolkits
  2. WebSocket > HTTP β€” Why use a web server for desktop apps? WebSocket enables true bidirectional communication
  3. Full-stack V β€” Write your entire app in one language

πŸ“¦ Installation

Prerequisites

  • V (v0.4.0 or later)
  • Chrome, Chromium, Edge, or Firefox

Install via VPM

v install --git https://github.com/kbkpbot/vxui.git

Manual Installation

git clone https://github.com/kbkpbot/vxui.git ~/.vmodules/vxui

πŸš€ Quick Start

1. Create your app (main.v)

module main

import vxui
import x.json2

struct App {
    vxui.Context
mut:
    counter int
}

@['/clicked']
fn (mut app App) clicked(message map[string]json2.Any) string {
    app.counter++
    return '<div id="counter">Count: ${app.counter}</div>'
}

fn main() {
    mut app := App{}
    app.logger.set_level(.debug)
    vxui.run(mut app, './ui/index.html') or {
        eprintln('Error: ${err}')
        exit(1)
    }
}

2. Create your UI (ui/index.html)

<!DOCTYPE html>
<html>
<head>
    <script src="./js/htmx.js"></script>
    <script src="./js/vxui-ws.js"></script>
</head>
<body>
    <h1>Hello vxui!</h1>
    <button hx-post="/clicked" hx-swap="outerHTML">
        Click Me
    </button>
    <div id="counter">Count: 0</div>
</body>
</html>

3. Run

v run main.v

πŸ—οΈ Architecture

flowchart TB
    subgraph Frontend["Browser"]
        HTML["HTML/CSS"]
        HTMX["htmx attributes"]
        WS["vxui-ws.js"]
    end
    
    subgraph Backend["V Backend"]
        WSS["WebSocket Server"]
        Router["Router"]
        Handler["Route Handler"]
    end
    
    HTML --> HTMX
    HTMX -->|"hx-post, hx-get, etc."| WS
    WS <-->|"WebSocket (No HTTP!)"| WSS
    WSS --> Router
    Router --> Handler
    Handler -->|"HTML fragments"| WSS
    WSS -->|"Response"| WS
    WS -->|"DOM Update"| HTML
Loading

How it works

  1. Start β€” vxui finds a free port and starts a WebSocket server
  2. Launch β€” Detects and launches your system browser with the HTML file
  3. Connect β€” Browser connects to WebSocket server via vxui-ws.js
  4. Interact β€” User actions trigger WebSocket messages instead of HTTP requests
  5. Respond β€” V handlers return HTML fragments for dynamic updates

πŸ“š Examples

Basic Form Handling

See examples/test/ for a complete form handling example with:

  • Modern dark theme with glassmorphism
  • Input validation
  • Dynamic updates
  • Edit/Cancel workflow

Real-time Charts

See examples/enchart/ for:

  • Modern dashboard UI with dark theme
  • ECharts integration with gradient charts
  • Real-time data streaming with live statistics
  • Stat cards showing current/average/peak values

Gallery Demo

See examples/gallery/ for a comprehensive UI controls demo:

  • Buttons, forms, inputs
  • Progress bars, tabs, tables
  • Cards, modals, notifications
  • Dark mode toggle

Element Plus Integration

See examples/element-plus/ for Vue 3 + Element Plus integration:

  • Professional UI components (Button, Form, Table, Dialog, etc.)
  • Backend-driven notifications via run_js()
  • Demonstrates vxui with modern Vue 3 ecosystem

Run examples:

cd examples/test
v run main.v

✨ Features

Execute JavaScript from Backend

Use run_js() to execute JavaScript in the browser and get results:

// Execute on first connected client
result := app.run_js('document.title', 5000)!  // 5 second timeout
println('Page title: ${result}')

// Execute on specific client
result := app.run_js_client(client_id, 'alert("Hello!")', 3000)!

Multi-Client Support

Enable multiple browser connections:

fn main() {
    mut app := App{}
    app.multi_client = true  // Allow multiple clients
    vxui.run(mut app, './ui/index.html')!
}

// In your handlers:
fn (mut app App) broadcast_msg(msg map[string]json2.Any) string {
    // Get all connected clients
    clients := app.get_clients()
    
    // Broadcast to all
    app.broadcast('<div hx-swap-oob="true">Server update</div>')!
    
    return '<div>Sent to ${clients.len} clients</div>'
}

Window Management

Control browser window size and position:

fn main() {
    mut app := App{}
    app.set_window_size(1200, 800)
    app.set_window_position(-1, -1)  // -1 = center
    app.set_window_title('My Application')
    vxui.run(mut app, './ui/index.html')!
}

Single Executable Distribution

Embed frontend files into the binary for easy distribution:

module main

import vxui

// Embed frontend files at compile time
const index_html = $embed_file('ui/index.html')
const app_js = $embed_file('ui/app.js')
const style_css = $embed_file('ui/style.css')

struct App {
    vxui.Context
}

fn main() {
    mut app := App{}
    
    // Create packed app with embedded files
    mut packed := vxui.new_packed_app()
    packed.add_file_string('index.html', index_html.to_string())
    packed.add_file_string('app.js', app_js.to_string())
    packed.add_file_string('style.css', style_css.to_string())
    
    // Run with packed resources
    vxui.run_packed(mut app, mut packed, 'index.html')!
}

Build single executable:

v -prod main.v           # Production build (~1.4 MB)
v -prod -compress main.v # Compressed build (smaller)

Result: A single .exe file containing all frontend assets!

πŸ”’ Security

vxui includes several security features:

  • Token Authentication β€” Auto-generated security token for client verification
  • XSS Protection β€” Built-in HTML/JS escaping functions
  • Path Traversal Prevention β€” Input sanitization
  • No External Network β€” WebSocket only binds to localhost

Token Authentication

Every connection requires token verification:

fn main() {
    mut app := App{}
    // Token is auto-generated, or set manually:
    // app.token = 'my-secret-token'
    
    // Get token for debugging
    println('Token: ${app.get_token()}')
    
    vxui.run(mut app, './ui/index.html')!
}

Safe Output Example

import vxui

fn (mut app App) handler(msg map[string]json2.Any) string {
    user_input := msg['name'] or { '' }.str()
    safe := vxui.escape_html(user_input)
    return '<div>Hello ${safe}</div>'
}

Security Best Practices

  1. Always validate input β€” Use sanitize_path() for file paths
  2. Escape output β€” Use escape_html(), escape_js(), escape_attr()
  3. Keep tokens secure β€” Tokens are auto-generated and passed via URL
  4. Limit JS execution β€” Configure js_sandbox settings appropriately
fn main() {
    mut app := App{}
    // Enhanced security configuration
    app.config.js_sandbox = vxui.JsSandboxConfig{
        enabled: true
        timeout_ms: 3000
        max_result_size: 1024 * 100  // 100KB
        allow_eval: false
    }
    vxui.run(mut app, './ui/index.html')!
}

πŸ”„ Migration Guide

From v0.5.x to v0.6.0

Deprecated fields removed:

  • app.token β†’ Use app.config.token
  • app.multi_client β†’ Use app.config.multi_client
// Before (v0.5.x)
mut app := App{}
app.token = 'my-token'
app.multi_client = true

// After (v0.6.0)
mut app := App{}
app.config.token = 'my-token'
app.config.multi_client = true

From v0.4.x to v0.5.0

Configuration unified:

  • All settings now in app.config
  • Window, browser, JS sandbox settings available
// Before
app.window = vxui.WindowConfig{width: 1200, height: 800}

// After
app.config.window = vxui.WindowConfig{width: 1200, height: 800}

🌍 Browser Support

vxui auto-detects and supports:

Browser Linux macOS Windows
Chrome βœ… βœ… βœ…
Chromium βœ… βœ… ❌
Edge βœ… βœ… βœ…
Firefox βœ… βœ… βœ…
Brave βœ… ❌ ❌

πŸ“– Documentation

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development

# Clone the repo
git clone https://github.com/kbkpbot/vxui.git
cd vxui

# Run tests
v test vxui_test.v

# Format code
v fmt -w .

πŸ›‘οΈ License

This project is licensed under the MIT License.

πŸ™ Acknowledgments

  • V Language β€” The amazing language powering vxui
  • htmx β€” The frontend library for dynamic HTML

⚠️ Alpha Notice

vxui is currently in alpha stage. APIs may change, and some features are still being developed. Please report any issues you encounter!


Built with ❀️ by kbkpbot and contributors

About

vxui is a cross-platform desktop UI framework which use your browser as screen, and use V lang as backend. It reply on Websocket, no http/https, no web server!

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors