# Learning to Go: Part 3 - HTML Templates

*Oh hi! This is a multi-part tutorial series, please make sure you reads the posts in order! You can find the list at the bottom of the page.*

Welcome back fellow Go newbies! In this stage of our tutorial we’ll use a templating library to help us render more stylish HTML, without having to embed a bunch of HTML and CSS directly into our Go code.

As this is not an HTML or CSS tutorial, I’ve written these files for you. First copy the `index.html` file into the same directory as your `main.go` file:

```xml
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>TNG Search</title>
    <link rel="stylesheet" href="/assets/style.css">
</head>

<body>
    <main>
        <header>
          <a class="logo" href="/">TNG Search</a>
          <form action="/search" method="GET">
            <input autofocus class="search-input" value=""
            placeholder="Enter a word" type="search" name="q">
          </form>
        </header>
      </main>
</body>

</html>
```

Next, create a sub-directory called `assets` and put the following `style.css` file in there:

```css
html {
    box-sizing: border-box;
  }
  
  *, *::before, *::after {
    box-sizing: inherit;
    margin: 0;
    padding: 0;
  }
  
  :root {
    --operations: #FFC300;
    --command: #900C3F;
  }
  
  body {
    font-family: sans-serif;
  }
  
  a {
    text-decoration: none;
    color: #333;
  }
  
  a:hover {
    text-decoration: underline;
  }
  
  header {
    width: 100%;
    height: 50px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: space-between;
    background-color: var(--command);
    padding: 5px 10px;
    align-items: center;
  }
  
  .logo {
    font-weight: bold;
    font-size: 25px;
    color: #ffffff;
  }
  
  form {
    height: calc(100% - 10px);
  }
  
  .search-input {
    width: 500px;
    height: 100%;
    border-radius: 4px;
    border-color: transparent;
    background-color: var(--operations);
    color: #ffffff;
    font-size: 16px;
    line-height: 1.4;
    padding-left: 5px;
  }
view raw
```

Now we need to make some updates to our `main.go` file. First we need to add an extra import for the `html/template` library. Since we now have multiple imports, we can group them together inside brackets. Replace your previous `import` statement with this:

```go
import ( "html/template" "net/http" )
```

Then under the imports, add this new line:

```go
var tpl = template.Must(template.ParseFiles("index.html"))
```

Here we’re defining a global variable called `tpl` which uses the `template` library’s `ParseFiles` function to load our `index.html`. It wraps this in the `Must` function which just means that our program will exit if for any reason it can’t load this file.

Inside of our `indexHandler` function, removing line containing the “Hello World” statement and replace it with:

```go
tpl.Execute(w, nil)
```

Here we’re running the `Execute` function on our `tpl` variable, and sending it the `http.ResponseWriter` that’s assigned to the variable `w`. In plain english, this causes the template to be rendered, and the output sent to the HTTP response.

We can try running our updated program now, just like before:

```bash
go run main.go
```

If we load [http://localhost:8080](http://localhost:8080/) in a browser we can see our new index.html file, but it doesn’t look quite right. Our index.html file refers to `/assets/style.css`, but that’s not loading because our program forwards all requests to our `indexHandler`.

Rather than create a new handler for our CSS file, we’ll create a static file server that can serve anything out of our `/assets` directory by default. We do this by adding the following lines inside the `main` function, just after we create the `mux` variable:

```go
fs := http.FileServer(http.Dir("assets"))
mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
```

Here we’re creating a variable called `fs` which is a `FileServer` from the `http` library. Then we add it as a handler to our `mux` variable. So now any requests that start with `/assets` will be dealt with by the static file server, rather than needing their own handler and function.

If your Go program is still running, use Control+C to quit out of it, then run it again once you’ve saved your changes.

You should now see an updated index page, complete with CSS styling!

![TNG search](https://cdn.hashnode.com/res/hashnode/image/upload/v1723551286046/d814944e-e2df-43ad-997a-f305b1f09b15.png align="left")

Nice work! We’re now using multiple libraries, and our app can serve different paths with different functions. Now move on to part 4.

Here’s the complete code of `main.go` if you need to check yours for errors:

```go
package main

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

var tpl = template.Must(template.ParseFiles("index.html"))

func indexHandler(w http.ResponseWriter, r *http.Request) {
    tpl.Execute(w, nil)
}

func main() {
    mux := http.NewServeMux()
    fs := http.FileServer(http.Dir("assets"))
    mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
    mux.HandleFunc("/", indexHandler)
    http.ListenAndServe(":8080", mux)
}
```
