templ

repository·main·Indexed 27 days ago

https://github.com/a-h/templ

An 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.

Tokens
50.4K
Snippets
164
Records
267
Agent score
94%

What's inside templ

  1. Overview of templ

    main
    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.
  2. Introduction to templ

    main

    templ 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.
  3. Understand templ Components

    main

    templ Components are markup and code that are compiled into Go functions via the templ generate command. These functions return a templ.Component interface.

    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.Component may write partial output to an io.Writer before returning an error. To ensure atomic output (either the full component or nothing), render to a buffer first before writing the buffer to the final io.Writer.

  4. Implement a common page layout with templ

    main

    To provide a consistent structure across your application (e.g., including <head>, scripts, and CSS), create a base Page component that accepts a templ.Component as a slot. You can then use a helper function to wrap this component into a standard http.Handler.

    1. Define a Page template with a content slot.
    2. Use templ.Handler to convert the component into a handler.
    3. Create a helper function that wraps the Page with 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))
    }
  5. Use switch statements for conditional rendering in templ

    main

    templ supports standard Go switch statements 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, including case and default blocks.

    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>
    	}
    }
  6. Perform Snapshot Testing with htmldiff

    main

    Snapshot testing checks that the rendered output matches a previously saved version to detect regressions.

    To use htmldiff.Diff for comparing components against expected HTML, you must have prettier installed and available in your system's PATH.

    Usage:

    1. Embed your expected HTML using //go:embed.
    2. Call htmldiff.Diff(component, expected).
    3. If a difference is detected, htmldiff.Diff returns the diff string and the actual rendered 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)
    	}
    }
  7. Configure templ proxy in watch mode

    main

    To start the templ proxy server in watch mode, use the generate --watch command. 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=false
  8. Serve static content in a Go application

    main

    To serve the static assets included in your Docker container, use http.FileServer combined with http.StripPrefix. This allows you to map a URL path (like /assets/) to a local directory on the filesystem (like assets).

    // Include the static content.
    // highlight-next-line
    mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))
  9. Verify generated templ files in CI/CD

    main

    To ensure that all *_templ.go files are up-to-date with their corresponding .templ source files in a CI/CD pipeline, run templ generate followed by git diff --exit-code.

    If the generated files are out of sync, git diff --exit-code will 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