Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions build-egui-web.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ echo ""
echo "📦 The egui web UI can now be served at /egui endpoint"
echo ""
echo "Next steps:"
echo " 1. Start the server: localgpt daemon start"
echo " 2. Open browser: http://localhost:31327/egui"
echo " 1. Build the server: cargo build --package localgpt --bin localgpt --release"
echo " 2. Start the daemon: localgpt daemon start (or target/release/localgpt daemon start)"
echo " 3. Open browser: http://localhost:31327/egui"
echo ""
echo "Note: The egui web UI is a PoC that reuses the desktop egui code."
echo " It demonstrates code reuse between desktop and web platforms."
echo ""
37 changes: 34 additions & 3 deletions crates/server/src/web/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,54 @@ struct Message {
struct Status {
connected: bool,
model: String,
version: String,
}

impl WebApp {
/// Create a new web app
pub fn new(_cc: &eframe::CreationContext<'_>) -> Self {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
// Configure visuals for dark theme
Self::configure_style(&cc.egui_ctx);

Self {
message_input: String::new(),
messages: Vec::new(),
session_id: None,
status: Status {
connected: true,
model: "claude-cli/opus".to_string(),
version: "0.3.0".to_string(),
},
}
}

fn configure_style(ctx: &egui::Context) {
// Set dark mode
ctx.set_visuals(egui::Visuals::dark());

let mut style = (*ctx.style()).clone();

// Use slightly larger text
style.text_styles.insert(
egui::TextStyle::Body,
egui::FontId::new(14.0, egui::FontFamily::Proportional),
);
style.text_styles.insert(
egui::TextStyle::Button,
egui::FontId::new(14.0, egui::FontFamily::Proportional),
);
style.text_styles.insert(
egui::TextStyle::Heading,
egui::FontId::new(20.0, egui::FontFamily::Proportional),
);

// Rounded corners
style.visuals.window_corner_radius = egui::CornerRadius::same(8);
style.visuals.widgets.noninteractive.corner_radius = egui::CornerRadius::same(4);
style.visuals.widgets.inactive.corner_radius = egui::CornerRadius::same(4);
style.visuals.widgets.hovered.corner_radius = egui::CornerRadius::same(4);
style.visuals.widgets.active.corner_radius = egui::CornerRadius::same(4);

ctx.set_style(style);
}
}

impl eframe::App for WebApp {
Expand Down
69 changes: 69 additions & 0 deletions crates/server/ui/egui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Egui Web UI - Proof of Concept

This directory contains the compiled WebAssembly artifacts for the LocalGPT egui web UI.

## Overview

This is a PoC demonstrating code reuse between desktop and web platforms using egui/eframe. The same egui UI code runs on both:
- **Desktop**: Native application (compiled with default features)
- **Web**: WASM application (compiled with `egui-web` feature)

## Building

Run the build script from the repository root:

```bash
./build-egui-web.sh
```

This will:
1. Install wasm32-unknown-unknown target (if needed)
2. Install wasm-bindgen-cli (if needed)
3. Build the server crate for WASM with `egui-web` feature
4. Generate JavaScript bindings
5. Optionally optimize with wasm-opt

## Output Files

- `localgpt_server_bg.wasm` (~1.3 MB) - The compiled WebAssembly module
- `localgpt_server.js` (~76 KB) - JavaScript bindings for the WASM module

## Usage

After building:

1. Start the LocalGPT daemon:
```bash
localgpt daemon start
```

2. Open your browser to:
```
http://localhost:31327/egui
```

## Architecture

The web UI (`crates/server/src/web/`) implements a simple chat interface that:
- Shows a welcome screen when no messages exist
- Provides a text input for messages
- Displays a Send button
- Uses egui's dark theme with custom styling
- Returns mock responses (PoC - not connected to backend yet)

## Code Reuse

Key patterns for desktop/web code sharing:
- `WebApp` struct in `web/app.rs` mirrors the desktop `DesktopApp` structure
- `configure_style()` method shared between both implementations
- Same egui/eframe version (v0.33.3) for consistency
- Conditional compilation with `#[cfg(feature = "egui-web")]`

## Next Steps

To make this production-ready:
- Connect to the HTTP API backend (WebSocket or REST)
- Add session management
- Implement streaming responses
- Add error handling
- Improve styling and UX