Templates
Render HTML templates with html/template.
Templates
Load a directory of .html templates at startup and render them with
c.HTML.
app := ply.New()
app.Templates("./templates")
app.Get("/", func(c *core.Context) {
c.HTML(200, "index.html", map[string]any{
"Title": "Ply",
"Items": []string{"one", "two"},
})
})How loading works
app.Templates(dir) walks the directory recursively. For every .html file it:
- computes the path relative to
dir, - converts the path to forward slashes,
- parses the file as a template with that relative path as its name.
A file at templates/pages/index.html is available as pages/index.html:
c.HTML(200, "pages/index.html", data)Loading happens once. Changes to template files require a restart. A read or
parse error causes Templates to panic, so load it during startup and let the
process fail early.
Template example
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{{ .Title }}</title>
</head>
<body>
<h1>{{ .Title }}</h1>
<ul>
{{ range .Items }}
<li>{{ . }}</li>
{{ end }}
</ul>
</body>
</html>html/template escapes values according to their HTML context. Do not cast
user input to template.HTML unless it has been sanitized.
Layouts
Use named templates to share a layout:
{{ define "layout" }}
<!doctype html>
<html>
<body>{{ template "content" . }}</body>
</html>
{{ end }}{{ define "content" }}
<h1>{{ .Title }}</h1>
{{ end }}Parse order does not matter. The names come from the define blocks.
Errors
c.HTML returns 500 with a plain text message when:
- no templates are loaded,
- the named template does not exist,
- execution fails.
In production, log the full error on the server and return a generic error page to the client.
Notes
- Templates are parsed from disk. They are not embedded in the binary.
- The directory must exist and be readable by the process.
- Do not load templates per request. Parse once during startup.
- Rendering happens inside a normal handler, so
app.Usemiddleware applies.

Ply