via

package module
v0.2.5 Latest Latest
Warning

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

Go to latest
Published: Jan 15, 2026 License: MIT Imports: 25 Imported by: 0

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, real-time engine for creating Go web applications. 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 ¶

func NewSQLiteSessionManager ¶ added in v0.2.5

func NewSQLiteSessionManager(db *sql.DB) (*scs.SessionManager, error)

NewSQLiteSessionManager creates a session manager using SQLite for persistence. Creates the sessions table if it doesn't exist. The returned manager can be configured further (Lifetime, Cookie settings, etc.) before passing to Options.SessionManager.

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 ¶

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 ¶

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) Redirect ¶

func (c *Context) Redirect(url string)

Redirect navigates the browser to the given URL. This triggers a full page navigation - the current context will be disposed and a new context created at the destination URL.

func (*Context) Redirectf ¶

func (c *Context) Redirectf(format string, a ...any)

Redirectf navigates the browser to a URL constructed from the format string and arguments.

func (*Context) ReplaceURL ¶

func (c *Context) ReplaceURL(url string)

ReplaceURL updates the browser's URL and history without triggering navigation. Useful for updating query params or path to reflect UI state changes.

func (*Context) ReplaceURLf ¶

func (c *Context) ReplaceURLf(format string, a ...any)

ReplaceURLf updates the browser's URL using a format string.

func (*Context) Session ¶

func (c *Context) Session() *Session

Session returns the session for this context. Session data persists across page views for the same browser. Returns a no-op session if no SessionManager is configured.

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 ¶

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 ¶

func (r *OnIntervalRoutine) Start()

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

func (*OnIntervalRoutine) Stop ¶

func (r *OnIntervalRoutine) Stop()

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

func (*OnIntervalRoutine) UpdateInterval ¶

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

	// SessionManager enables cookie-based sessions. If set, Via wraps handlers
	// with scs LoadAndSave middleware. Configure the session manager before
	// passing it (lifetime, cookie settings, store, etc).
	SessionManager *scs.SessionManager

	// DatastarContent is the Datastar.js script content.
	// If nil, the embedded default is used.
	DatastarContent []byte

	// DatastarPath is the URL path where the script is served.
	// Defaults to "/_datastar.js" if empty.
	DatastarPath string
}

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 Session ¶

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

Session provides access to the user's session data. Session data persists across page views for the same browser.

func (*Session) Clear ¶

func (s *Session) Clear() error

Clear removes all data from the session.

func (*Session) Delete ¶

func (s *Session) Delete(key string)

Delete removes a value from the session.

func (*Session) Destroy ¶

func (s *Session) Destroy() error

Destroy destroys the session entirely (use for logout).

func (*Session) Exists ¶

func (s *Session) Exists(key string) bool

Exists returns true if the key exists in the session.

func (*Session) Get ¶

func (s *Session) Get(key string) any

Get retrieves a value from the session.

func (*Session) GetBool ¶

func (s *Session) GetBool(key string) bool

GetBool retrieves a bool value from the session.

func (*Session) GetBytes ¶

func (s *Session) GetBytes(key string) []byte

GetBytes retrieves a []byte value from the session.

func (*Session) GetFloat64 ¶

func (s *Session) GetFloat64(key string) float64

GetFloat64 retrieves a float64 value from the session.

func (*Session) GetInt ¶

func (s *Session) GetInt(key string) int

GetInt retrieves an int value from the session.

func (*Session) GetString ¶

func (s *Session) GetString(key string) string

GetString retrieves a string value from the session.

func (*Session) GetTime ¶

func (s *Session) GetTime(key string) time.Time

GetTime retrieves a time.Time value from the session.

func (*Session) ID ¶

func (s *Session) ID() string

ID returns the session token (cookie value).

func (*Session) Keys ¶

func (s *Session) Keys() []string

Keys returns all keys in the session.

func (*Session) Pop ¶

func (s *Session) Pop(key string) any

Pop retrieves a value and deletes it from the session (flash message pattern).

func (*Session) PopBool ¶

func (s *Session) PopBool(key string) bool

PopBool retrieves a bool value and deletes it from the session.

func (*Session) PopBytes ¶

func (s *Session) PopBytes(key string) []byte

PopBytes retrieves a []byte value and deletes it from the session.

func (*Session) PopFloat64 ¶

func (s *Session) PopFloat64(key string) float64

PopFloat64 retrieves a float64 value and deletes it from the session.

func (*Session) PopInt ¶

func (s *Session) PopInt(key string) int

PopInt retrieves an int value and deletes it from the session.

func (*Session) PopString ¶

func (s *Session) PopString(key string) string

PopString retrieves a string value and deletes it from the session.

func (*Session) PopTime ¶

func (s *Session) PopTime(key string) time.Time

PopTime retrieves a time.Time value and deletes it from the session.

func (*Session) RenewToken ¶

func (s *Session) RenewToken() error

RenewToken regenerates the session token (use after login to prevent session fixation).

func (*Session) Set ¶

func (s *Session) Set(key string, val any)

Set stores a value in the session.

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) HTTPServeMux ¶

func (v *V) HTTPServeMux() *http.ServeMux

HTTPServeMux returns the underlying HTTP request multiplexer to enable user extentions, middleware and plugins. It also enables integration with test frameworks like gost-dom/browser for SSE/Datastar testing.

IMPORTANT. The returned *http.ServeMux can only be modified during initialization, before calling via.Start(). Concurrent handler registration is not safe.

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