Skip to content

Wrapping up Module 5

Module 5 has covered a lot of ground. You started with a bare WebView widget and a simple HTML string, and ended with a full bidirectional communication layer between Ruby and JavaScript, live data visualisation, interactive maps, and a proper markdown editor with syntax highlighting.

What you built

Lesson 5.1 introduced the WebView widget and its three content loading approaches. You saw why load_url with a base64 data URI is more reliable than set_page for pages containing JavaScript, and how CDN script tags and local base64-encoded assets each have their place.

Lesson 5.2 covered the JavaScript bridge in three progressively capable demos. Navigation interception for simple one-way messaging, the script message handler for the WebKit native approach, and the JsBridge class for full bidirectional RPC. The critical lesson — that Ruby must trigger the ready event via run_script after registering the handler, never relying on JS to emit it from the page script — came from a real bug discovered during development.

Lesson 5.3 built a live sensor dashboard with Chart.js fed by Ruby timers. The full multi-file app structure was established: js_bridge.rb and js_bridge_client.js as a library pair, HTML in a dedicated Ruby module, panels with clean public interfaces, and a thin frame as coordinator.

Lesson 5.4 embedded a Leaflet map with city navigation and click-to-place markers. Map events flowed to Ruby, Ruby controlled the map through registered JS methods, and marker state was kept in sync across both sides using IDs.

Lesson 5.5 completed the arc by upgrading the Module 4 markdown editor from HtmlWindow to WebView. Only one file changed — PreviewPanel — while the frame, the model, and the editor panel were untouched. The improvement in the preview was immediate and striking.

The patterns to take forward

The bridge library pair. js_bridge.rb and js_bridge_client.js drop into any WebView app unchanged. Copy them, require_relative the Ruby side, load the JS side as a base64 data URI.

The ready pattern. Always:

1
2
3
4
5
@webview.evt_webview_loaded(@webview.id) do
  next if @webview.current_url == 'about:blank'
  @webview.add_script_message_handler('bridge')
  @bridge.run_script("RubyBridge.emit('ready', {})")
end

Never rely on JS emitting ready from the page script.

HTML in a Ruby module. Keep page HTML in lib/html/page_name.rb as a module with a class method. Keeps frames clean and makes the HTML easy to find and edit.

Panels with clean interfaces. The frame never touches @bridge or @webview directly. It calls map_panel.fly_to(lat, lng) or chart_panel.push_data(series, value, label). WebView details stay inside the panel.

load_url with base64 for pages with JavaScript. set_page is fine for static content. For anything with scripts, use:

1
2
encoded = Base64.strict_encode64(html)
@webview.load_url("data:text/html;base64,#{encoded}")

What was not covered

Offline tile caching. The route planner app uses a thread pool to pre-cache OpenStreetMap tiles for offline use. This is covered in a separate post on the route planner.

Complex Leaflet usage. Polylines, GeoJSON import and export, context menus on the map, and drag-to-reorder markers are all covered in the route planner post.

WebView security. For apps that load external URLs rather than self-contained HTML, navigation interception becomes important for security — preventing the WebView from navigating away from your content. The evt_webview_navigating pattern from Demo 1 is the foundation.

Multiple WebView pages. All the Module 5 apps use a single WebView page. Real apps sometimes need to navigate between pages or dynamically replace content. The pattern is the same but the state management becomes more careful.

Distribution

wxRuby3 distribution to non-technical users — people without Ruby installed — is a real and unsolved problem at the time of writing. The tooling exists in principle but does not yet handle wxRuby3’s native extension cleanly on all platforms.

This is covered honestly in the series conclusion. The short version: wxRuby3 is best suited to audiences that have Ruby, or environments where a one-time setup can be performed. For internal tools and developer utilities — which is where most wxRuby3 apps live — this is entirely acceptable.

A dedicated post on distribution will cover the current state of the tooling and what actually works, updated as the ecosystem matures.


Continue to: Where to go from here