via

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Dec 4, 2025 License: MIT Imports: 20 Imported by: 1

README ¶

⚡Via

Real-time engine for building reactive web applications in pure Go.

Why Via?

Somewhere along the way, the web became tangled in layers of JavaScript, build chains, and frameworks stacked on frameworks.

Via takes a radical stance:

  • No templates.
  • No JavaScript.
  • No transpilation.
  • No hydration.
  • No front-end fatigue.
  • Single SSE stream.
  • Full reactivity.
  • Built-in Brotli compression.
  • Pure Go.

Example

package main

import (
	"github.com/go-via/via"
	"github.com/go-via/via/h"
)

type Counter struct{ Count int }

func main() {
	v := via.New()

	v.Page("/", func(c *via.Context) {
		data := Counter{Count: 0}
		step := c.Signal(1)

		increment := c.Action(func() {
			data.Count += step.Int()
			c.Sync()
		})

		c.View(func() h.H {
			return h.Div(
				h.P(h.Textf("Count: %d", data.Count)),
				h.Label(
					h.Text("Update Step: "),
					h.Input(h.Type("number"), step.Bind()),
				),
				h.Button(h.Text("Increment"), increment.OnClick()),
			)
		})
	})

	v.Start()
}

🚧 Experimental

Via is still a newborn. Via is taking its first steps!

  • Version 0.1.0 released.
  • Expect a little less chaos.

Contributing

  • Via is intentionally minimal and opinionated — and so is contributing.
  • If you love Go, simplicity, and meaningful abstractions — Come along for the ride!
  • Fork, branch, build, tinker with things, submit a pull request.
  • Keep every line purposeful.
  • Share feedback: open an issue or start a discussion.

Credits

Via builds upon the work of these amazing projects:

  • 🚀 Datastar - The hypermedia powerhouse at the core of Via. It powers browser reactivity through Signals and enables real-time HTML/Signal patches over an always-on SSE event stream.
  • 🧩 Gomponents - The awesome project that gifts Via with Go-native HTML composition superpowers through the via/h package.

Thank you for building something that doesn’t just function — it inspires. 🫶

Documentation ¶

Overview ¶

Package via provides a reactive web framework for Go. It lets you build live, type-safe web interfaces without JavaScript.

Via unifies routing, state, and UI reactivity through a simple mental model: Go on the server — HTML in the browser — updated in real time via Datastar.

Index ¶

Constants ¶

This section is empty.

Variables ¶

This section is empty.

Functions ¶

This section is empty.

Types ¶

type ActionTriggerOption ¶

type ActionTriggerOption interface {
	// contains filtered or unexported methods
}

ActionTriggerOption configures behavior of action triggers

func WithSignal ¶

func WithSignal(sig *signal, value string) ActionTriggerOption

WithSignal sets a signal value before triggering the action.

func WithSignalInt ¶

func WithSignalInt(sig *signal, value int) ActionTriggerOption

WithSignalInt sets a signal to an int value before triggering the action.

type Context ¶

type Context struct {
	// contains filtered or unexported fields
}

Context is the living bridge between Go and the browser.

It holds runtime state, defines actions, manages reactive signals, and defines UI through View.

func (*Context) Action ¶

func (c *Context) Action(f func()) *actionTrigger

Action registers an event handler and returns a trigger to that event that that can be added to the view fn as any other via.h element.

Example:

n := 0
increment := c.Action(func(){
	 n++
	 c.Sync()
})

c.View(func() h.H {
	 return h.Div(
	 	 	h.P(h.Textf("Value of n: %d", n)),
	 	 	h.Button(h.Text("Increment n"), increment.OnClick()),
	 )
})

func (*Context) Component ¶

func (c *Context) Component(initCtx func(c *Context)) func() h.H

Component registers a subcontext that has self contained data, actions and signals. It returns the component's view as a DOM node fn that can be placed in the view of the parent. Components can be added to components.

Example:

counterCompFn := func(c *via.Context) {
	(...)
}

v.Page("/", func(c *via.Context) {
	counterComp := c.Component(counterCompFn)

	c.View(func() h.H {
		return h.Div(
			h.H1(h.Text("Counter")),
			counterComp(),
		)
	})
})

func (*Context) ExecScript ¶

func (c *Context) ExecScript(s string)

func (*Context) GetPathParam ¶ added in v0.1.4

func (c *Context) GetPathParam(param string) string

GetPathParam retrieves the value from the page request URL for the given parameter name or an empty string if not found.

Example:

v.Page("/users/{user_id}", func(c *via.Context) {

		userID := GetPathParam("user_id")

		c.View(func() h.H {
				return h.Div(
						h.H1(h.Textf("User ID: %s", userID)),
				)
		})
})

func (*Context) OnInterval ¶ added in v0.1.4

func (c *Context) OnInterval(duration time.Duration, handler func()) *OnIntervalRoutine

OnInterval starts a go routine that sets a time.Ticker with the given duration and executes the given handler func() on every tick. Use *Routine.UpdateInterval to update the interval.

func (*Context) Signal ¶

func (c *Context) Signal(v any) *signal

Signal creates a reactive signal and initializes it with the given value. Use Bind() to link the value of input elements to the signal and Text() to display the signal value and watch the UI update live as the input changes.

Example:

mysignal := c.Signal("world")

c.View(func() h.H {
	return h.Div(
		h.P(h.Span(h.Text("Hello, ")), h.Span(mysignal.Text())),
		h.Input(mysignal.Bind()),
	)
})

Signals are 'alive' only in the browser, but Via always injects their values into the Context before each action call. If any signal value is updated by the server, the update is automatically sent to the browser when using Sync() or SyncSignsls().

func (*Context) Sync ¶

func (c *Context) Sync()

Sync pushes the current view state and signal changes to the browser immediately over the live SSE event stream.

func (*Context) SyncElements ¶

func (c *Context) SyncElements(elem ...h.H)

SyncElements pushes an immediate html patch over the live SSE stream to the browser that merges with the DOM

For the merge to occur, each top lever element in the patch needs to have an ID that matches the ID of an element that already sits in the view.

Example:

If the view already contains the element:

h.Div(
	h.ID("my-element"),
	h.P(h.Text("Hello from Via!"))
)

Then, the merge will only occur if the ID of one of the top level elements in the patch matches 'my-element'.

func (*Context) SyncSignals ¶

func (c *Context) SyncSignals()

SyncSignals pushes the current signal changes to the browser immediately over the live SSE event stream.

func (*Context) View ¶

func (c *Context) View(f func() h.H)

View defines the UI rendered by this context. The function should return an h.H element (from via/h).

Changes to signals or state can be pushed live with Sync().

type LogLevel ¶

type LogLevel int
const (
	LogLevelError LogLevel
	LogLevelWarn
	LogLevelInfo
	LogLevelDebug
)

type OnIntervalRoutine ¶ added in v0.1.4

type OnIntervalRoutine struct {
	// contains filtered or unexported fields
}

OnIntervalRoutine allows for defining concurrent goroutines safely. Goroutines started by *OnIntervalRoutine are tied to the *Context lifecycle.

func (*OnIntervalRoutine) Start ¶ added in v0.1.4

func (r *OnIntervalRoutine) Start()

Start executes the predifined goroutine. If no predifined goroutine exists, or it already started, Start does nothing.

func (*OnIntervalRoutine) Stop ¶ added in v0.1.4

func (r *OnIntervalRoutine) Stop()

Stop interrupts the predifined goroutine. If no predifined goroutine exists, or it already ustopped, Stop does nothing.

func (*OnIntervalRoutine) UpdateInterval ¶ added in v0.1.4

func (r *OnIntervalRoutine) UpdateInterval(d time.Duration)

UpdateInterval sets a new interval duration for the internal *time.Ticker. If the provided duration is equal of less than 0, UpdateInterval does nothing.

type Options ¶

type Options struct {
	// The development mode flag. If true, enables server and browser auto-reload on `.go` file changes.
	DevMode bool

	// The http server address. e.g. ':3000'
	ServerAddress string

	// Level of the logs to write to stdout.
	// Options: Error, Warn, Info, Debug.
	LogLvl LogLevel

	// The title of the HTML document.
	DocumentTitle string

	// Plugins to extend the capabilities of the `Via` application.
	Plugins []Plugin
}

Options defines configuration options for the via application

type Plugin ¶

type Plugin func(v *V)

Plugin is a func that can mutate the given *via.V app runtime. It is useful to integrate popular JS/CSS UI libraries or tools.

type V ¶

type V struct {
	// contains filtered or unexported fields
}

V is the root application. It manages page routing, user sessions, and SSE connections for live updates.

func New ¶

func New() *V

New creates a new *V application with default configuration.

func (*V) AppendToFoot ¶

func (v *V) AppendToFoot(elements ...h.H)

AppendToFoot appends the given h.H nodes to the end of the base HTML document body. Useful for including JS scripts.

func (*V) AppendToHead ¶

func (v *V) AppendToHead(elements ...h.H)

AppendToHead appends the given h.H nodes to the head of the base HTML document. Useful for including css stylesheets and JS scripts.

func (*V) Config ¶

func (v *V) Config(cfg Options)

Config overrides the default configuration with the given options.

func (*V) HandleFunc ¶

func (v *V) HandleFunc(pattern string, f http.HandlerFunc)

HandleFunc registers the HTTP handler function for a given pattern. The handler function panics if in conflict with another registered handler with the same pattern.

func (*V) Page ¶

func (v *V) Page(route string, initContextFn func(c *Context))

Page registers a route and its associated page handler. The handler receives a *Context that defines state, UI, signals, and actions.

Example:

v.Page("/", func(c *via.Context) {
	c.View(func() h.H {
		return h.H1(h.Text("Hello, Via!"))
	})
})

func (*V) Start ¶

func (v *V) Start()

Start starts the Via HTTP server on the given address.

Directories ¶

Path Synopsis
h
Package h provides a Go-native DSL for HTML composition.
Package h provides a Go-native DSL for HTML composition.
internal

Jump to

Keyboard shortcuts

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