### Go Web Server Example Source: https://templ.guide/developer-tools/live-reload A basic Go web server setup using Templ components. This file is typically run by the `--cmd` flag in `templ generate`. ```go package main import ( "fmt" "net/http" "github.com/a-h/templ" ) func main() { component := hello("World") http.Handle("/", templ.Handler(component)) fmt.Println("Listening on :8080") http.ListenAndServe(":8080", nil) } ``` -------------------------------- ### Initialize NPM Project and Install Dependencies Source: https://templ.guide/syntax-and-usage/script-templates Sets up a new Node.js project and installs TypeScript and esbuild as development dependencies. ```bash mkdir ts cd ts npm init npm install --save-dev typescript esbuild ``` -------------------------------- ### Install templ in Nix Flake Source: https://templ.guide/quick-start/installation Example configuration for integrating templ into a Nix Flake, either for NixOS or a project-specific flake. ```nix { inputs = { ... templ.url = "github:a-h/templ"; ... }; outputs = inputs@{ ... }: # For NixOS configuration: { # Add the overlay, nixpkgs.overlays = [ inputs.templ.overlays.default ]; # and install the package environment.systemPackages = with pkgs; [ templ ]; }; # For a flake project: let forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { inherit system; pkgs = import nixpkgs { inherit system; }; }); templ = system: inputs.templ.packages.${system}.templ; in { packages = forAllSystems ({ pkgs, system }: { myNewPackage = pkgs.buildGoModule { ... preBuild = "''${templ system}/bin/templ generate "; }; }); devShell = forAllSystems ({ pkgs, system }: pkgs.mkShell { buildInputs = with pkgs [ go (templ system) ]; }); } ``` -------------------------------- ### Build a URL with Path and Query Parameters Source: https://templ.guide/experimental/urlbuilder Use `urlbuilder.New` to start constructing a URL. Chain `Path` and `Query` methods to add segments and parameters. Finally, call `Build` to get a `templ.SafeURL`. ```go import ( "github.com/templ-go/x/urlbuilder" "strconv" "strings" ) templ component(o Order) { { strings.ToUpper(o.Name) } } ``` -------------------------------- ### Start HTTP Server in Go Source: https://templ.guide/syntax-and-usage/forms Starts the HTTP server on the specified address and port, returning any error encountered. ```go log.Info("Starting server", slog.String("address", addr)) return http.ListenAndServe(addr, mux) ``` -------------------------------- ### Troubleshooting: Check Binary Installation Source: https://templ.guide/developer-tools/ide-support Verify that Go, gopls, and templ binaries are installed and accessible in your system's PATH. This is crucial for IDE integration. ```bash which go gopls templ ``` ```text /run/current-system/sw/bin/go /Users/adrian/go/bin/gopls /Users/adrian/bin/templ ``` -------------------------------- ### Install templ Globally with Go Source: https://templ.guide/quick-start/installation Installs the templ CLI globally for use on your system. Requires Go 1.24 or greater. ```bash go install github.com/a-h/templ/cmd/templ@latest ``` -------------------------------- ### Main Entrypoint for Go Application Source: https://templ.guide/syntax-and-usage/forms Sets up logging, context, and calls the run function. Exits with an error code if the server fails to start. ```go var dbURI = "file:data.db?mode=rwc" var addr = "localhost:8080" func main() { log := slog.Default() ctx := context.Background() if err := run(ctx, log); err != nil { log.Error("Failed to run server", slog.Any("error", err)) os.Exit(1) } } ``` -------------------------------- ### Setup Templ Counter with Datastar SSE Source: https://templ.guide/server-side-rendering/datastar Sets up SSE endpoints for a templated counter example using Datastar. It handles global and per-user increments and updates the UI with changed signals. ```go package site import ( "net/http" "sync/atomic" "github.com/Jeffail/gabs/v2" "github.com/go-chi/chi/v5" "github.com/gorilla/sessions" "github.com/starfederation/datastar-go/datastar" ) func setupExamplesTemplCounter(examplesRouter chi.Router, sessionSignals sessions.Store) error { var globalCounter atomic.Uint32 const ( sessionKey = "templ_counter" countKey = "count" ) userVal := func(r *http.Request) (uint32, *sessions.Session, error) { sess, err := sessionSignals.Get(r, sessionKey) if err != nil { return 0, nil, err } val, ok := sess.Values[countKey].(uint32) if !ok { val = 0 } return val, sess, nil } examplesRouter.Get("/templ_counter/data", func(w http.ResponseWriter, r *http.Request) { userVal, _, err := userVal(r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } signals := TemplCounterSignals{ Global: globalCounter.Load(), User: userVal, } c := templCounterExampleInitialContents(signals) datastar.NewSSE(w, r).MergeFragmentTempl(c) }) updateGlobal := func(signals *gabs.Container) { signals.Set(globalCounter.Add(1), "global") } examplesRouter.Route("/templ_counter/increment", func(incrementRouter chi.Router) { incrementRouter.Post("/global", func(w http.ResponseWriter, r *http.Request) { update := gabs.New() updateGlobal(update) datastar.NewSSE(w, r).MarshalAndMergeSignals(update) }) incrementRouter.Post("/user", func(w http.ResponseWriter, r *http.Request) { val, sess, err := userVal(r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } val++ sess.Values[countKey] = val if err := sess.Save(r, w); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } update := gabs.New() updateGlobal(update) update.Set(val, "user") datastar.NewSSE(w, r).MarshalAndMergeSignals(update) }) }) return nil } ``` -------------------------------- ### Install templ as a Go Tool Source: https://templ.guide/quick-start/installation Installs templ locally within your project using Go's tool directive feature. Use 'go tool templ' to run it. ```bash go get -tool github.com/a-h/templ/cmd/templ@latest ``` -------------------------------- ### Run the Go Program Source: https://templ.guide/quick-start/running-your-first-templ-application Execute the Go program from your terminal to start the web server. Ensure you are in the directory containing your `main.go` file. ```bash go run *.go ``` -------------------------------- ### Main Application Entrypoint Source: https://templ.guide/project-structure/project-structure Configures and starts the HTTP server. It initializes the logger, database store, service layer, and HTTP handlers. Session middleware is added, and server timeouts are configured. The application listens on localhost:9000. ```go package main import ( "fmt" "net/http" "os" "time" "github.com/a-h/templ/examples/counter/db" "github.com/a-h/templ/examples/counter/handlers" "github.com/a-h/templ/examples/counter/services" "github.com/a-h/templ/examples/counter/session" "golang.org/x/exp/slog" ) func main() { log := slog.New(slog.NewJSONHandler(os.Stderr)) s, err := db.NewCountStore(os.Getenv("TABLE_NAME"), os.Getenv("AWS_REGION")) if err != nil { log.Error("failed to create store", slog.Any("error", err)) os.Exit(1) } cs := services.NewCount(log, s) h := handlers.New(log, cs) var secureFlag = true if os.Getenv("SECURE_FLAG") == "false" { secureFlag = false } // Add session middleware. sh := session.NewMiddleware(h, session.WithSecure(secureFlag)) server := &http.Server{ Addr: "localhost:9000", Handler: sh, ReadTimeout: time.Second * 10, WriteTimeout: time.Second * 10, } fmt.Printf("Listening on %v\n", server.Addr) server.ListenAndServe() } ``` -------------------------------- ### Serve Static Assets Before Live Reload Setup Source: https://templ.guide/developer-tools/live-reload-with-other-tools This Go code snippet demonstrates serving static assets using `http.FS` with `embed.FS` before implementing live reload. ```go //go:embed assets/* var assets embed.FS ... mux.Handle("/assets/", http.FileServer(http.FS(assets))) ``` -------------------------------- ### Multi-stage Dockerfile with templ Source: https://templ.guide/quick-start/installation An example Dockerfile demonstrating a multi-stage build process using the templ Docker image to generate code. ```dockerfile # Fetch FROM golang:latest AS fetch-stage COPY go.mod go.sum /app WORKDIR /app RUN go mod download # Generate FROM ghcr.io/a-h/templ:latest AS generate-stage COPY --chown=65532:65532 . /app WORKDIR /app RUN ["templ", "generate"] # Build FROM golang:latest AS build-stage COPY --from=generate-stage /app /app WORKDIR /app RUN CGO_ENABLED=0 GOOS=linux go build -o /app/app # Test FROM build-stage AS test-stage RUN go test -v ./... # Deploy FROM gcr.io/distroless/base-debian12 AS deploy-stage WORKDIR / COPY --from=build-stage /app/app /app EXPOSE 8080 USER nonroot:nonroot ENTRYPOINT ["/app"] ``` -------------------------------- ### Vim: Install LSP and Autocomplete Plugins Source: https://templ.guide/developer-tools/ide-support Use vim-plug to install the necessary plugins for LSP and autocompletion in Vim. Ensure you are using Vim version 8 or later. ```vim Plug 'prabirshrestha/vim-lsp' Plug 'prabirshrestha/asyncomplete.vim' Plug 'prabirshrestha/asyncomplete-lsp.vim' ``` -------------------------------- ### Prop Drilling Example in Templ Source: https://templ.guide/syntax-and-usage/context Demonstrates how data is passed through multiple components using props, leading to prop drilling. ```templ package main templ top(name string) {
Switch to Linux
{ `switch to Linux` }
{ "for a day" }
{ fmt.Sprintf("%f", price) }{ "for" }{ fmt.Sprintf("%d", count) }
{ fmt.Sprintf("%f for %d", price, count) }
} ``` -------------------------------- ### Error: Text Block Starting with Unescaped Keyword Source: https://templ.guide/syntax-and-usage/statements A text run starting with `if`, `for`, or `switch` without an immediately following opening brace `{` will cause a parser error. Use Go string expressions or capitalize the keyword to resolve this. ```templ package main templ text(b bool) {if a tree fell in the woods
} ``` -------------------------------- ### Handle GET Request to Display Form in Go Source: https://templ.guide/syntax-and-usage/forms Implement a handler for GET requests to display the form. This function populates the model with existing data if it's an edit request, or uses an empty model for new entries. ```go func (h *Handler) Get(w http.ResponseWriter, r *http.Request) { model := NewModel() // If it's an edit request, populate the model with existing data. if id := r.PathValue("id"); id != "" { contact, ok, err := h.DB.Get(r.Context(), id) if err != nil { h.Log.Error("Failed to get contact", slog.String("id", id), slog.Any("error", err)) http.Error(w, err.Error(), http.StatusInternalServerError) return } if !ok { http.Redirect(w, r, "/contacts/edit", http.StatusSeeOther) return } model = ModelFromContact(contact) } h.DisplayForm(w, r, model) } ``` -------------------------------- ### Create Project Directory Source: https://templ.guide/quick-start/creating-a-simple-templ-component Creates a new directory for your Go project. ```bash mkdir hello-world ``` -------------------------------- ### Implement Go Handlers for HTTP Requests Source: https://templ.guide/server-side-rendering/example-counter-application Implements Go handlers for GET and POST requests. The GET handler renders the page, while the POST handler parses form data, updates global state if the 'global' button was pressed, and then re-renders the page. ```go package main import ( "fmt" "log" "net/http" ) type GlobalState struct { Count int } var global GlobalState func getHandler(w http.ResponseWriter, r *http.Request) { component := page(global.Count, 0) component.Render(r.Context(), w) } func postHandler(w http.ResponseWriter, r *http.Request) { // Update state. r.ParseForm() // Check to see if the global button was pressed. if r.Form.Has("global") { global.Count++ } //TODO: Update session. // Display the form. getHandler(w, r) } func main() { // Handle POST and GET requests. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { postHandler(w, r) return } getHandler(w, r) }) // Start the server. fmt.Println("listening on http://localhost:8000") if err := http.ListenAndServe("localhost:8000", nil); err != nil { log.Printf("error listening: %v", err) } ``` -------------------------------- ### Accessing data from an HTML attribute Source: https://templ.guide/syntax-and-usage/script-templates Example of how to retrieve and parse JSON data from an HTML attribute using client-side JavaScript. ```javascript const button = document.getElementById('alerter'); const data = JSON.parse(button.getAttribute('alert-data')); ``` -------------------------------- ### Configure Go Web Server to Serve Static Assets Source: https://templ.guide/syntax-and-usage/script-templates Sets up an HTTP multiplexer in Go to serve static files from the 'assets' directory and handle Templ component requests. ```go func main() { mux := http.NewServeMux() // Serve the JS bundle. mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets")))) // Serve components. data := map[string]any{"msg": "Hello, World!"} h := templ.Handler(components.Page(data)) mux.Handle("/", h) fmt.Println("Listening on http://localhost:8080") http.ListenAndServe("localhost:8080", mux) } ``` -------------------------------- ### Define Translations in YAML Source: https://templ.guide/integrations/internationalization Translations are stored in YAML files, organized by language. This example shows the structure for English translations. ```yaml en: hello: "Hello" select_language: "Select Language" ``` -------------------------------- ### Setting and Rendering Context in Go Source: https://templ.guide/syntax-and-usage/context Demonstrates creating a context with a value and passing it to a Templ component's Render function. ```go // Define the context key type. type contextKey string // Create a context key for the theme. var themeContextKey contextKey = "theme" // Create a context variable that inherits from a parent, and sets the value "test". ctx := context.WithValue(context.Background(), themeContextKey, "test") // Pass the ctx variable to the render function. themeName().Render(ctx, w) ``` -------------------------------- ### Create a Button Component with templUI Source: https://templ.guide/component-libraries Demonstrates how to import and use the Button component from the templUI library. Ensure the 'components' and 'icons' packages are correctly imported. ```go import "github.com/axzilla/templui/components" templ ExamplePage() { @components.Button(components.ButtonProps{ Text: "Click me", IconRight: icons.ArrowRight(icons.IconProps{Size: "16"}), }) } ``` -------------------------------- ### Format All Templ Files Source: https://templ.guide/developer-tools/cli Demonstrates how to format all .templ files in the current directory and its subdirectories using the `templ fmt` command. ```bash templ fmt . ``` -------------------------------- ### Set Up HTTP Routes in Go Source: https://templ.guide/syntax-and-usage/forms Configures the HTTP multiplexer with handlers for various routes including home, contacts, and contact management (edit/delete). ```go mux := http.NewServeMux() homeHandler := home.NewHandler() mux.Handle("/", homeHandler) ch := contacts.NewHandler(log, db) mux.Handle("/contacts", ch) ceh := contactsedit.NewHandler(log, db) mux.Handle("/contacts/edit", ceh) mux.Handle("/contacts/edit/{id}", ceh) cdh := contactsdelete.NewHandler(log, db) mux.Handle("/contacts/delete/{id}", cdh) ``` -------------------------------- ### Accessing data from a script element Source: https://templ.guide/syntax-and-usage/script-templates Example of how to retrieve and parse JSON data embedded within a script element using client-side JavaScript. ```javascript const data = JSON.parse(document.getElementById('id').textContent); ``` -------------------------------- ### Handle GET Request for Contacts Source: https://templ.guide/syntax-and-usage/forms Retrieves a list of contacts from the database and renders them using the View template. Handles potential database errors. ```go func (h *Handler) Get(w http.ResponseWriter, r *http.Request) { contacts, err := h.DB.List(r.Context()) if err != nil { h.Log.Error("Failed to list contacts", slog.Any("error", err)) http.Error(w, err.Error(), http.StatusInternalServerError) return } v := layout.Handler(View(contacts)) v.ServeHTTP(w, r) } ``` -------------------------------- ### Go Main Function for Static Site Generation Source: https://templ.guide/static-rendering/blog-example Orchestrates the static site generation process by creating output directories, rendering the index page, and iterating through blog posts to create individual pages. It handles markdown conversion and integrates raw HTML using the Unsafe component. ```go package main import ( "bytes" "context" "io" "log" "os" "path" "time" "github.com/a-h/templ" "github.com/gosimple/slug" "github.com/yuin/goldmark" ) func main() { // Output path. rootPath := "public" if err := os.Mkdir(rootPath, 0755); err != nil { log.Fatalf("failed to create output directory: %v", err) } // Create an index page. name := path.Join(rootPath, "index.html") f, err := os.Create(name) if err != nil { log.Fatalf("failed to create output file: %v", err) } // Write it out. err = indexPage(posts).Render(context.Background(), f) if err != nil { log.Fatalf("failed to write index page: %v", err) } // Create a page for each post. for _, post := range posts { // Create the output directory. dir := path.Join(rootPath, post.Date.Format("2006/01/02"), slug.Make(post.Title)) if err := os.MkdirAll(dir, 0755); err != nil && err != os.ErrExist { log.Fatalf("failed to create dir %q: %v", dir, err) } // Create the output file. name := path.Join(dir, "index.html") f, err := os.Create(name) if err != nil { log.Fatalf("failed to create output file: %v", err) } // Convert the markdown to HTML, and pass it to the template. var buf bytes.Buffer if err := goldmark.Convert([]byte(post.Content), &buf); err != nil { log.Fatalf("failed to convert markdown to HTML: %v", err) } // Create an unsafe component containing raw HTML. content := Unsafe(buf.String()) // Use templ to render the template containing the raw HTML. err = contentPage(post.Title, content).Render(context.Background(), f) if err != nil { log.Fatalf("failed to write output file: %v", err) } } } ``` -------------------------------- ### Display form using layout handler Source: https://templ.guide/syntax-and-usage/forms Renders the form view within the application's common layout. This method is used by both GET and POST handlers. ```go func (h *Handler) DisplayForm(w http.ResponseWriter, r *http.Request, m Model) { layout.Handler(View(m)).ServeHTTP(w, r) } ``` -------------------------------- ### Dockerfile for Go Application Source: https://templ.guide/hosting-and-deployment/hosting-using-docker This Dockerfile sets up a multi-stage build for a Go application. It first builds the application and then copies the compiled binary and assets to a minimal release image. It exposes port 8080 and runs the application as a non-root user. ```docker # Build. FROM golang:1.20 AS build-stage WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . /app RUN CGO_ENABLED=0 GOOS=linux go build -o /entrypoint # Deploy. FROM gcr.io/distroless/static-debian11 AS release-stage WORKDIR / COPY --from=build-stage /entrypoint /entrypoint COPY --from=build-stage /app/assets /assets EXPOSE 8080 USER nonroot:nonroot ENTRYPOINT ["/entrypoint"] ``` -------------------------------- ### Handle GET request for contact form Source: https://templ.guide/syntax-and-usage/forms Retrieves an existing contact or initializes a new one for form display. Handles database interactions and populates the model. ```go func (h *Handler) Get(w http.ResponseWriter, r *http.Request) { // Read the ID from the URL. id := r.PathValue("id") model := NewModel() if id != "" { // Get the existing contact from the database and populate the form. contact, ok, err := h.DB.Get(r.Context(), id) if err != nil { h.Log.Error("Failed to get contact", slog.String("id", id), slog.Any("error", err)) http.Error(w, err.Error(), http.StatusInternalServerError) return err } if !ok { http.Redirect(w, r, "/contacts/edit", http.StatusSeeOther) return } model = ModelFromContact(contact) } h.DisplayForm(w, r, model) } ```