Native application framework for Go

Toby Chui f2913943a7 added readme 3 hete
examples c03d819f16 added examples 3 hete
img 4e569b36f4 added readme 3 hete
.gitignore 12ad996520 Initial commit 3 hete
LICENSE 12ad996520 Initial commit 3 hete
README.md f2913943a7 added readme 3 hete
backend.go c03d819f16 added examples 3 hete
debug.go c03d819f16 added examples 3 hete
go.mod c03d819f16 added examples 3 hete
go.sum c03d819f16 added examples 3 hete
naffg.go c03d819f16 added examples 3 hete

README.md

Naffg

Native-like Application Framework For Golang

This is a simple module that provide a desktop application windows for your application using the Windows' WebView2 API. This module also includes a basic http server based on net/http and provide a embedded client & server bundle in single binary using go:embed.

Usage

This module wraps an internal web resources folder and a WebView2 instance in one module, so you can easily get started building a simple local application using WebApp technology. The main components of this module consists of the following

  • WebView2 Instance
  • A HTTP Web Server (default to :36850, can be changed by EventExchangePort variable in naffg.Options)
  • Support embedded file system for Web UI files

Example

The following example assume you have the following folder structure with res storing all the UI resources (html, css and javascript files)

MyProject/
├─ res/
│  ├─ index.html
├─ main.go

Content of main.go

package main

import (
	"embed"
	"encoding/json"
	"net/http"

	"github.com/tobychui/naffg"
)

//go:embed res/*
var uiFiles embed.FS

func main() {
	app := naffg.NewApplication(&naffg.Options{
		Title:      "Hello World",
		Width:      400,
		Height:     300,
		Resizable:  false,
		UiRes:      &uiFiles, //Embed the UI resources
		UiResPreix: "res",    //The folder where the resources is embeded from
	})

	//Print the embedded files
	app.Debug_PrintEmbeddedFiles()

	//Handle the API, for example /api/hello?name=John
	app.Mux().HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
		//Get the name from the query
		name := r.URL.Query().Get("name")
		if name == "" {
			name = "Who are you?"
		} else {
			name = "Hello, " + name
		}

		//Write the response
		js, _ := json.Marshal(name)
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(js))
	})

	// Run the application
	app.Run()
}

Content of the ./res/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            font-family: Arial, sans-serif;
        }
    </style>
</head>
<body>
    <div>
        <form id="myForm">
            <input type="text" id="myInput" placeholder="Enter text">
            <button type="submit">Send</button>
        </form>
        <p id="response">Enter a name in the input box and click send</p>
    </div>
    

    <script>
        document.getElementById('myForm').addEventListener('submit', function(event) {
            event.preventDefault();
            var inputValue = document.getElementById('myInput').value;

            fetch('/api/hello?name=' + encodeURIComponent(inputValue))
                .then(response => response.text())
                .then(data => {
                    document.getElementById('response').innerText = data;
                })
                .catch(error => {
                    console.error('Error:', error);
                });
        });
    </script>
</body>
</html>

You will see a WebView2 windows pop-up after running go run main.go

image-20241102122707465

More examples can be found in the ./examples/ folder.

Implementation Notes

Note that the WebView2 application must be run in the same thread as the main() function.

Do not use goroutine on the app.Run() function call

License

MIT