gox

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 1 Imported by: 10

README

gox

JSX-like syntax for Go. Write components with familiar JSX patterns, get type-safe Go code.

// button.gox
package ui

type ButtonProps struct {
    Label    string
    Disabled bool
}

func Button(props ButtonProps) gox.VNode {
    return <button disabled={props.Disabled}>
        {props.Label}
    </button>
}

Installation

Homebrew (macOS/Linux)
brew tap germtb/tap
brew install gox
Go install
go install github.com/germtb/gox/cmd/gox@latest
Download binary

Download the latest release from GitHub Releases.

# macOS (Apple Silicon)
curl -sSL https://github.com/germtb/gox/releases/latest/download/gox_darwin_arm64.tar.gz | tar xz
sudo mv gox /usr/local/bin/

# macOS (Intel)
curl -sSL https://github.com/germtb/gox/releases/latest/download/gox_darwin_amd64.tar.gz | tar xz
sudo mv gox /usr/local/bin/

# Linux (amd64)
curl -sSL https://github.com/germtb/gox/releases/latest/download/gox_linux_amd64.tar.gz | tar xz
sudo mv gox /usr/local/bin/

Quick Start

  1. Create a .gox file:
// hello.gox
package main

import "github.com/germtb/gox"

func Hello() gox.VNode {
    return <div>
        <h1>Hello, World!</h1>
    </div>
}
  1. Run your project:
gox run .

That's it. Gox handles code generation automatically.

Commands

Command Description
gox run [args] Generate and run with go run
gox build [args] Generate and build with go build
gox generate [path] Generate .go files from .gox files
gox fmt [path] Format .gox files
gox lsp Start LSP server (for IDE integration)
gox version Print version
gox help Show help
Examples
# Run a project
gox run ./cmd/myapp

# Build with output
gox build -o myapp ./cmd/myapp

# Generate all .gox files recursively
gox generate ./...

# Format and write changes
gox fmt -w ./...

# List files that need formatting
gox fmt -l .

How It Works

Gox transforms .gox files into standard Go code:

button.gox  →  gox generate  →  button_gox.go

The generated code uses the gox.VNode type and is fully type-checked by the Go compiler.

Using gox vs go

If your project has .gox files, use gox commands:

gox run .      # instead of go run .
gox build .    # instead of go build .

If your project is pure Go (even with gox dependencies), use standard Go:

go run .       # works fine
go build .     # works fine

This is because gox libraries ship with pre-generated .go files.

For Library Authors

If you're publishing a library that uses gox:

  1. Commit generated files - Remove *_gox.go from .gitignore
  2. Ship both .gox and *_gox.go - Consumers get working Go code

This allows consumers to go get your library without needing gox installed.

your-library/
├── component.gox           # Source (for contributors)
├── component_gox.go        # Generated (for consumers)
└── go.mod
Why commit generated files?
Approach Pros Cons
Commit generated files go get just works Generated code in git
Gitignore generated files Clean repo Breaks go get, forces gox on consumers

Most code generation tools (protobuf, sqlc, ent) recommend committing generated files for the same reason.

For Application Developers

If you're building an application (not a library):

  1. Gitignore generated files - Keep your repo clean
  2. Use gox run / gox build - Handles generation automatically
  3. Add to CI - Run gox build in your build pipeline

Example .gitignore for applications:

*_gox.go
*_gox_test.go
*_gox.go.map
*_gox_test.go.map

Typed Props

Components with typed props get compile-time type checking:

type ButtonProps struct {
    Label    string
    Disabled bool
    OnClick  func()
}

func Button(props ButtonProps) gox.VNode {
    return <button disabled={props.Disabled} onClick={props.OnClick}>
        {props.Label}
    </button>
}

// Usage - props are type-checked!
func App() gox.VNode {
    return <Button label="Submit" disabled={false} />
}

The Go compiler will catch:

  • Missing required props
  • Wrong prop types
  • Typos in prop names

VS Code Extension

Install the VS Code extension for:

  • Syntax highlighting
  • Format on save
  • Go-to-definition (works across .gox and .go files)
  • Error diagnostics
cd vscode-gox
npm install
npm run compile
# Then: "Developer: Install Extension from Location..."

Configure in .vscode/settings.json:

{
  "files.associations": {
    "*.gox": "gox"
  },
  "[gox]": {
    "editor.formatOnSave": true
  }
}

Source Maps

Gox generates source maps (.map files) that remap errors from generated code back to your .gox source:

button_gox.go:42:5: undefined: foo
         ↓ (remapped)
button.gox:15:5: undefined: foo

This works automatically with gox run and gox build.

Project Structure

your-project/
├── cmd/
│   └── app/
│       └── main.gox          # Entry point with JSX
├── ui/
│   ├── button.gox            # Component
│   ├── button_gox.go         # Generated (gitignore for apps)
│   └── header.gox            # Component
├── go.mod
└── .gitignore

FAQ

Do consumers of my library need gox?

No. If you commit the generated *_gox.go files, consumers use standard go get and go build. They never need to know gox exists.

Can I mix .gox and .go files?

Yes. They live side by side in the same package. .go files can import and use components defined in .gox files (via the generated code).

What's the runtime overhead?

The runtime is minimal - just the VNode type and helper functions. There's no virtual DOM diffing or complex runtime. Generated code is straightforward Go.

How do I render VNodes?

Gox generates a tree of gox.VNode values. You provide a renderer for your target:

  • HTML: Walk the tree and output HTML strings
  • Terminal: Use a library like bubbletea or lipgloss
  • Testing: Inspect the tree directly

See demo/app.gox for a terminal renderer example.

License

MIT

Documentation

Overview

Package gox provides JSX-like syntax for Go and the core types for virtual DOM trees.

Index

Constants

View Source
const (
	TextNodeType     = "__text__"
	FragmentNodeType = "__fragment__"
)

NodeType constants for special node types.

Variables

This section is empty.

Functions

func WalkTree

func WalkTree(root VNode, walker Walker)

WalkTree traverses a VNode tree depth-first, calling the walker for each node.

Types

type Component

type Component func(props Props) VNode

Component is a function that returns a VNode.

type Props

type Props map[string]any

Props is a flexible property map.

type RenderFunc

type RenderFunc func(VNode) error

RenderFunc is a function type that implements Renderer.

func (RenderFunc) Render

func (f RenderFunc) Render(vnode VNode) error

Render implements the Renderer interface.

type Renderer

type Renderer interface {
	// Render processes a VNode tree and produces output.
	Render(vnode VNode) error
}

Renderer is the interface for connecting VNode trees to actual implementations. Users implement this interface to bridge gox output to their tree system (e.g., TUI libraries, HTML DOM, custom tree structures).

type VNode

type VNode struct {
	Type     any // string for intrinsic elements, Component for components
	Props    Props
	Children []VNode
}

VNode is the core tree node type.

func E

func E(typ any, props Props, children ...VNode) VNode

E is a shorthand alias for Element.

func Element

func Element(typ any, props Props, children ...VNode) VNode

Element creates a VNode for an element (intrinsic or component). typ can be a string (for intrinsic elements like "div", "span") or a Component function.

func Empty

func Empty() VNode

Empty returns an empty VNode.

func Fragment

func Fragment(children ...VNode) VNode

Fragment wraps multiple children without a parent element.

func Map

func Map[T any](items []T, fn func(T) VNode) []VNode

Map applies a function to each element and returns the resulting VNodes. Useful for rendering lists: {gox.Map(items, func(item Item) VNode { return <ItemView item={item} /> })}

func MapIndex

func MapIndex[T any](items []T, fn func(int, T) VNode) []VNode

MapIndex applies a function with index to each element and returns the resulting VNodes.

func Spread

func Spread(nodes []VNode) VNode

Spread expands a slice of VNodes into children. Useful when you have a []VNode and need to pass as children.

func Text

func Text(content string) VNode

Text creates a text VNode.

func V

func V(value any) VNode

V converts an arbitrary value to a VNode. If the value is already a VNode, it's returned as-is. If it's a string, it's wrapped as a Text node. If it's a []VNode, it's wrapped as a Fragment. Numeric types and booleans are converted to their string representation. Panics for unsupported types (channels, functions, etc.).

func When

func When(condition bool, child VNode) VNode

When returns child if condition is true, else empty VNode. Useful for conditional rendering: {gox.When(showExtra, <Extra />)}

func WhenElse

func WhenElse(condition bool, ifTrue, ifFalse VNode) VNode

WhenElse returns ifTrue if condition is true, else ifFalse.

func (VNode) GetTextContent

func (v VNode) GetTextContent() (string, bool)

GetTextContent returns the text content if this is a text node.

func (VNode) IsComponent

func (v VNode) IsComponent() bool

IsComponent returns true if this VNode represents a component.

func (VNode) IsEmpty

func (v VNode) IsEmpty() bool

IsEmpty returns true if this VNode is empty/nil.

func (VNode) IsFragment

func (v VNode) IsFragment() bool

IsFragment returns true if this VNode is a fragment.

func (VNode) IsText

func (v VNode) IsText() bool

IsText returns true if this VNode is a text node.

type WalkFunc

type WalkFunc func(VNode, int) bool

WalkFunc is a function type that implements Walker.

func (WalkFunc) Walk

func (f WalkFunc) Walk(vnode VNode, depth int) bool

Walk implements the Walker interface.

type Walker

type Walker interface {
	// Walk is called for each node in the tree.
	// Return false to stop walking children.
	Walk(vnode VNode, depth int) bool
}

Walker provides a way to traverse VNode trees.

Directories

Path Synopsis
Package ast defines the AST types for gox files.
Package ast defines the AST types for gox files.
cmd
gox command
gox is a preprocessor that transforms .gox files containing Go + JSX syntax into pure .go files.
gox is a preprocessor that transforms .gox files containing Go + JSX syntax into pure .go files.
Package formatter provides formatting for .gox files.
Package formatter provides formatting for .gox files.
Package generator transforms gox AST into Go source code.
Package generator transforms gox AST into Go source code.
Package lsp implements a Language Server Protocol proxy for gox files.
Package lsp implements a Language Server Protocol proxy for gox files.
Package parser parses gox files into an AST.
Package parser parses gox files into an AST.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL