<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cesar Gimenes</title>
    <description>The latest articles on DEV Community by Cesar Gimenes (@crgimenes).</description>
    <link>https://dev.to/crgimenes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F254474%2F8bf24d58-8608-442b-b76e-a4996c372d8c.png</url>
      <title>DEV Community: Cesar Gimenes</title>
      <link>https://dev.to/crgimenes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crgimenes"/>
    <language>en</language>
    <item>
      <title>Building desktop WebView apps in Go without CGo</title>
      <dc:creator>Cesar Gimenes</dc:creator>
      <pubDate>Tue, 30 Jun 2026 03:54:59 +0000</pubDate>
      <link>https://dev.to/crgimenes/building-desktop-webview-apps-in-go-without-cgo-47bj</link>
      <guid>https://dev.to/crgimenes/building-desktop-webview-apps-in-go-without-cgo-47bj</guid>
      <description>&lt;p&gt;I have been working on &lt;a href="https://github.com/crgimenes/glaze" rel="noopener noreferrer"&gt;Glaze&lt;/a&gt;, a small desktop WebView toolkit for Go.&lt;/p&gt;

&lt;p&gt;The short version: Glaze lets a Go program open a native desktop window backed by the WebView already available on the operating system, without using CGo.&lt;/p&gt;

&lt;p&gt;It currently targets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS, through WKWebView&lt;/li&gt;
&lt;li&gt;Linux, through WebKitGTK&lt;/li&gt;
&lt;li&gt;Windows, through WebView2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is still young, but the core idea is already useful: keep small Go desktop tools close to the normal Go workflow.&lt;/p&gt;

&lt;p&gt;No C compiler in the build path.&lt;br&gt;
No bundled native helper library.&lt;br&gt;
No large application framework around it.&lt;/p&gt;

&lt;p&gt;Just Go code calling the system WebView.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why I wanted this
&lt;/h2&gt;

&lt;p&gt;I write a lot of small tools in Go.&lt;/p&gt;

&lt;p&gt;Some of them are fine as CLI programs. Others need a basic interface: a form, a preview, a local dashboard, a small editor, or a way to inspect and manipulate data visually.&lt;/p&gt;

&lt;p&gt;For those cases, HTML is often enough. The browser gives me layout, text rendering, forms, tables, keyboard handling, and a familiar debugging model.&lt;/p&gt;

&lt;p&gt;But I do not always want to ship a web server as the user interface. I also do not always want to pull in a large desktop framework when all I need is a native window around a local UI.&lt;/p&gt;

&lt;p&gt;A WebView is a reasonable middle ground.&lt;/p&gt;

&lt;p&gt;The problem is that many WebView solutions eventually bring CGo, native build tooling, helper libraries, or larger framework assumptions into the project.&lt;/p&gt;

&lt;p&gt;That is not necessarily wrong. For many applications, those trade-offs are acceptable.&lt;/p&gt;

&lt;p&gt;For this project, I wanted something narrower.&lt;/p&gt;
&lt;h2&gt;
  
  
  The design constraint
&lt;/h2&gt;

&lt;p&gt;The main constraint behind Glaze is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the WebView already provided by the OS, but call it from Go without CGo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Glaze uses &lt;a href="https://github.com/ebitengine/purego" rel="noopener noreferrer"&gt;purego&lt;/a&gt; to call native platform APIs directly from Go.&lt;/p&gt;

&lt;p&gt;That means each backend talks to the platform WebView:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WKWebView on macOS&lt;/li&gt;
&lt;li&gt;WebKitGTK on Linux&lt;/li&gt;
&lt;li&gt;WebView2 on Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is not a full GUI toolkit. That is intentional.&lt;/p&gt;

&lt;p&gt;Glaze is focused on the window, the WebView, JavaScript-to-Go bindings, and a few desktop helpers that are useful for small tools.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hello world
&lt;/h2&gt;

&lt;p&gt;A minimal Glaze program looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/crgimenes/glaze"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;glaze&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Glaze"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;glaze&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HintNone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Hello from Glaze&amp;lt;/h1&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That opens a native window and renders HTML inside the system WebView.&lt;/p&gt;
&lt;h2&gt;
  
  
  A local Go app in a desktop window
&lt;/h2&gt;

&lt;p&gt;One of the patterns I care about most is turning an existing &lt;code&gt;net/http&lt;/code&gt; application into a desktop app with minimal changes.&lt;/p&gt;

&lt;p&gt;Glaze has an &lt;code&gt;AppWindow&lt;/code&gt; helper for that.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/crgimenes/glaze"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mux&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;`&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;title&amp;gt;Glaze App&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
        body {
            font-family: system-ui, sans-serif;
            margin: 2rem;
        }
        button {
            font: inherit;
            padding: 0.5rem 1rem;
        }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Local Go UI&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This page is served by a Go http.Handler and displayed in a desktop WebView.&amp;lt;/p&amp;gt;
    &amp;lt;button onclick="location.reload()"&amp;gt;Reload&amp;lt;/button&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"write response: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;glaze&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;glaze&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppOptions&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"Glaze App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the style of application I had in mind: local tools, internal utilities, small editors, dashboards, inspectors, and experiments.&lt;/p&gt;

&lt;p&gt;The UI can still be plain HTML, CSS, and JavaScript. The backend can still be normal Go.&lt;/p&gt;
&lt;h2&gt;
  
  
  Calling Go from JavaScript
&lt;/h2&gt;

&lt;p&gt;Glaze also supports binding Go functions to JavaScript.&lt;/p&gt;

&lt;p&gt;That makes it possible to keep the UI lightweight while still doing real work in Go.&lt;/p&gt;

&lt;p&gt;The goal is not to turn every application into a complex frontend. The useful case is exposing a small surface area: save a file, query local state, run a calculation, trigger an operation, or send an event.&lt;/p&gt;

&lt;p&gt;This fits well with small tools where most of the logic belongs in Go and the WebView is mainly the presentation layer.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Glaze is not trying to be
&lt;/h2&gt;

&lt;p&gt;Glaze is not trying to replace mature GUI toolkits.&lt;/p&gt;

&lt;p&gt;It is also not trying to replace larger frameworks for building full desktop applications.&lt;/p&gt;

&lt;p&gt;Those projects usually solve broader problems: packaging, application lifecycle, icons, installers, auto-update, system integration, custom controls, and more.&lt;/p&gt;

&lt;p&gt;Glaze is intentionally smaller.&lt;/p&gt;

&lt;p&gt;The target use case is closer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“I have a Go tool and want a small local UI”&lt;/li&gt;
&lt;li&gt;“I already have an HTTP handler and want to show it in a desktop window”&lt;/li&gt;
&lt;li&gt;“I want HTML for layout but do not want to ship a browser”&lt;/li&gt;
&lt;li&gt;“I want to avoid CGo in this project”&lt;/li&gt;
&lt;li&gt;“I want a thin WebView layer instead of a full application framework”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That scope keeps the API easier to reason about.&lt;/p&gt;
&lt;h2&gt;
  
  
  Platform notes
&lt;/h2&gt;

&lt;p&gt;macOS is the cleanest case because the Cocoa and WebKit frameworks are already part of the system.&lt;/p&gt;

&lt;p&gt;Windows depends on the Microsoft Edge WebView2 Runtime, which is already present on current Windows installations in many cases.&lt;/p&gt;

&lt;p&gt;Linux is the hard case. Different distributions package WebKitGTK differently, and dynamic library names matter. Glaze tries to detect GTK4/WebKitGTK first and falls back to GTK3/WebKitGTK where appropriate, but Linux still needs more testing across distributions.&lt;/p&gt;

&lt;p&gt;That is one of the areas where feedback would be useful.&lt;/p&gt;
&lt;h2&gt;
  
  
  Current features
&lt;/h2&gt;

&lt;p&gt;At the moment Glaze includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;desktop WebView windows&lt;/li&gt;
&lt;li&gt;JavaScript-to-Go binding&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BindMethods&lt;/code&gt; helper for exposing exported Go methods&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RenderHTML&lt;/code&gt; helper for Go templates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AppWindow&lt;/code&gt; for local &lt;code&gt;net/http&lt;/code&gt; apps&lt;/li&gt;
&lt;li&gt;Go-to-JavaScript event bridge&lt;/li&gt;
&lt;li&gt;native file dialogs&lt;/li&gt;
&lt;li&gt;native menu support on macOS and Windows&lt;/li&gt;
&lt;li&gt;runnable visual examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository also includes small demos such as Game of Life, Starfield, Doom Fire, Mandelbrot, Falling Sand, Raycasting, and a Filo REPL.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/crgimenes" rel="noopener noreferrer"&gt;
        crgimenes
      &lt;/a&gt; / &lt;a href="https://github.com/crgimenes/glaze" rel="noopener noreferrer"&gt;
        glaze
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Glaze: a CGo-free desktop WebView toolkit for Go
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Glaze&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Glaze is a desktop WebView binding for Go. It is a pure-Go port of &lt;a href="https://github.com/webview/webview" rel="noopener noreferrer"&gt;webview/webview&lt;/a&gt; built on &lt;a href="https://github.com/ebitengine/purego" rel="noopener noreferrer"&gt;purego&lt;/a&gt;, keeping CGo out of the picture. Each backend talks to the WebView framework the OS already ships -- WKWebView on macOS, WebKitGTK on Linux, WebView2 on Windows -- so nothing native is bundled.&lt;/p&gt;

&lt;p&gt;It started as a fork of &lt;code&gt;go-webview&lt;/code&gt; but has diverged enough to live as a separate codebase with its own goals and API.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Examples&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Desktop&lt;/th&gt;

&lt;th&gt;Game of Life&lt;/th&gt;

&lt;th&gt;Starfield&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/desktop/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fdesktop.gif" alt="Desktop example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/gameoflife/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fgameoflife.gif" alt="Game of Life example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/starfield/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fstarfield.gif" alt="Starfield example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;br&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Doom Fire&lt;/th&gt;

&lt;th&gt;Mandelbrot&lt;/th&gt;

&lt;th&gt;Falling Sand&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/doomfire/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fdoomfire.gif" alt="Doom Fire example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/mandelbrot/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fmandelbrot.gif" alt="Mandelbrot example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/fallingsand/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Ffallingsand.gif" alt="Falling Sand example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;br&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Raycasting&lt;/th&gt;

&lt;th&gt;Filo REPL&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/raycasting/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Fraycasting.gif" alt="Raycasting example preview"&gt;&lt;/a&gt;&lt;/td&gt;

&lt;td&gt;&lt;a href="https://github.com/crgimenes/glaze/examples/filorepl/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcrgimenes%2Fglaze%2FHEAD%2Fimgs%2Ffilorepl.gif" alt="Filo REPL example preview"&gt;&lt;/a&gt;&lt;/td&gt;


&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why no CGo&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;This is the whole point of the project, and it's the part that's easy to miss. Most native-WebView bindings reach for CGo, which quietly takes back the things that make Go pleasant to ship: cross-compiling suddenly needs a matching &lt;strong&gt;C&lt;/strong&gt; cross-compiler for every target (mingw for Windows, a sysroot for Linux), builds stop being reproducible, and &lt;code&gt;go&lt;/code&gt;…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/crgimenes/glaze" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;p&gt;The main benefit is keeping the project close to regular Go development.&lt;/p&gt;

&lt;p&gt;The main cost is that Glaze sits close to native platform APIs, so platform differences are real.&lt;/p&gt;

&lt;p&gt;Some trade-offs are deliberate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It does not bundle a browser.&lt;/li&gt;
&lt;li&gt;It does not try to hide every OS difference.&lt;/li&gt;
&lt;li&gt;It does not try to become a complete desktop framework.&lt;/li&gt;
&lt;li&gt;Linux support depends on system WebKitGTK libraries.&lt;/li&gt;
&lt;li&gt;Windows support depends on WebView2 runtime behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my use case, that is acceptable. I prefer a small, explicit layer over a large abstraction that hides too much.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I want to take it
&lt;/h2&gt;

&lt;p&gt;The immediate focus is stability and examples.&lt;/p&gt;

&lt;p&gt;The most valuable improvements right now are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing on more Linux distributions&lt;/li&gt;
&lt;li&gt;better diagnostics when system WebView libraries are missing&lt;/li&gt;
&lt;li&gt;more examples showing realistic local tools&lt;/li&gt;
&lt;li&gt;API feedback from Go developers who build small desktop utilities&lt;/li&gt;
&lt;li&gt;clearer documentation for platform-specific behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am also interested in keeping the project boring in the good sense: small API, predictable behavior, explicit errors, and no unnecessary magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;The project is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/crgimenes/glaze" rel="noopener noreferrer"&gt;https://github.com/crgimenes/glaze&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback is welcome, especially around the API shape, Linux/WebKitGTK behavior, and whether the examples make the intended use case clear.&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
