templ-components

Server-rendered Go components that ship real HTML — no JavaScript framework required. Built on templ, HTMX, and Tailwind CSS v4.
Documentation · Quick Start · Component Catalog
No DaisyUI. No Node.js. No framework lock-in.
Why templ-components?
94 server-rendered components. 37 typed string enums. 102 SVG icons. Zero client-side framework.
templ-components follows HATEOAS — the server renders HTML, JavaScript enhances it rather than replacing it. Every component uses Tailwind CSS v4 utility classes with built-in dark mode, CSP nonce support, and ARIA accessibility.
| Feature |
templ-components |
templUI |
goshipit |
| CSS approach |
Tailwind v4 (CSS-first) |
Tailwind + CSS vars |
Tailwind + DaisyUI |
| JavaScript |
HATEOAS (enhances HTML) |
Alpine.js |
DaisyUI JS |
| Requires Node.js |
No |
No |
Yes |
| Components |
94 |
40+ |
— |
| Typed props |
37 enums |
— |
— |
| Dark mode |
Built-in (tested) |
CSS custom properties |
Via DaisyUI |
| CSP compliant |
Yes (nonce on all scripts) |
Yes |
— |
| HTMX integration |
Built-in package |
— |
— |
| Standalone library |
Yes |
No |
No |
Quick Start
1. Install
go get github.com/larsartmann/templ-components
Build flag required: this library uses encoding/json/v2 (via
errorpage). Set GOEXPERIMENT=jsonv2 when building until Go 1.27 ships it
as stable:
export GOEXPERIMENT=jsonv2
2. Build a page
package main
import (
"github.com/larsartmann/templ-components/layout"
"github.com/larsartmann/templ-components/display"
"github.com/larsartmann/templ-components/icons"
)
templ Dashboard() {
@layout.Base(layout.DefaultPageProps()) {
@layout.ThemeScript("")
@display.PageHeader(display.PageHeaderProps{Title: "Dashboard"})
@display.Grid(display.GridProps{Cols: display.GridCols3}) {
@display.StatCard(display.StatCardProps{
Label: "Revenue", Value: "$42,189", Trend: display.TrendUp,
})
@display.StatCard(display.StatCardProps{
Label: "Users", Value: "1,204", Icon: icons.Users,
})
}
}
}
3. Generate and run
templ generate && go run .
Full guide: Installation · Quick Start
Component Catalog
display — Data Display (30 components)
Cards, tables (Table + DataTable), tabs, modals, badges, buttons, avatars, tooltips, accordions, dropdowns, stat cards, page headers, definition lists, responsive grid, carousel, and more.
@display.Card(display.CardProps{Title: "Users", Subtitle: "Manage users"}) {
<p>Card content</p>
}
@display.Card(display.CardProps{
Title: "Users",
TitleClass: "text-indigo-600",
HeaderClass: "bg-gray-50 dark:bg-gray-900/50",
}) {
<p>Override title and header classes without replacing the whole header.</p>
}
@display.StatCard(display.StatCardProps{Label: "Users", Value: "1,204", Icon: icons.Users, Change: "12%", Trend: display.TrendUp})
@display.Grid(display.GridProps{Cols: display.GridCols3, Gap: display.GridGapLG}) {
for _, u := range users {
@display.Card(display.CardProps{Title: u.Name}) { <p>{ u.Email }</p> }
}
}
@display.Table(display.TableProps{
Headers: []string{"Name", "Email", "Role"},
Rows: []display.TableRow{
display.SimpleTableRow("Alice", "alice@example.com", "Admin"),
},
Striped: true,
})
@display.Modal(display.ModalProps{Title: "Confirm", Size: display.ModalSizeSM}) {
<p>Are you sure?</p>
}
feedback — User Feedback (13 components)
Alerts, toasts, spinners, progress bars, skeletons, step indicators, loading states.
@feedback.ToastContainer("")
@feedback.Toast(feedback.ToastProps{Message: "Saved!", Type: feedback.ToastSuccess})
@feedback.Alert(feedback.AlertProps{Title: "Warning", Type: feedback.AlertWarning})
@feedback.ProgressBar(feedback.ProgressBarProps{Current: 45, Total: 100})
@feedback.SkeletonCardGrid(6)
Inputs, selects, textareas, checkboxes, radios, toggles, file inputs, date pickers, comboboxes, sliders, ratings, tags input, validation.
@forms.Input(forms.InputProps{Name: "email", Type: forms.InputEmail, Label: "Email"})
@forms.Select(forms.SelectProps{Name: "country", Label: "Country",
Options: []forms.SelectOption{{Value: "de", Label: "Germany"}}})
@forms.Toggle(forms.ToggleProps{Name: "notifications", Label: "Enable notifications"})
@forms.Combobox(forms.ComboboxProps{Name: "country", Label: "Country",
Options: []forms.ComboboxOption{{Value: "de", Label: "Germany"}}})
navigation — Navigation (12 components)
Nav bars, breadcrumbs, pagination, mobile menus, sidebar, load-more.
@navigation.SimpleNav(navigation.SimpleNavProps{BrandText: "MyApp", CurrentPath: "/"})
@navigation.Breadcrumbs(navigation.BreadcrumbsProps{Items: []navigation.BreadcrumbItem{
{Text: "Home", Href: "/"}, {Text: "Users", Active: true},
}})
@navigation.Pagination(navigation.PaginationProps{CurrentPage: 2, TotalPages: 10})
@navigation.SidebarNav(navigation.SidebarNavProps{CurrentPath: "/users"})
icons — SVG Icons (102 icons)
Typed icon constants, no icon library dependency.
@icons.Icon(icons.Home, "h-5 w-5 text-gray-500")
@icons.Icon(icons.Check, "h-6 w-6 text-green-500")
htmx — HTMX Integration (8 components)
Loading indicators, error handling, CSRF protection, out-of-band swaps, View Transitions.
@htmx.GlobalErrorHandling(htmx.DefaultErrorHandlingConfig())
@htmx.LoadingIndicator(feedback.Spinner(feedback.SpinnerMD, "text-blue-600"))
@htmx.ViewTransitions(htmx.ViewTransitionsProps{Global: true})
errorpage — Error Pages (4 components)
Structured error pages with family-aware styling, HTTP handler integration, dedicated 404.
@errorpage.NotFound404(errorpage.DefaultNotFound404Props())
@errorpage.ErrorPage(errorpage.ErrorPageProps{Family: errorpage.FamilyNotFound, Why: "Not found"})
Design Principles
Type-safe. 37 typed string enums make invalid states unrepresentable. Props structs embed utils.BaseProps for consistent ID, class, attributes, ARIA label, and CSP nonce propagation.
Accessible. ARIA attributes, roles, keyboard navigation, and screen-reader text across all interactive components. Native <dialog> for modals, <details> for accordions, <search> landmark for search inputs.
CSP-ready. All inline scripts use nonce attributes. No eval(), no inline event handlers. Integration test suite verifies compliance on every component.
Dark mode. Every component has proper dark: variants — enforced by TestDarkModeCompliance + TestDarkModeSemanticColors regression tests. ThemeScript prevents FOUC.
Server-rendered. Zero client-side JavaScript by default. Interactive features use minimal vanilla JS with nonce-based CSP.
Pay for what you use. Import only the packages you need. No monolithic bundle.
Tailwind CSS Setup
Tailwind v4 uses CSS-first configuration. Vendor the dependency so Tailwind can scan the .templ source files:
go mod vendor
Then in your CSS:
@import "tailwindcss";
@source "../vendor/github.com/larsartmann/templ-components";
@custom-variant dark (&:where(.dark, .dark *));
tailwindcss -i app.css -o styles.css --minify
If your project uses BuildFlow, the tailwind-build provider handles this automatically.
Theming
Components emit standard Tailwind classes (bg-blue-600, text-gray-900). Override colors without touching component code:
@theme {
--color-blue-600: #4f46e5;
--color-blue-500: #6366f1;
}
For semantic tokens (bg-tc-primary, text-tc-danger), copy the included templ-components-theme.css.
See the Theming guide for details.
By the Numbers
| Metric |
Value |
| Components |
94 |
| SVG icons |
102 |
| Typed enums |
34 |
| Packages |
9 |
| Tests |
~890 functions + ~1,650 subtests |
| Dependencies |
3 (templ, tailwind-merge-go, go-error-family) |
Requirements
- Go 1.26+ (
GOEXPERIMENT=jsonv2)
- templ CLI (install)
- Tailwind CSS 4.x+
- HTMX 2.x (optional, for
htmx package)
Ecosystem
This library is part of the GOTH stack (Go + Templ + HTMX):
| Project |
What it does |
| cqrs-htmx |
Production CQRS+ES framework with WebAuthn, RBAC, multi-tenancy, SSE. |
| go-cqrs-lite |
Minimal CQRS/ES building blocks. |
| go-error-family |
Structured error families. Used by templ-components' errorpage package. |
Contributing
Contributions are welcome. See CONTRIBUTING.md for setup, conventions, and workflow.
License
MIT