MyGo
Plugins

Web pages

Plugins

Features that come in a Go package and an npm package, such as the official plugins, and writing your own.

A plugin adds a feature to web pages in two halves: Go services, and a JavaScript package whose functions call them. The app uses the Go half with mygo.Use and imports the JavaScript half from npm.

Official plugins

FetchA fetch that makes HTTP requests from Go, with no CORS, any header, streamed bodies and cancellation.WebSocketA WebSocket whose connections Go makes, with headers on the handshake.SQLiteLocal databases, parameterized queries and atomic transactions, using SQLite's C engine compiled with Zig, without cgo.WatchChanges to files, in the directories the app lets pages watch.UpdaterAn update window in the manner of Sparkle, which checks for updates and offers to install them. It is all Go, and its window is a web page or, for apps of native UI, native UI.TerminalA terminal for native UI, a view that runs the shell or any program with Ghostty's terminal emulator. It is all Go, with a native library that the CLI puts into apps.GlassLiquid Glass for native UI, as macOS draws it, on every platform, with macOS's scroll edges and backdrop blurs. It is all Go, with shaders of its own.GameWhat games need beyond what apps do, opt-in: a game loop in fixed steps with its input, a camera, and gamepads in one standard layout. It is all Go.LoadingLoading.dev's 29 loading indicators for native UI, as they look and move in browsers. It is all Go.SF SymbolsApple's SF Symbols for native UI on macOS, drawn by the system. It is all Go.AutomationA socket through which another process, an end-to-end test runner or an agent, drives the running app: its windows, the elements of their native UI, input, menus, scripts in pages and screenshots. It is all Go, opt-in, and left out of release builds; mygo-automation is its command line client for agents.PermissionFlowThe permissions the system keeps for the user to give, such as Accessibility, Screen Recording and the microphone: checked, asked for, and a guide to System Settings with the app to drag into its list, after PermissionFlow. It is all Go.

Using plugins

mygo.Use takes the plugins of the app, before App.Run:

import (
	"github.com/egoist/mygo"
	"github.com/egoist/mygo/plugins/fetch"
	"github.com/egoist/mygo/plugins/websocket"
)

func main() {
	mygo.Use(fetch.Plugin, websocket.Plugin)
	// ...
}

and the frontend imports their packages:

bun add @mygo-plugins/fetch @mygo-plugins/websocket
import { fetch } from "@mygo-plugins/fetch";
import { WebSocket } from "@mygo-plugins/websocket";

const res = await fetch("https://api.example.com/me", {
  headers: { authorization: `Bearer ${token}` },
});
const ws = new WebSocket("wss://api.example.com/live", [], {
  headers: { authorization: `Bearer ${token}` },
});

The Plugin variable of an official plugin has the default options, and its New function takes options, such as the http.Client of the fetch and WebSocket plugins and an Allow function that decides which requests pages may make. Each plugin's page lists them.

Using a plugin's JavaScript package without its Go half fails with an error that says to call mygo.Use.

Writing a plugin

The Go half is a mygo.Plugin: a name, a service whose methods pages call, and an optional Setup that runs when the app uses it:

package clock

// Plugin gives pages the time of the Go side.
var Plugin = mygo.Plugin{Name: "clock", Service: service{}}

type service struct{}

func (service) Now() time.Time { return time.Now() }

The service is bound like those of mygo.Bind, with the same rules for its methods (contexts, channels, errors), but as plugin:<name> and outside the generated TypeScript client. Its JavaScript package calls it with call of mygo-runtime, which it lists as a peer dependency, so that it uses the app's copy (and as a development dependency, for its own builds and tests):

import { call } from "mygo-runtime";

export const now = async () => new Date(await call<string>("plugin:clock.Now"));

Only the app's trusted pages may call a plugin, as with every bound method. mygo.Use panics when a name is taken or the service's methods use types that cannot cross to JavaScript, so mistakes show at startup.