A lightweight, cross-platform HTML viewer for Rust.
html_view provides a minimal, ergonomic API for rendering HTML content in a native window, similar in spirit to matplotlib.pyplot.show() for visualization rather than UI development.
It is intended for debugging, inspection, and lightweight display, not for building full desktop applications.
The need/want for a tool like this came from wanting to incorporate plotting functionality into my other crates which deal with audio:
- Install the viewer application (one-time setup):
cargo install html_view_app- Add the library to your project:
cargo add html_view- Display HTML with a single line:
html_view::show("<h1>Hello, World!</h1>")?;That's it! See Usage Patterns for more examples.
- What This Is (and Is Not)
- How It Works
- Installation
- Usage Patterns
- Core Features
- Security
- Command-Line Interface
- Platform Requirements
- Building from Source
- Examples
- Contributing
- License
html_view is:
- A quick way to render HTML from Rust
- Useful for visualization, debugging, reports, and local tools
- Designed to require minimal setup and minimal code
- Perfect for one-off displays or temporary windows
html_view is not:
- A GUI framework
- A browser replacement
- A long-lived embedded webview inside your process
- A solution for complex application state or interaction
If you need a full application framework, use Tauri, egui, iced, or a native GUI toolkit directly.
html_view works by launching a small, native Tauri application as a separate process and sending it instructions over a simple JSON-based protocol.
┌─────────────────┐ JSON Files ┌──────────────────┐
│ │ ──────────────────────> │ │
│ Your Rust App │ │ html_view_app │
│ │ <──────────────────── │ (Tauri 2.0) │
│ │ Exit Status + UUID │ │
└─────────────────┘ └──────────────────┘
Process A Process B
This design:
- Keeps your Rust process lightweight and isolated
- Avoids embedding webview state or event loops
- Allows blocking or non-blocking execution
- Makes failures and crashes contained and debuggable
- Enables version compatibility checking between library and viewer
You install the viewer once, then reuse it across projects.
The easiest way to get started with bundled binary auto-download:
cargo add html_view --features bundledThe pre-built viewer binary will be automatically downloaded during the first build.
For minimal dependencies or when you prefer explicit control, install the library and viewer separately:
1. Install the library:
cargo add html_view2. Install the viewer binary:
cargo install html_view_appThe library will automatically find the binary in this order:
- Bundled binary (if
bundledfeature was used) HTML_VIEW_APP_PATHenvironment variable~/.cargo/bin/html_view_app(fromcargo install)- Same directory as your executable
target/debugortarget/release(for development)
If the binary isn't found, you'll get an error message showing all paths checked.
For using the viewer without writing Rust code:
cargo install html_view_cliSee Command-Line Interface for usage.
The simplest way to display HTML:
use html_view;
fn main() -> Result<(), html_view::ViewerError> {
html_view::show("<h1>Hello!</h1><p>Simple HTML display</p>")?;
Ok(())
}Customize window size, title, and behavior:
use html_view::ViewerOptions;
let mut options = ViewerOptions::inline_html("<h1>Custom Window</h1>");
options.window.width = Some(800);
options.window.height = Some(600);
options.window.title = Some("My App".to_string());
options.behaviour.enable_devtools = true;
html_view::open(options)?;Or use the fluent builder API:
use html_view::ViewerOptions;
ViewerOptions::new()
.width(800)
.height(600)
.title("My App")
.devtools()
.show_html("<h1>Custom Window</h1>")?;Don't wait for the window to close:
use html_view::{ViewerOptions, ViewerWaitMode, ViewerResult};
let mut options = ViewerOptions::inline_html("<h1>Non-blocking</h1>");
options.wait = ViewerWaitMode::NonBlocking;
match html_view::open(options)? {
ViewerResult::NonBlocking(mut handle) => {
// Do other work here
println!("Viewer is running with ID: {}", handle.id);
// Check if it's still running
while handle.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_millis(100));
// Do work...
}
// Or wait for it to close
let status = handle.wait()?;
println!("Viewer closed: {:?}", status.reason);
}
_ => unreachable!(),
}Load HTML from the filesystem:
use html_view::ViewerOptions;
use std::path::PathBuf;
// Single HTML file
let options = ViewerOptions::local_file(PathBuf::from("index.html"));
html_view::open(options)?;
// Application directory (with assets)
let mut options = ViewerOptions::app_dir(PathBuf::from("./dist"));
// Optional: specify entry file (defaults to index.html)
if let html_view_shared::ViewerContent::AppDir { entry, .. } = &mut options.content {
*entry = Some("main.html".to_string());
}
html_view::open(options)?;Display web content (requires explicit opt-in for security):
use html_view::ViewerOptions;
use url::Url;
let mut options = ViewerOptions::remote_url(
Url::parse("https://example.com")?
);
// Must explicitly allow remote content
options.behaviour.allow_remote_content = true;
options.behaviour.allow_external_navigation = true;
// Optional: restrict to specific domains
options.behaviour.allowed_domains = Some(vec![
"example.com".to_string(),
"api.example.com".to_string(),
]);
html_view::open(options)?;Auto-close the window after a timeout:
use html_view::ViewerOptions;
let mut options = ViewerOptions::inline_html("<h1>Auto-close in 5 seconds</h1>");
options.environment.timeout_seconds = Some(5);
html_view::open(options)?;
// Window automatically closes after 5 secondsCreate a frameless window with a custom title bar:
use html_view::ViewerOptions;
let mut options = ViewerOptions::inline_html("<h1>Frameless Window</h1>");
options.window.decorations = false;
options.window.toolbar.show = true;
options.window.toolbar.title_text = Some("My Custom App".to_string());
options.window.toolbar.background_color = Some("#2C3E50".to_string());
options.window.toolbar.text_color = Some("#ECF0F1".to_string());
html_view::open(options)?;- Minimal API: Single-function
show()for most cases,open()for advanced config - Multiple Content Types: Inline HTML, local files, app directories, remote URLs
- Execution Modes: Blocking (wait for close) or non-blocking (get a handle)
- Window Control: Size, position, decorations, transparency, always-on-top
- Cross-Platform: Native rendering on Linux (WebKitGTK), macOS (WKWebView), Windows (WebView2)
- Version Checking: Automatic compatibility verification between library and viewer
- Process Isolation: Viewer runs separately, no state pollution in your app
By default, html_view is locked down to prevent accidental security issues:
- Remote content is disabled
- External navigation is blocked
- Developer tools are disabled
- File dialogs are disabled
- Only provided content is rendered
To display remote URLs or allow navigation:
let mut options = ViewerOptions::inline_html("<h1>Hello</h1>");
options.behaviour.allow_remote_content = true;
options.behaviour.allow_external_navigation = true;
// Optional: restrict navigation to specific domains
options.behaviour.allowed_domains = Some(vec![
"example.com".to_string(),
"trusted-site.com".to_string(),
]);- Never trust user input in HTML content - sanitize it first
- Use domain allowlists when enabling external navigation
- Disable remote content unless absolutely needed
- Enable devtools only during development, not in production
- Use HTTPS for all remote URLs
The CLI provides a quick way to view HTML without writing Rust code.
cargo install html_view_cli# Inline HTML
html_view_cli html "<h1>Hello, World!</h1>"
# Local file
html_view_cli file index.html
# Application directory
html_view_cli dir ./dist --entry main.html
# Remote URL
html_view_cli url https://example.comhtml_view_cli html "<h1>Custom</h1>" \
--width 800 \
--height 600 \
--title "My App" \
--devtools \
--timeout 10See the html_view_cli README for complete documentation.
Requires WebKitGTK 4.1:
# Debian/Ubuntu
sudo apt install libwebkit2gtk-4.1-dev
# Arch Linux
sudo pacman -S webkit2gtk-4.1Note: At runtime, only the library is needed, not the -dev package:
sudo apt install libwebkit2gtk-4.1-0Uses the system WKWebView framework. No additional dependencies required.
Minimum version: macOS 10.13 (High Sierra) or later
Uses Microsoft Edge WebView2, which is:
- Included by default in Windows 11
- Available for Windows 10 via Windows Update
- Downloadable as the WebView2 Runtime
git clone https://github.com/jmg049/HTMLView.git
cd HTMLView
cargo build --workspace --releaseTo install the viewer application:
cargo install --path html_view_appImportant: The Tauri app bundles frontend assets. If you encounter issues:
# Build the entire workspace first
cargo build --workspace --release
# Then install from the built binary
cargo install --path html_view_app --forceFor development, you can run directly from the workspace:
# Run the viewer directly
cargo run -p html_view_app -- --help
# Run tests
cargo test --workspace
# Run examples
cargo run --example simpleThe repository includes several examples demonstrating different features:
# Simple inline HTML
cargo run --example simple
# Advanced configuration
cargo run --example advanced
# Timeout and auto-close
cargo run --example timeoutFor more examples, see the examples/ directory.
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is dual-licensed under:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
Built using Tauri 2.0.
