diff --git a/build-egui-web.sh b/build-egui-web.sh index 529cdfa4..766b25fa 100755 --- a/build-egui-web.sh +++ b/build-egui-web.sh @@ -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 "" diff --git a/crates/server/src/web/app.rs b/crates/server/src/web/app.rs index 067ceb72..b26c6a7c 100644 --- a/crates/server/src/web/app.rs +++ b/crates/server/src/web/app.rs @@ -21,12 +21,14 @@ 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(), @@ -34,10 +36,39 @@ impl WebApp { 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 { diff --git a/crates/server/ui/egui/README.md b/crates/server/ui/egui/README.md new file mode 100644 index 00000000..fd028eb6 --- /dev/null +++ b/crates/server/ui/egui/README.md @@ -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