Documentation
¶
Overview ¶
Package app hosts an alacris-go live application in a native OS webview.
The live protocol does not change. Go still renders elements, patches props over SSE, and receives component events over POST. This package is a host for that model: it serves the same http.Handler on a loopback address and opens the operating system's webview onto it. There is no JavaScript binding layer, no generated TypeScript, and no second way to talk to Go. Native capabilities (dialogs, menus, the filesystem, notifications) are ordinary Go function calls, typically from a live.On handler or a menu callback.
app.Run(app.Options{
Title: "Board",
Width: 1100,
Height: 800,
Handler: mux,
Menu: app.DefaultMenu(),
})
Build tags ¶
Opening a window requires a binary built with `-tags desktop`. That pulls CGO and the OS webview (WKWebView, WebView2, WebKitGTK). Without the tag, Listen still works — it is ordinary HTTP — and Run returns ErrNoDesktop.
Host token ¶
EventSource requires an HTTP family URL, so the webview cannot use a custom scheme. Open binds 127.0.0.1 and issues a random host token: the first navigation carries it as a query parameter, the gate swaps it for an HttpOnly cookie and redirects. Another local process that can reach the port cannot create a session without that token. Listen, used by tests, does not install the gate. The live cookie is still required.
Index ¶
- Variables
- func CacheDir(identifier string) (string, error)
- func Confirm(ctx context.Context, title, text string) (bool, error)
- func DataDir(identifier string) (string, error)
- func FinishPendingUpdate() error
- func Message(ctx context.Context, title, text string) error
- func Notify(ctx context.Context, n Notification) error
- func OpenFile(ctx context.Context, dlg FileDialog) (string, error)
- func OpenURL(ctx context.Context, raw string) error
- func PlatformKey() string
- func ReadClipboard(ctx context.Context) (string, error)
- func Relaunch() error
- func RevealInFileManager(ctx context.Context, path string) error
- func Run(opts Options) error
- func SaveAs(ctx context.Context, dlg FileDialog) (string, error)
- func SaveFile(ctx context.Context, filters ...FileFilter) (string, error)
- func SignArtifact(priv ed25519.PrivateKey, artifact []byte) string
- func Verify(pub ed25519.PublicKey, artifact []byte, sigB64 string) error
- func WriteClipboard(ctx context.Context, text string) error
- type App
- type Appearance
- type FileDialog
- type FileFilter
- type Host
- type Manifest
- type Menu
- type MenuItem
- type Notification
- type Options
- type PlatformUpdate
- type Role
- type Titlebar
- type Tray
- type Update
- type Updater
- type Window
- func (w *Window) BeginDrag()
- func (w *Window) Center()
- func (w *Window) Close()
- func (w *Window) Focus()
- func (w *Window) Fullscreen()
- func (w *Window) Hide()
- func (w *Window) Maximize()
- func (w *Window) Minimize()
- func (w *Window) Position() (x, y int)
- func (w *Window) RegisterShortcut(keys string, fn func()) error
- func (w *Window) SetAlwaysOnTop(on bool)
- func (w *Window) SetBadge(s string)
- func (w *Window) SetDecorations(on bool)
- func (w *Window) SetPosition(x, y int)
- func (w *Window) SetSize(width, height int)
- func (w *Window) SetTitle(title string)
- func (w *Window) SetTitlebar(style Titlebar)
- func (w *Window) Show()
- func (w *Window) URL() string
- func (w *Window) Unfullscreen()
- func (w *Window) Unmaximize()
- func (w *Window) UnregisterShortcut(keys string) error
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyRunning = errors.New("app: another instance is running")
ErrAlreadyRunning is returned by Run when SingleInstance is set and another process of this app holds the lock.
var ErrCanceled = errors.New("app: canceled")
ErrCanceled is returned by a dialog when the user dismissed it.
var ErrNoDesktop = errors.New("app: this binary was built without desktop support; rebuild with -tags desktop")
ErrNoDesktop is returned by Run when the binary was not built with `-tags desktop`. Listen does not need the tag.
var ErrNoShortcut = errors.New("app: global shortcuts are not available")
ErrNoShortcut means this OS cannot register a global hotkey.
Functions ¶
func DataDir ¶
DataDir is the per-app directory for durable files (config, lock, sockets). identifier is a reverse-DNS id, the same value as Options.Identifier.
func FinishPendingUpdate ¶
func FinishPendingUpdate() error
FinishPendingUpdate applies a parked `exe.new` from a previous Apply that could not replace a locked Windows binary. Run calls it. It is safe to call at the start of main.
func Notify ¶
func Notify(ctx context.Context, n Notification) error
Notify shows an OS notification.
func OpenFile ¶
func OpenFile(ctx context.Context, dlg FileDialog) (string, error)
OpenFile asks the user to pick an existing file. The zero FileDialog offers every file. ErrCanceled means the user dismissed the dialog.
func OpenURL ¶
OpenURL opens raw in the user's default handler. http, https, mailto, and registered app schemes are accepted; file, network-share and script schemes are refused, as is anything that is not a syntactically valid URL.
func PlatformKey ¶
func PlatformKey() string
PlatformKey is the map key for this binary: GOOS-GOARCH, e.g. darwin-arm64.
func ReadClipboard ¶
ReadClipboard returns the current OS clipboard text.
func Relaunch ¶
func Relaunch() error
Relaunch starts a new copy of this executable with the same arguments and exits. On Windows, if a `.new` file is parked next to the running exe (Apply could not replace a locked file), that file is swapped in first.
func RevealInFileManager ¶
RevealInFileManager shows path in the OS file manager.
func Run ¶
Run listens on loopback, opens a native window onto the handler, and blocks until the window closes.
func SaveAs ¶
func SaveAs(ctx context.Context, dlg FileDialog) (string, error)
SaveAs is SaveFile with a title and default filename.
func SaveFile ¶
func SaveFile(ctx context.Context, filters ...FileFilter) (string, error)
SaveFile asks the user where to write a file.
func SignArtifact ¶
func SignArtifact(priv ed25519.PrivateKey, artifact []byte) string
SignArtifact returns the base64 signature to put in a Manifest. The matching public key is what the app embeds.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
An App owns the loopback host and, once Open has run, one or more windows.
func (*App) Open ¶
Open starts the gated loopback server and creates the first window without entering the event loop. A second Open returns the existing first window; use NewWindow for another.
type Appearance ¶
type Appearance int
Appearance is the window chrome colour scheme. The page still follows whatever Config.Theme (or the OS) says; this only hints the title bar.
const ( // AppearanceSystem follows the OS. It is the default. AppearanceSystem Appearance = iota AppearanceLight AppearanceDark )
type FileDialog ¶
type FileDialog struct {
Title string
Filename string
Filters []FileFilter
}
A FileDialog configures OpenFile or SaveFile.
type FileFilter ¶
FileFilter names one extension the file dialog should offer.
type Host ¶
type Host struct {
// contains filtered or unexported fields
}
A Host is the loopback HTTP server Run puts behind the webview.
Listen is the testable half of the host: it does not need a display or `-tags desktop`. The caller must Shutdown. Listen does not install the host-token gate; Open does, so a window is the only client that can create a session.
func Listen ¶
Listen serves opts.Handler on a loopback address and returns the bound host. Tests use this. Run/Open call listen with the host-token gate on.
func (*Host) BootstrapURL ¶
BootstrapURL is the first navigation target. When the host is gated it carries the one-shot token as a query parameter; the gate swaps that for an HttpOnly cookie and redirects, so EventSource never sees the token.
func (*Host) Shutdown ¶
Shutdown closes the listener and waits for in-flight requests, the same contract as http.Server.Shutdown.
A live EventSource is a request that never ends on its own, so Shutdown with a background context would wait forever and the process would sit in the dock until it was force-quit. The caller must bound ctx; leftover streams are then forced closed so their handlers return.
type Manifest ¶
type Manifest struct {
Version string `json:"version"`
Notes string `json:"notes,omitempty"`
PubDate string `json:"pub_date,omitempty"`
Platforms map[string]PlatformUpdate `json:"platforms"`
}
Manifest is the JSON an updater endpoint serves. The shape matches Tauri's updater so a GitHub Release can host one file both tools read.
{
"version": "0.2.0",
"notes": "…",
"pub_date": "2026-08-17T12:00:00Z",
"platforms": {
"darwin-arm64": {
"url": "https://example/Board_0.2.0_darwin-arm64.tar.gz",
"signature": "<base64 ed25519 of the artifact bytes>"
}
}
}
type Menu ¶
type Menu struct {
Items []MenuItem
}
A Menu is a native menu bar.
func DefaultMenu ¶
func DefaultMenu() *Menu
DefaultMenu is Quit under File, plus the Edit menu a text field needs.
type MenuItem ¶
type MenuItem struct {
Title string
Keys string // "CmdOrCtrl+E", "CmdOrCtrl+Shift+N"
Role Role
Do func(w *Window)
Items []MenuItem
}
A MenuItem is one entry, a separator, or a submenu.
Do runs on the UI thread. It may call SaveFile, patch a live session, or Close the window. It is ignored when Role is not RoleNone.
type Notification ¶
A Notification is a desktop banner. It does not need `-tags desktop`.
type Options ¶
type Options struct {
// Title is the window title. Defaults to "alacris".
Title string
// Width and Height are the initial content size in pixels.
// They default to 800×600.
Width int
Height int
// MinWidth and MinHeight bound shrinking. Zero means no minimum.
MinWidth int
MinHeight int
// FixedSize prevents the user from resizing the window.
FixedSize bool
// Handler is the same mux a browser build would ListenAndServe.
// Required.
Handler http.Handler
// Path is the URL path the webview opens, relative to the loopback
// origin. Defaults to "/".
Path string
// Addr is the loopback address to bind. Empty means 127.0.0.1:0
// (a free port). Only loopback hosts are accepted; 0.0.0.0 is refused.
Addr string
// Menu is installed as the native menu bar on macOS, Windows, and
// Linux. Nil means no menu; DefaultMenu is the usual Edit/Quit set.
Menu *Menu
// Appearance hints the title bar. The default follows the OS.
Appearance Appearance
// Dev opens the webview inspector.
Dev bool
// OnReady runs after the window exists and the loopback server is
// listening, immediately before the native event loop blocks. Window
// methods that do not need Dispatch (SetTitle, SetSize, Close) are
// safe here.
OnReady func(*Window)
// X and Y are the initial window origin in screen pixels. Ignored
// when Center is true. Both zero means the OS picks.
X, Y int
// Center places the window on the primary display. Overrides X and Y.
Center bool
// MaxWidth and MaxHeight bound growing. Zero means no maximum.
MaxWidth int
MaxHeight int
// Fullscreen opens the window in the OS full-screen space.
Fullscreen bool
// Undecorated hides the native title bar. Equivalent to
// Titlebar: TitlebarHidden, which is the clearer spelling.
Undecorated bool
// Titlebar chooses how the title bar is drawn. The zero value is the OS
// one, so this is opt-in.
Titlebar Titlebar
// AlwaysOnTop keeps the window above others.
AlwaysOnTop bool
// Hidden opens the window without showing it (a tray-only start).
Hidden bool
// Identifier is the reverse-DNS id used for single-instance locking,
// data directories, and deep-link registration. Required when
// SingleInstance is true.
Identifier string
// SingleInstance refuses a second process and forwards its arguments
// to OnSecondInstance on the first.
SingleInstance bool
// OnSecondInstance runs in the first process when another launch is
// refused. Args are the second process's os.Args[1:].
OnSecondInstance func(args []string)
// DeepLinkScheme registers an URL scheme (no "://") the OS should
// deliver to this app. OnDeepLink receives the full URL.
DeepLinkScheme string
// OnDeepLink runs when the OS delivers a matching URL. Also invoked
// for a second-instance launch whose args look like a URL.
OnDeepLink func(url string)
// Tray, if set, installs a status-item / notification-area icon.
Tray *Tray
// OnClose runs as the loopback host is coming down, after the last
// window has already gone. Use it to drop long-lived connections
// (a live EventSource, a second listener) so Shutdown does not wait
// on them. The return is kept for the documented cancel, but by this
// point the event loop has ended and a false cannot keep the window.
OnClose func() bool
}
Options configure a desktop window around an http.Handler.
type PlatformUpdate ¶
PlatformUpdate is one OS/arch artifact.
type Titlebar ¶ added in v0.8.0
type Titlebar int
Titlebar is how the window's title bar is drawn.
The default is the OS one. The other two exist because an application whose own surface runs to the top edge looks wrong underneath a bar the OS painted a different colour, and there is no way to tint that bar: on macOS it is AppKit's, in whatever grey the current appearance says.
const ( // TitlebarNative is the OS title bar, drawn by the OS. The default. TitlebarNative Titlebar = iota // TitlebarInset keeps the window buttons and lets the page draw behind // them. Content runs to the top edge and the bar is whatever the page // paints there; dragging and the buttons stay native. // // This is what a modern desktop application usually wants. On macOS it is // a transparent title bar over a full-size content view, so the traffic // lights float above the page. Windows and Linux have no equivalent of // that arrangement, so they fall back to TitlebarHidden and the page is // expected to draw its own buttons. TitlebarInset // TitlebarHidden removes the title bar altogether. The page draws its own, // and BeginDrag moves the window. TitlebarHidden )
type Tray ¶
type Tray struct {
// Title is shown when the OS cannot draw an icon (macOS extra, Linux).
Title string
// Tooltip is the hover text.
Tooltip string
Menu *Menu
}
A Tray is a status-item / notification-area icon. Menu items with Do run as Go callbacks, the same as the window menu.
type Updater ¶
type Updater struct {
// Endpoint is the URL of a Manifest JSON file.
Endpoint string
// PublicKey verifies PlatformUpdate.Signature. Required.
PublicKey ed25519.PublicKey
// Current is this binary's version. Compared as a dotted triple when
// both sides look like semver; otherwise string inequality is enough
// to offer the update.
Current string
// HTTP is the client used to fetch. Defaults to http.DefaultClient.
HTTP *http.Client
// ApplyTo is the path replaced on Apply. Empty means os.Executable.
ApplyTo string
}
Updater checks an HTTP endpoint for a newer signed artifact.
func (Updater) Apply ¶
Apply downloads the artifact, verifies the ed25519 signature, and replaces the running binary. The process is not restarted; call ApplyAndRelaunch (or Relaunch after Apply) to exec the new file. On Windows, a locked executable is parked as `<exe>.new` and swapped in by Relaunch.
func (Updater) ApplyAndRelaunch ¶
ApplyAndRelaunch is Apply followed by Relaunch. On success this process is replaced or exited.
type Window ¶
type Window struct {
// contains filtered or unexported fields
}
A Window is one native webview. An App may open more than one; Run blocks on the first until it closes.
func (*Window) BeginDrag ¶ added in v0.8.0
func (w *Window) BeginDrag()
BeginDrag starts moving the window, as though the pointer had grabbed a title bar.
It is for a page that draws its own title bar: call it from a pointerdown in the region that should behave like one, over the live layer. The OS then runs the drag, so the window keeps up with the pointer rather than chasing it through a round trip per frame.
It only does anything while a mouse button is actually down, because every platform implements it by handing the current event back to the window manager.
func (*Window) Close ¶
func (w *Window) Close()
Close terminates this window. Closing the last window ends Run.
func (*Window) Fullscreen ¶
func (w *Window) Fullscreen()
Fullscreen enters the OS full-screen space.
func (*Window) Hide ¶
func (w *Window) Hide()
Hide removes the window from the screen without destroying it.
func (*Window) Maximize ¶
func (w *Window) Maximize()
Maximize fills the work area. Unmaximize restores the previous size.
func (*Window) Minimize ¶
func (w *Window) Minimize()
Minimize hides the window in the dock / taskbar.
func (*Window) RegisterShortcut ¶
RegisterShortcut binds keys (the same grammar as MenuItem.Keys) as a global hotkey while the app is running. Needs `-tags desktop`.
func (*Window) SetAlwaysOnTop ¶
SetAlwaysOnTop keeps the window above others when on is true.
func (*Window) SetDecorations ¶
SetDecorations shows or hides the native title bar.
func (*Window) SetPosition ¶
SetPosition moves the window's top-left corner, in screen pixels.
func (*Window) SetTitlebar ¶ added in v0.8.0
SetBadge sets the dock / taskbar badge. Empty clears it. No-op where the OS has no badge. SetTitlebar chooses how the title bar is drawn.
func (*Window) UnregisterShortcut ¶
UnregisterShortcut drops a previously registered hotkey.