Proton

July 10, 2026 · View on GitHub

A GUI library for Go that doesn't make you want to switch to web dev.

Go Report Card Mentioned in Awesome Go

Why Proton?

Zero CGO Required: Cross-compile to Windows and macOS flawlessly from any machine without fighting external compiler toolchains.

Pure Go Ecosystem: Built on top of Gio, maintaining a 100% Go native development experience.

API Immunity: No raw Gio types pollute your code. If the underlying rendering engine updates, your app's codebase remains completely untouched.

Our First Stargazers

Thank you to the early adopters who supported Proton from the very beginning!


@VioGrafu
(First Stargazer)

@bigwhite

@TanmayCzax

@aurax

@DemonK1

@pekim

@fbaube

@gorilacrocodille

@alanmsant2

Documentation

Official Docs For Proton

Docs Repo


Example apps

GIF

You can create even better! Proton is not just for Todo or Calculator apps

GUI demo Demo2

Pictures

Sample2 Sample1

Code

ChatGPT Image Jul 10, 2026, 01_09_19 PM

Getting Started

package main

import "github.com/CzaxStudio/proton"

func main() {
    a := proton.New("hello")
    a.Window("Hello", 400, 200, func(ctx proton.Context) {
        proton.H3(ctx, "Hello from Proton!")
    })
    a.Run()
}

Install

go get github.com/CzaxStudio/proton

Then run once to pull Gio's dependencies:

go mod tidy

Linux — three system packages required:

sudo apt install libwayland-dev libxkbcommon-dev libvulkan-dev

macOS and Windows need nothing extra.


How it works

Your draw function runs every frame. Call widget functions in order — they stack vertically by default. State lives in your own struct. No setState, no component trees, no XML.

type UI struct {
    btn     proton.Clickable    // button
    name    proton.Editor       // text input
    checked proton.Bool         // checkbox / toggle
    choice  proton.Enum         // radio group
    vol     proton.Float        // slider
    scroll  proton.Scrollable   // list / scroll area
}

Widgets

Text

Label H1H6 Body2 Caption Text Muted ColoredText ErrorText SuccessText WarningText

Buttons

Button OutlineButton IconButton Tappable Link LinkSmall

Inputs

Input TextArea Checkbox Toggle RadioButton Slider ProgressBar NumberInput SelectBox SearchInput

Lists

List HList Scroll TextView LogView

Layout

Row Column RowSpread RowEnd GrowRow GrowColumn GrowItem FixedItem FlexSpacer Split HSplit ResizeSplit ResizeHSplit Center ZStack Pad PadH PadV PadSides Gap Grid MinSize MaxWidth

Visual

Divider LabeledDivider Rect RoundRect Card HoverCard Badge StatusDot Avatar Tag Image Logo CodeBlock ShortcutHint ColorSwatch

Data

Table ProgressRing Stepper

Feedback

Toast Alert AlertDismissable Tooltip Spinner

Overlays & Dialogs

Overlay Tabs Accordion ContextMenu

Utilities

If OnKey FocusArea


Layout

// side by side
proton.Row(ctx,
    func(ctx proton.Context) { proton.Label(ctx, "left") },
    func(ctx proton.Context) { proton.Label(ctx, "right") },
)

// one child fills remaining space
proton.GrowRow(ctx,
    proton.FixedItem(ctx, func(ctx proton.Context) { proton.Label(ctx, "Search:") }),
    proton.GrowItem(ctx, func(ctx proton.Context) { proton.Input(ctx, &e, "") }),
    proton.FixedItem(ctx, func(ctx proton.Context) { proton.Button(ctx, &b, "Go") }),
)

// draggable split pane
proton.ResizeSplit(ctx, &u.split, 0.35, leftFn, rightFn)

// padding
proton.Pad(ctx, 16, func(ctx proton.Context) { ... })
proton.PadSides(ctx, 8, 16, 8, 16, func(ctx proton.Context) { ... })

// blank space
proton.Gap(ctx, 12)

Theming

46 built-in palettes. One line to apply any of them.

a.ApplyPalette(proton.NordPalette)
a.ApplyPalette(proton.CatppuccinPalette)
a.ApplyPalette(proton.DraculaPalette)
a.ApplyPalette(proton.TokyoNightPalette)
a.ApplyPalette(proton.GruvboxDarkPalette)
a.ApplyPalette(proton.RosePinePalette)
// ... 40 more

Custom palette

a.ApplyPalette(proton.Palette{
    Bg:        proton.RGB(0x1e1e2e),
    Fg:        proton.RGB(0xcdd6f4),
    Primary:   proton.RGB(0x89b4fa),
    PrimaryFg: proton.RGB(0x1e1e2e),
})

Hex color codes

No structs needed — just pass the hex string:

a.ThemeBuilder().
    Bg("#1e1e2e").
    Fg("#cdd6f4").
    Primary("#89b4fa").
    PrimaryFg("#1e1e2e").
    Apply()

// patch one color on the current theme
a.ColorCode("primary", "#ff6b6b")
a.ColorCode("bg", "#0d1117")

Accepted formats: "#rrggbb", "rrggbb", "#rgb", "#rrggbbaa".

Background colors

a.SetBackgroundCode("#1a1b26")
a.SetBackgroundRGB(26, 27, 38)
a.SetBackgroundGradient("#1a1b26", "#2d1b69", "vertical")
a.SetBackgroundRainbow() // animated full-spectrum gradient

Font scale

a.SetFontScale(1.1)

Live theme picker

Drop into a settings window to let users switch themes at runtime:

type UI struct {
    picker proton.ThemePickerState
}

proton.ThemePicker(ctx, &u.picker, a)

Logo

Load once at startup, draw anywhere.

//go:embed assets/logo.png
var logoBytes []byte

func main() {
    a := proton.New("myapp")
    a.SetLogoBytes(logoBytes)

    a.Window("My App", 480, 300, func(ctx proton.Context) {
        proton.Row(ctx,
            func(ctx proton.Context) { proton.Logo(ctx, 40, 40) },
            func(ctx proton.Context) { proton.Gap(ctx, 10) },
            func(ctx proton.Context) { proton.H5(ctx, "My App") },
        )
    })
    a.Run()
}

Or load from a file path:

a.SetLogo("assets/logo.png")

PNG and JPEG both work. The image is decoded once and cached — not re-read per frame.


Alerts and Feedback

proton.Alert(ctx, proton.AlertInfo,    "Informational message.")
proton.Alert(ctx, proton.AlertSuccess, "Operation completed.")
proton.Alert(ctx, proton.AlertWarning, "Proceed with caution.")
proton.Alert(ctx, proton.AlertError,   "Something went wrong.")

// dismissable
if proton.AlertDismissable(ctx, &u.closeBtn, proton.AlertInfo, "Click x to close") {
    u.showAlert = false
}

// toast — call last in your draw function
u.toast.Show("Saved!", 2*time.Second)
proton.Toast(ctx, &u.toast)

New in v0.2.x

Table

proton.Table(ctx,
    []string{"Name", "Status", "Score"},
    []proton.TableRow{
        {"Alice", "Active", "98"},
        {"Bob",   "Away",   "74"},
    },
)

Stepper

proton.Stepper(ctx, currentStep, []string{"Build", "Test", "Stage", "Deploy"})

ProgressRing

proton.ProgressRing(ctx, 0.72, 48, 5, proton.RGB(0x88c0d0))

SearchInput

q := proton.SearchInput(ctx, &u.search, "Search notes...")

Avatar

proton.Avatar(ctx, "AJ", proton.RGB(0x5e81ac), proton.RGB(0xeceff4), 40)

NumberInput

qty := proton.NumberInput(ctx, &u.qty, 1, 99, 1)

Overlay / modal

proton.Overlay(ctx, &u.modal, func(ctx proton.Context) {
    proton.Card(ctx, proton.RGB(0x2e3440), 12, 24, func(ctx proton.Context) {
        proton.H5(ctx, "Confirm?")
        proton.Gap(ctx, 16)
        proton.Pad(ctx, 4, func(ctx proton.Context) {
            if proton.Button(ctx, &u.closeBtn, "Close") {
                u.modal.Hide()
            }
        })
    })
})

Async Updates

go func() {
    result := fetchFromAPI()
    u.data = result
    ctx.Invalidate()
}()

Keyboard Shortcuts

proton.OnKey(ctx, proton.ModCtrl, "S", func() { save() })
proton.OnKey(ctx, proton.ModNone, proton.KeyEscape, func() { closeDialog() })
proton.OnKey(ctx, proton.ModCtrl|proton.ModShift, "N", func() { newWindow() })

Window Options

a.WindowEx("App", 800, 600, []proton.WindowOption{
    proton.Fullscreen(),
}, draw)

Android

Same code runs on Android. No rewrites.

go install gioui.org/cmd/gogio@latest
gogio -target android -appid com.yourname.yourapp .
adb install yourapp.apk

Full guide: docs/10-android.md


API Immunity

Every draw function takes proton.Context — an interface. No Gio types appear in the public API. If Gio's internals change in a future version, only Proton's implementation updates. Your code keeps compiling unchanged.

func (app *MyApp) draw(ctx proton.Context) {
    proton.Button(ctx, &app.btn, "Click")
}

Examples

go run ./examples/hello        # minimal — one window, one label
go run ./examples/todo         # todo list
go run ./examples/calculator   # grid of buttons
go run ./examples/notes        # note-taking app with search and split pane
go run ./examples/dashboard    # dev dashboard with charts, logs, and tables
go run ./examples/showcase     # every widget in one place
go run ./examples/themes       # live theme picker
go run ./examples/logoapp      # custom logo with go:embed
go run ./examples/kitchen      # stress test for all features

License

MIT

Currently under development for v0.2.5