templ
repository·main·Indexed 27 days ago
https://github.com/a-h/templAn HTML templating language for Go that provides type-safe components and developer tooling, including LSP support. It includes a CLI for compiling .templ files into Go code, a formatter (fmtcmd), and a development proxy for hot reloading with SSE support.
What's inside templ
- templ is an HTML templating language for Go designed with high-quality developer tooling. It allows you to write type-safe HTML components that integrate seamlessly with Go code.
Introduction to templ
maintempl is an HTML templating language for Go that allows you to create components that render HTML fragments. These components can be composed to build full screens, pages, or applications.
Key features include:
- Server-side rendering: Can be deployed as serverless functions, Docker containers, or standard Go programs.
- Static rendering: Supports generating static HTML files.
- Compiled code: Components are compiled directly into performant Go code.
- Go integration: Use standard Go logic (
if,switch,for) and call any Go code directly within templates. - No JavaScript required: Operates without client or server-side JavaScript.
- Developer experience: Provides IDE autocompletion.
Understand templ Components
maintempl Components are markup and code that are compiled into Go functions via the
templ generatecommand. These functions return atempl.Componentinterface.Components support:
- HTML elements
- Text and expressions (for outputting text or including other templates)
- Branching statements (
if,switch) - Loops (
for)
Visibility follows standard Go rules: components starting with an uppercase letter are public, while those starting with a lowercase letter are private.
Note on partial output: A
templ.Componentmay write partial output to anio.Writerbefore returning an error. To ensure atomic output (either the full component or nothing), render to a buffer first before writing the buffer to the finalio.Writer.Implement a common page layout with templ
mainTo provide a consistent structure across your application (e.g., including
<head>, scripts, and CSS), create a basePagecomponent that accepts atempl.Componentas a slot. You can then use a helper function to wrap this component into a standardhttp.Handler.- Define a
Pagetemplate with acontentslot. - Use
templ.Handlerto convert the component into a handler. - Create a helper function that wraps the
Pagewith your specific content component.
// layout/page.templ package layout templ Page(content templ.Component) { <!DOCTYPE html> <html> <head> <script src="/static/htmx.min.js"></script> <link rel="stylesheet" href="/static/bootstrap.css"/> </head> <body class="container"> @content </body> </html> } // layout/layout.go func Handler(content templ.Component) http.Handler { return templ.Handler(Page(content)) }- Define a
Use switch statements for conditional rendering in templ
maintempl supports standard Go
switchstatements within component definitions. You can use them to conditionally render different HTML elements or components based on a value. The syntax follows standard Go logic, includingcaseanddefaultblocks.package main templ userTypeDisplay(userType string) { switch userType { case "test": <span>{ "Test user" }</span> case "admin": <span>{ "Admin user" }</span> default: <span>{ "Unknown user" }</span> } }Perform Snapshot Testing with htmldiff
mainSnapshot testing checks that the rendered output matches a previously saved version to detect regressions.
To use
htmldiff.Difffor comparing components against expected HTML, you must haveprettierinstalled and available in your system'sPATH.Usage:
- Embed your expected HTML using
//go:embed. - Call
htmldiff.Diff(component, expected). - If a difference is detected,
htmldiff.Diffreturns thediffstring and theactualrendered content.
package testcomment import ( _ "embed" "os" "testing" "github.com/a-h/templ/generator/htmldiff" ) //go:embed expected.html var expected string func Test(t *testing.T) { component := render("sample content") actual, diff, err := htmldiff.Diff(component, expected) if err != nil { t.Fatal(err) } if diff != "" { if err := os.WriteFile("actual.html", []byte(actual), 0644); err != nil { t.Errorf("failed to write actual.html: %v", err) } t.Error(diff) } }- Embed your expected HTML using
Access templ documentation
mainFor comprehensive user documentation, guides, and tutorials, visit the official templ guide website.
https://templ.guideConfigure templ proxy in watch mode
mainTo start the
templproxy server in watch mode, use thegenerate --watchcommand. You should specify the proxy URL (where your Go server is running) and disable automatic browser opening to avoid conflicts with other watch processes.Example assuming your server runs on
http://localhost:8080:templ generate --watch --proxy="http://localhost:8080" --open-browser=falseServe static content in a Go application
mainTo serve the static assets included in your Docker container, use
http.FileServercombined withhttp.StripPrefix. This allows you to map a URL path (like/assets/) to a local directory on the filesystem (likeassets).// Include the static content. // highlight-next-line mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))Understand templ's Language Server Protocol (LSP) implementation
mainFor a deep dive into how the Language Server Protocol works from the ground up and howtempl's language server integrates withgopls, watch the Gophercon UK 2023 talk.Integrate React with templ using Islands Architecture
mainYou can use React components as 'islands of interactivity' within atemplapplication.templhandles the server-side rendering of the page structure, while React is used to provide specific interactive features on the client side by mounting components into specific HTML elements (usually identified byidordata-*attributes).Verify generated templ files in CI/CD
mainTo ensure that all
*_templ.gofiles are up-to-date with their corresponding.templsource files in a CI/CD pipeline, runtempl generatefollowed bygit diff --exit-code.If the generated files are out of sync,
git diff --exit-codewill return a non-zero exit code, causing the pipeline to fail. This prevents committing stale generated code and ensures the repository is always in a buildable state without requiring manual generation steps.templ generate git diff --exit-code