gomponents: pure Go components for server-rendered HTML
HTML components in pure Go.
At a glance
- What is it?
- gomponents builds reusable HTML 5 components as Go values and renders them directly to an io.Writer. It suits server-rendered Go applications that want component composition without a separate template syntax or build step.
- Who is it for?
- gomponents is a good fit for Go teams that want HTML components to remain ordinary Go code and prefer to avoid a separate template language or additional build step. It is less suitable if a template-oriented workflow or direct manipulation of a template AST is central to the application.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- maragudk/gomponents1,918 ★ · +7
| Repository | 2026-10-16 | 2026-10-23 |
|---|---|---|
| maragudk/gomponents | 1.9k | 1.9k |
7 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
gomponents replaces template syntax with Go composition
gomponents addresses a narrow but common problem in server-rendered Go applications: expressing reusable HTML without maintaining markup in template files and passing application data through a template-oriented API. It represents elements, attributes, text, and conditionals as Go values. A component can therefore be an ordinary function, receive ordinary Go parameters, and return a `Node`.
The intended users are Go developers building HTML 5 interfaces who want compiler assistance, IDE completion, `gofmt` and `goimports` support, and standard Go debugging. The README presents gomponents as a way to focus on application code rather than learning another templating language. It does not provide a client-side component runtime, browser reactivity system, asset pipeline, or JavaScript compiler. Its scope is constructing and rendering HTML on the server.
That distinction matters when choosing the library. A gomponents component is not a browser widget and does not own client-side state. It describes server-produced markup. The README example builds navigation from links, conditionally includes a profile link, marks the active route, and inserts an escaped label through `Text`. This is a direct fit for pages and fragments rendered by a Go web server, but it does not replace a frontend framework for interactive browser behavior.
Nodes render directly through the gomponents package layout
The repository divides the library by responsibility. The core `gomponents` package defines interfaces and functions such as `Node`, `El`, `Attr`, `Map`, `Group`, `If`, `Text`, and `Raw`. The `gomponents/html` package supplies HTML elements and attributes, while `gomponents/components` contains higher-level components and utilities. HTTP-oriented code lives in `gomponents/http`, and experimental packages are grouped under `gomponents/x/...`.
A typical component imports packages from all three of the main layers. `Nav` and `A` construct elements, `Href` and `Classes` express attributes, and `Text` adds content. The rendered value can then be composed by ordinary Go control flow. The README also documents `Map` for turning data into components, `Group` for grouping nodes, and `If` and `Iff` for conditional rendering.
The README states that rendering writes directly to an `io.Writer`. It also says the implementation avoids unnecessary allocations where possible, but that is a design claim rather than a guarantee for every application. The project includes benchmarks and a Makefile target for running them. The README publishes results for constructing and rendering a realistic page to `io.Discard` on an Apple M4, including 2,858 allocations for that case. Those figures describe the maintainer's benchmark, not a prediction for an application with different component depth or output volume.
Void elements receive special handling. Elements such as `br`, `img`, and `input` are rendered without closing tags through an internal void-element list. If children are supplied while creating such an element, the renderer ignores nodes that are not attributes. This preserves valid HTML output, although it also means application code cannot attach ordinary child content to void elements and expect it to appear.
Install gomponents and build a navigation component
The documented installation is the standard Go module command. Add the module to the project that will construct the HTML components.
go get maragu.dev/gomponentsThe module declares Go 1.18 in `go.mod`. A first component can then follow the README's navigation example. The example receives an authentication flag and the current path, creates a `Nav`, and includes profile navigation only when the caller is authenticated.
package main
import (
. "maragu.dev/gomponents"
. "maragu.dev/gomponents/components"
)The imports above are only the first part of the complete example. Add the `gomponents/html` package, then define the functions that return `Node` values.
func Navbar(authenticated bool, currentPath string) Node {
return Nav(
NavbarLink("/", "Home", currentPath),
NavbarLink("/about", "About", currentPath),
If(authenticated, NavbarLink("/profile", "Profile", currentPath)),
)
}The component helper creates each link and adds the `is-active` class when its `href` matches `currentPath`. Dot imports are optional, so applications that avoid them can qualify each exported name with its package path.
func NavbarLink(href, name, currentPath string) Node {
return A(Href(href), Classes{"is-active": currentPath == href}, Text(name))
}This example demonstrates the normal data flow: application state enters as Go arguments, composition produces a `Node`, and standard Go conditions determine optional content. `Text` inserts escaped text. For trusted, pre-rendered markup, `Raw` inserts a raw string, but its use creates a deliberate distinction between escaped and unescaped content.
The public API favors small helpers over larger template features
gomponents includes conveniences for several recurring rendering tasks. `Text` and `Textf` handle escaped text, while `Raw` and `Rawf` insert strings without escaping. `Map` maps data to components, `Group` groups child nodes, and `If` and `Iff` support conditional output. These names cover common needs without introducing a general-purpose flow-control system inside the core package.
That restraint has consequences for extension design. The README states that new flow control functions such as `IfElse` and `Else` are unlikely to be added to the core API. Generic collection operations such as `Map`, `Filter`, and `Reduce` are directed toward the experimental `x/slices` package. Developers needing a specialized traversal or rendering pattern may therefore keep a local helper or write an immediately invoked function, as shown in the README.
Dot imports can make compact HTML declarations resemble ordinary HTML, but they also place multiple package APIs into the file namespace. The README explicitly notes that they are optional. This gives teams a choice between terse declarations and imports that make the source of `Nav`, `A`, `Text`, and other names easier to trace.
The package boundaries also separate stable expectations from experimental ones. The README says experimental `gomponents/x/...` packages do not have the same compatibility guarantees as the core and may contain breaking changes. Applications built around those packages should review each module path before upgrades. Core functionality is intentionally limited, so gomponents works best when its small API is sufficient rather than when every desired abstraction belongs in one rendering library.
gomponents, html/template, and Templ solve different authoring problems
The closest alternatives named by the project are Go's `html/template` and Templ. All three can produce HTML, but they place the component boundary in different places. gomponents constructs component values directly in Go and requires no separate build step, unlike approaches that require additional build steps.
The author gives a specific reason for gomponents: passing data through templates was considered less convenient. That does not make the alternatives incorrect. An existing application may already have an established `html/template` architecture, established template specialists, or conventions centered on template files. A team that values generated-code workflows may choose Templ for reasons that outweigh its separate toolchain. The README explicitly says that all three can achieve the same final HTML result.
gomponents is the wrong tool when the requested abstraction is primarily a template language rather than a Go function. It is also a poor fit for teams seeking built-in browser reactivity, component hydration, or a complete frontend build system. Its direct rendering model offers a narrower and more Go-native boundary, but application code must manage composition, state mapping, and output writing explicitly.
MIT licensing and recent releases affect upgrade planning
The repository is licensed under MIT. That permits use, modification, distribution, and private use under the license's stated conditions, while requiring preservation of the copyright and license notice. Projects that vendor dependencies, generate notices, or enforce automated license checks should account for `LICENSE` during integration. This is a technical review of the repository's declared terms, not legal advice.
The last push was on 2026-10-06, and release `v1.4.0` carries the same date. Its release description mentions an official coding-agent skill and numerous performance improvements. The previous releases were `v1.3.0` on 2026-04-14 and `v1.2.0` on 2025-08-19. The README describes the library as mature and stable with no breaking changes, but it also states that experimental packages under `x` may make breaking changes.
The repository's Makefile exposes concrete maintenance commands. Tests run across all packages with randomized test order, while fuzz targets are discovered from files declaring functions with the `Fuzz` prefix.
go test -shuffle on ./...The benchmark target runs the benchmark suite with memory measurements.
go test -bench . -benchmem ./...For upgrade cost, the main boundary is package stability rather than the module's lack of a separate build tool. Core consumers should review release notes and API changes, while users of `gomponents/x/...` need closer scrutiny because the documented compatibility policy differs.
gomponents fits Go servers that want HTML as Go values
The decisive benefit is not that gomponents can render HTML. Go's standard tooling and several libraries can do that. Its specific choice is to make reusable HTML components ordinary Go functions returning `Node` values. That gives teams compiler and editor integration, standard formatting, and conditional composition without a separate template syntax or generation step.
The trade-off is equally specific. The library concentrates on server-side HTML construction and does not supply a frontend runtime or a broad feature set. Core extensions are deliberately constrained, while experimental packages can change across releases. Dot imports are optional but common in the short example, and misused raw content can bypass the protection provided by `Text` and `Textf`.
gomponents should be adopted by Go teams that want reusable server-rendered components to live inside their normal module and debugging workflow. It should not displace `html/template` or Templ without agreement on the team's preferred authoring model, and it is unsuitable as a stand-alone answer for interactive client-side interfaces. The first verification should be a small component composed from the project's real application data, rendered through the application's actual HTTP writer, and reviewed for escaped text, conditional children, and the output format expected by existing integration tests.
Editorial conclusion
gomponents is a good fit for Go teams that want HTML components to remain ordinary Go code and prefer to avoid a separate template language or additional build step. It is less suitable if a template-oriented workflow or direct manipulation of a template AST is central to the application. Before adoption, verify that direct Go composition fits the team's code organization, inspect how the application writes rendered nodes to its HTTP response, and confirm that the required HTML elements and attributes are covered by the API.
Frequently asked questions
How do I install gomponents in a Go project?
Run `go get maragu.dev/gomponents`, then import the core package plus `maragu.dev/gomponents/html` and `maragu.dev/gomponents/components` for the README's component example. The module declares Go 1.18.
Is gomponents production-ready?
The README describes gomponents as mature, stable, fully tested, and used in production by its author and others. This is the maintainer's statement rather than an independent audit, so an adopting team should still run its own integration and rendering checks.
Should I choose gomponents, html/template, or Templ?
gomponents constructs components directly in Go without an extra build step. The README says all three can produce the same final HTML.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/maragudk-gomponents)Star history chart for your README
[](https://hysenlabs.com/projects/maragudk-gomponents)Was this useful?