SkillAgentSearch skills...

Hlive

HLive is a server-side WebSocket based dynamic template-less view layer for Go.

Install / Use

/learn @SamHennessy/Hlive
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

HLive

Server-side virtual DOM

HLive is a server-side WebSocket based dynamic template-less view layer for Go.

HLive is a fantastic tool for creating complex and dynamic browser-based user interfaces for developers who want to keep all the logic in Go.

All the power and data available on the backend with the responsive feel of a pure JavaScript solution.

It's a great use case for admin interfaces and internal company tools.

Notice

The first version of the API is under active development. Change is likely. Your feedback is welcome.

Please help the project by building something and giving us your feedback.

Table of contents

Quick Start Tutorial

Step 1: Static Page

Import HLive using the optional alias l:

package main

import l "github.com/SamHennessy/hlive"

Let's create our first page:

func home() *l.Page {
	page := l.NewPage()
	page.DOM.Body.Add("Hello, world.")

	return page
}

Next we use a PageServer to add it to an HTTP router:

func main() {
	http.Handle("/", l.NewPageServer(home))

	log.Println("Listing on :3000")

	if err := http.ListenAndServe(":3000", nil); err != nil {
		log.Println("Error: http listen and serve:", err)
	}
}

Your editor should add the extra imports http and log for you.

You can now run it, for example:

go run ./tutorial/helloworld/helloworld.go

In a browser go to http://localhost:3000 you should see this:

Hello world step 1

Step 2: Interactive Page

HLive is all about interactive content. We're going to add a text input field to let us type our own hello message.

We need to replace our existing home function. We need a string to hold our message:

func home() *l.Page {
	var message string

Now we're going to create a Component. Component's are HTML tags that can react to browser events. We are going to base our Component on the input HTML tag.

	input := l.C("input")

We want to set the input to a text type. We do this adding aAttrs map to our Component.

	input.Add(l.Attrs{"type": "text"})

Here we add an EventBinding to listen to "keyup" JavaScript events. When triggered, the handler function will be called. Our handler will update message. It does this by using the data passed in the Event parameter.

	input.Add(l.On("keyup", func(ctx context.Context, e l.Event) {
		message = e.Value
	}))

We create a new Page like before:

	page := l.NewPage()

Here we add our input to the body but first we wrap it in a div tag.

	page.DOM.Body.Add(l.T("div", input))

Next, we will display our message. Notice that we're passing message by reference. That's key for making this example work. We'll also add an "hr" tag to stop it being squashed todeather.

	page.DOM.Body.Add(l.T("hr"))
	page.DOM.Body.Add("Hello, ", &message)

Finally, we return the Page we created.

	return page
}

Let's see that all together, but this time I'm going to use some shortcuts. Can you spot the differences?

func home() *l.Page {
	var message string

	input := l.C("input",
		l.Attrs{"type": "text"},
		l.OnKeyUp(func(ctx context.Context, e l.Event) {
			message = e.Value
		}),
	)

	page := l.NewPage()
	page.DOM.Body.Add(
		l.T("div", input),
		l.T("hr"),
		"Hello, ", &message,
	)

	return page
}

Run it and type something into the input. The page should update to display what you typed.

Hello world step 2

Examples

The examples can be run from the root of the project using go run <path_to_example>. For example:

go run _example/click/click.go

Simple

Click

_example/click/click.go

Click a button see a counter update.

https://user-images.githubusercontent.com/119867/131120937-64091d27-3232-4820-ab20-e579c86cfb92.mp4

Hover

_example/hover/hover.go

Hover over an element and see another element change

Diff Apply

_example/callback/callback.go

Trigger a Diff Apply event when a DOM change is applied in the browser. Use it to trigger server side logic.

Advanced

Animation

_example/animation/animation.go

Create a continuously changing animation by chaining Diff Apply callbacks.

Clock

_example/clock/clock.go

Push browser DOM changes from the server without the need for a user to interact with the page.

File Upload

_example/fileUpload/fileUpload.go

Use a file input to get information about a file before uploading it. Then trigger a file upload from the server when you're ready.

The file is uploaded via WebSocket as a binary (not base64 encoded) object.

Initial Sync

_example/initialSync/initialSync.go

Some browsers, such as FireFox, will not clear data from form fields when the page is reloaded. To the user there is data in the field and if they submit a form they expect that data to be recognised.

Initial sync is a client side process that will send this data to the server after a page refresh. You can check for this behavior in your event handlers.

This example also shows how to get multiple values from inputs that support that.

Local Render

_example/localRender/localRender.go

By default, all Components are rendered after each Event Binding that a user triggers.

You can disable this by turning Auto Render off for a component. You can then render that manually but this will rerender the whole page.

If you only want to re-render a single component, and it's children you can do that instead. It's easy to introduce subtle bugs when using this feature.

Session

_example/session/session.go

An example of how to implement a user session using middleware and cookies. It also shows our to pass data from middleware to Components.

Using middleware in HLive is just like any Go app.

To Do List

_example/todo/todo.go

A simple To Do list app.

URL Parameters

_example/urlParams/urlParams.go

Passing URL params to Components is not straightforward in HLive. Here is an example of how to do it.

This is due to the HLive having a two-step process of loading a page and Components are primarily designed to get data from Events.

Concepts

Tag

A static HTML tag. A Tag has a name (e.g., an <p></p>'s name is p). A Tag can have zero or more Attributes. A Tag can have child Tags nested inside it. A Tag may be Void, which means it doesn't have a closing tag (e.g., <hr>). Void tags can't have child Tags.

Attribute

An Attribute has a name and a value. (e.g., href="https://example.com" or disabled="").

CSS Classes

The HLive implementation of Tag has an optional special way to work with the class attribute. These types are all designed to make toggling CSS classes on and off easy.

HLive's ClassBool is a map[string]bool type. The key is a CSS class, and the value enables the class for rending if tr

View on GitHub
GitHub Stars101
CategoryDevelopment
Updated1mo ago
Forks3

Languages

Go

Security Score

100/100

Audited on Feb 17, 2026

No findings