View components in pure Go, that render to HTML 5.
https://www.gomponents.com
.github/workflows | ||
assert | ||
attr | ||
components | ||
el | ||
examples/simple | ||
.editorconfig | ||
.gitignore | ||
CONTRIBUTING.md | ||
go.mod | ||
gomponents_test.go | ||
gomponents.go | ||
LICENSE | ||
Makefile | ||
README.md |
gomponents
gomponents are declarative view components in Go, that can render to HTML. gomponents aims to make it easy to build HTML pages of reusable components, without the use of a template language. Think server-side-rendered React, but without the virtual DOM and diffing.
The implementation is still incomplete, but usable. The API may change until version 1 is reached.
Check out the blog post gomponents: declarative view components in Go for background.
Usage
Get the library using go get
:
go get -u github.com/maragudk/gomponents
Then do something like this:
package main
import (
"net/http"
g "github.com/maragudk/gomponents"
"github.com/maragudk/gomponents/attr"
"github.com/maragudk/gomponents/el"
)
func main() {
_ = http.ListenAndServe("localhost:8080", handler())
}
func handler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
page := Page("Hi!", r.URL.Path)
_ = g.Write(w, page)
}
}
func Page(title, path string) g.Node {
return el.Document(
el.HTML(
g.Attr("lang", "en"),
el.Head(
el.Title(title),
el.Style(g.Attr("type", "text/css"), g.Raw(".is-active{font-weight: bold}")),
),
el.Body(
Navbar(path),
el.H1(title),
el.P(g.Textf("Welcome to the page at %v.", path)),
),
),
)
}
func Navbar(path string) g.Node {
return g.El("nav",
el.A("/", attr.Classes{"is-active": path == "/"}, g.Text("Home")),
el.A("/about", attr.Classes{"is-active": path == "/about"}, g.Text("About")),
)
}
You could also use a page template to simplify your code a bit:
package main
import (
"net/http"
g "github.com/maragudk/gomponents"
"github.com/maragudk/gomponents/attr"
c "github.com/maragudk/gomponents/components"
"github.com/maragudk/gomponents/el"
)
func main() {
_ = http.ListenAndServe("localhost:8080", handler())
}
func handler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
page := Page("Hi!", r.URL.Path)
_ = g.Write(w, page)
}
}
func Page(title, path string) g.Node {
return c.HTML5(c.DocumentProps{
Title: title,
Language: "en",
Head: []g.Node{el.Style(g.Attr("type", "text/css"), g.Raw(".is-active{font-weight: bold}"))},
Body: []g.Node{
Navbar(path),
el.H1(title),
el.P(g.Textf("Welcome to the page at %v.", path)),
},
})
}
func Navbar(path string) g.Node {
return g.El("nav",
el.A("/", attr.Classes{"is-active": path == "/"}, g.Text("Home")),
el.A("/about", attr.Classes{"is-active": path == "/about"}, g.Text("About")),
)
}
For more complete examples, see the examples directory.