1. Overview

In this tutorial, you’ll create a Go web server that uses the html/template package to serve dynamic HTML pages, and leverages Tailwind CSS for styling. By the end, you'll have a clean, maintainable approach for structuring your web application.

2. Project Structure

Here’s a simple, recommended file layout:

            
            my-project/
            ├── go.mod
            ├── main.go
            └── templates/
                ├── base.html
                ├── index.html
                └── (other templates)
            
                  

- go.mod holds your Go module info (dependencies).
- main.go is your entry point, containing func main().
- templates/ keeps your HTML files. You can split them however you like.

3. Initialize Your Go Module

If you’re using modules (recommended for Go 1.13+), navigate to your folder and run:

            
            cd my-project
            go mod init github.com/yourusername/my-project
            
                  

This creates a go.mod file tracking your dependencies.

4. Create Your HTML Templates

Tailwind can be included via a CDN link or by locally building the CSS. For simplicity, we’ll use a CDN. You can place the link in a base layout so all pages inherit it.

4.1 base.html (Layout)

            
            <!-- templates/base.html -->
            <!DOCTYPE html>
            <html lang="en">
            <head>
              <meta charset="UTF-8">
              <title>{{block "title" .}}My Go App{{end}}</title>
              <script href="https://unpkg.com/@tailwindcss/browser@4" rel="stylesheet"> </script>
            </head>
            <body class="bg-gray-900 text-gray-100 font-sans">

              {{/* Navigation or header content goes here, if desired */}}

              {{/* Where child templates inject their own content */}}
              {{block "content" .}}{{end}}

              {{/* A footer could also go here */}}

            </body>
            </html>
            
                  

4.2 index.html (Child Template)

In the index.html file, define the title and content blocks to override what’s in base.html:

            
            <!-- templates/index.html -->
            {{define "title"}}Home Page{{end}}

            {{define "content"}}
            <div class="container mx-auto p-4">
              <h1 class="text-2xl font-bold mb-4">Welcome to My Go + Tailwind Site!</h1>
              <p class="leading-relaxed mb-4">
                This page is styled with Tailwind CSS, served by a simple Go server.
              </p>
              <a href="/about" class="bg-teal-500 hover:bg-teal-400 text-white px-4 py-2 rounded">
                About
              </a>
            </div>
            {{end}}
            
                  

Note how we use Tailwind classes (e.g., text-2xl, bg-teal-500) in HTML for styling.

5. Write the Go Server (main.go)

Below is a minimal example that parses the templates and serves index.html and a hypothetical about.html:

            
            package main

            import (
                "fmt"
                "html/template"
                "log"
                "net/http"
            )

            var tmpl *template.Template

            func main() {
                // Parse all .html files in the templates folder
                var err error
                tmpl, err = template.ParseGlob("templates/*.html")
                if err != nil {
                    log.Fatalf("Error parsing templates: %v", err)
                }

                // Register routes
                http.HandleFunc("/", indexHandler)
                http.HandleFunc("/about", aboutHandler)

                // Start server
                fmt.Println("Server running on http://localhost:8080")
                if err := http.ListenAndServe(":8080", nil); err != nil {
                    log.Fatalf("Server failed: %v", err)
                }
            }

            func indexHandler(w http.ResponseWriter, r *http.Request) {
                // Render index.html (which uses base.html)
                if err := tmpl.ExecuteTemplate(w, "index.html", nil); err != nil {
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                }
            }

            func aboutHandler(w http.ResponseWriter, r *http.Request) {
                // Suppose you also have about.html
                if err := tmpl.ExecuteTemplate(w, "about.html", nil); err != nil {
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                }
            }
            
                  

This setup ensures all HTML files in templates/ are loaded at startup, letting you reuse base.html for consistent styling.

6. Tailwind: CDN vs. Local Build

The above example uses a CDN link for Tailwind – the simplest approach. For advanced customization (e.g., tailwind.config.js), you can build your own Tailwind CSS and reference a local file. That process typically involves:

For most small apps, the **CDN** method is perfectly fine.

7. Testing Your Setup

1. Run go run main.go in your project root.
2. Visit http://localhost:8080 in your browser.
3. You should see a page with the Tailwind styling (dark background, large headings, etc.).
4. Navigate to /about if you have an about.html page set up similarly.

8. FAQ

Q: Can I pass data to the templates?
A: Absolutely. Create a struct (e.g., type PageData struct), fill it with data, and pass it as the final argument in ExecuteTemplate.

Q: Where do I put images or static files?
A: You can serve them from a /static directory. For example:

            
            http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
            
                  

Then reference your static content via /static/... paths in your templates.

9. Summary

By following these steps, you’ve created a Go web server that uses HTML templates and Tailwind CSS. This setup keeps your code clean, your front-end styling powerful, and your build process straightforward. From here, you can:

With Tailwind’s utility classes, you can rapidly build responsive, modern UIs without manually writing much CSS. Enjoy your new Go + Tailwind stack!