templ
website·Indexed 34 days ago
https://templ.guideA library for Go that allows developers to write HTML templates that compile to Go code. It supports components, server-side rendering with streaming, static site generation, and integration with tools like htmx, Chi, and Echo. The toolset includes a command-line tool for template generation and features for live reloading.
What's inside templ
- templUI is a UI component library built specifically for templ. It leverages the Go type system for safety, Alpine.js for interactivity, and Tailwind CSS for styling. It includes over 30 ready-made components (such as buttons, cards, modals, and charts), is CSP compliant, and is designed for production-ready enterprise applications.
Overview of templ for HTML components in Go
templ is a tool for creating components that render HTML fragments, which can be composed into full pages or applications. It compiles components into performant Go code and supports both server-side rendering (via serverless functions, Docker, or standard Go programs) and static HTML generation. It allows the use of standard Go logic (if,switch,for) and requires no JavaScript for its core functionality.Understand the default templ rendering lifecycle
By default,templ.Handlerrenders the entire template to a buffer before writing it to the response. This ensures that if a template fails to render, the server can still set the appropriate HTTP response code and avoid sending a partial, broken response to the client.Manage templ generated files in version control
It is recommended to commit generated*_templ.gofiles to your source code repository. This ensures the codebase remains buildable (e.g., viago install) and usable as a dependency in other projects without requiring the end-user to runtempl generatemanually.Integrate React components as islands of interactivity in templ
To use React components within a templ application, follow an 'islands' architecture: templ renders the initial server-side HTML (including placeholder elements with specific IDs), and a client-side JavaScript bundle mounts the React components into those placeholders.
- Create React Components: Define components using TSX/JSX.
- Create templ Placeholders: Use templ to render
divelements with unique IDs where React components should be mounted. - Mount Components: Write a TypeScript/JavaScript entry point that uses
createRootfromreact-dom/clientto target those IDs and render the components. - Bundle and Serve: Use a tool like
esbuildto bundle the JS/TSX and serve it as a static asset via a Go web server.
// react/index.ts import { createRoot } from 'react-dom/client'; import { Header } from './components'; const headerRoot = document.getElementById('react-header'); if (headerRoot) { createRoot(headerRoot).render(<Header />); }// components.templ templ page() { <html> <body> <div id="react-header"></div> <script src="/static/index.js"></script> </body> </html> }Sanitize and handle URL attributes in templ
Attributes expecting URLs (e.g.,
href,src,action) are automatically sanitized when using dynamic values to prevent harmful protocols likejavascript:. Unsafe URLs are replaced withabout:invalid#TemplFailedSanitizationURL.- To bypass sanitization: Use
templ.SafeURL(myURL). - For non-standard URL attributes (e.g.,
hx-get): Usetempl.URL(urlString)to manually sanitize. - Constant values (e.g.,
href="javascript:alert()") are not sanitized.
// Automatic sanitization <a href={ p.URL }>{ p.Name }</a> // Manual sanitization for non-standard attributes <div hx-get={ templ.URL(fmt.Sprintf("/contacts/%s/email", contact.ID)) }> { contact.Name } </div>- To bypass sanitization: Use
Understand templ Component basics
templ Components are markup and code defined in.templfiles that are compiled into Go functions via thetempl generatecommand. Each generated function returns atempl.Componentinterface. Components support HTML elements, text, expressions, branching (if,switch), andforloops. Visibility follows Go rules: components starting with an uppercase letter are public; others are private.// header.templ package main templ headerTemplate(name string) { <header data-testid="headerTemplate"> <h1>{ name }</h1> </header> }Use experimental templ packages
Experimental packages for templ are hosted athttps://github.com/templ-go/x/. These packages are provided without guarantees of stability, compatibility with future versions, or permanence; they may be removed at any time and should be used at the developer's own risk.Implement an onion architecture for Go and templ applications
The onion model separates the application into layers where each layer is unaware of the layer above it. This ensures a clear separation of concerns:
- HTTP Handler Layer: Processes requests, orchestrates the use of services, and uses
components(templ) to render HTML responses. It contains no business logic. - Service Layer: Implements application logic, orchestrates API calls, and manages database interactions. It is agnostic of HTTP and HTML.
- Database Access Layer: Handles raw database activity (queries/inserts) and prevents database-specific records from leaking into the service layer.
For larger applications, a
modelspackage can be added for shared data structures (e.g., aUserstruct).- HTTP Handler Layer: Processes requests, orchestrates the use of services, and uses
Enable live reload with templ generate
Use thetempl generate --watchcommand to automatically re-generate Go code from*.templfiles and restart the web server when*.gofiles change. By adding the--proxyflag, templ runs an HTTP proxy (defaulting tolocalhost:7331) that injects JavaScript into the response to automatically reload the browser window without manual refreshing.templ generate --watch --proxy="http://localhost:8080" --cmd="go run ."Render content once per page using OnceHandler
To ensure a piece of content is rendered only once per page—even if the component containing it is called multiple times—use
templ.NewOnceHandler(). This is typically used for<script>,<style>, or<link>tags.Critical Warning: Do not call
@templ.NewOnceHandler().Once()directly inside a component. This creates a new handler instance on every call, defeating the purpose and causing the content to be rendered multiple times. Instead, define the handler as a variable outside the component scope.package once // Define the handler outside the component to persist across renders var helloHandle = templ.NewOnceHandler() templ hello(label, name string) { @helloHandle.Once() { <script> function hello(name) { alert('Hello, ' + name + '!'); } </script> } <input type="button" value={ label } data-name={ name } onclick="hello(this.getAttribute('data-name'))"/> }Prevent injection attacks in templ scripts and styles
To prevent user-provided data from injecting vulnerabilities, templ prohibits the use of variables within<script>and<style>tags. These sections must contain only static content.templ Example() { <script> function showAlert() { alert("hello"); } </script> <style type="text/css"> /* Only CSS is allowed */ </style> }