TMPLX is a Go template engine that extends the standard html/template
package to provide Django/Jinja2-style template inheritance, blocks, and includes. It maintains the security and familiar syntax of Go templates while adding powerful features for building complex template hierarchies.
- Template Inheritance: Extend base templates using
{{extend "base.html"}}
- Block Definitions: Define and override template blocks
- Template Includes: Include other templates with
{{include "partial.html"}}
- Custom Functions: Full support for Go's template.FuncMap
- Filesystem Abstraction: Works with regular files or embed.FS
- Zero External Dependencies: Built on top of Go's standard library
- Multi source support: Supports multiple sources for templates
go get github.com/kalyan02/tmplx
- Create your templates:
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{block "title" .}}Default Title{{end}}</title>
</head>
<body>
{{block "content" .}}
<p>Default content</p>
{{end}}
</body>
</html>
<!-- templates/pages/home.html -->
{{extend "base.html"}}
{{block "title" .}}Home Page{{end}}
{{block "content" .}}
{{include "partials/header.html"}}
<h1>Welcome, {{.Name}}!</h1>
{{end}}
- Use the template engine:
package main
import (
"log"
"strings"
"github.com/kalyan02/tmplx"
)
func main() {
// Create a new engine
engine := tmplx.New(tmplx.Options{
Dir: "templates",
FuncMap: template.FuncMap{
"upper": strings.ToUpper,
},
})
// Load all templates
if err := engine.Load(); err != nil {
log.Fatal(err)
}
// Render a template
data := map[string]interface{}{
"Name": "John",
}
result, err := engine.Render("pages/home.html", data)
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
Extend base templates using the extend
directive:
{{extend "layouts/base.html"}}
- Must be the first directive in the template
- Child templates can override blocks defined in parent templates
- Supports multiple levels of inheritance
Define reusable blocks that can be overridden by child templates:
{{block "sidebar" .}}
<!-- default sidebar content -->
{{end}}
Override blocks in child templates:
{{block "sidebar" .}}
<!-- custom sidebar content -->
{{end}}
Include other templates:
{{include "partials/header.html"}}
- Included templates have access to the current context
- Can be used anywhere in templates
- Supports nested includes
TMPLX supports multiple sources for templates:
Note: templates are processed in sequential order and can only inherit or include from same or previous sources. i.e you cannot include a template from a source that is loaded after the current source.
// Create engine with embed.FS
engine := New(Options{
Sources: []Source{
// layouts/base.html in root of embed fs fsys1
{FS: fsys1},
// pages/home.html in root of embed fs fsys2
{FS: fsys2},
// home2.html in "pages" folder in fsys3 embed fs
{FS: fsys3, Dir: "pages/"},
// partials/header.html from "templates" folder on disk
{Dir: "templates"},
}
})
type Options struct {
Dir string // Root directory for templates
FS fs.FS // Optional filesystem (eg. embed.FS)
FuncMap template.FuncMap // Custom template functions
Logger Logger // Optional logger interface
}
// Create new engine
engine := tmplx.New(Options{
Dir: "templates",
})
// Load all templates
err := engine.Load()
// Add custom functions
err := engine.AddFuncs(template.FuncMap{
"myFunc": func() string { return "hello" },
})
// Render a template
result, err := engine.Render("pages/home.html", data)
// Get parsed template
tmpl, err := engine.GetTemplate("pages/home.html")
TMPLX works seamlessly with Go 1.16+ embed.FS:
//go:embed templates/*
var templateFS embed.FS
engine := tmplx.New(tmplx.Options{
FS: templateFS,
})
-
Template Organization:
- Keep base templates in a
layouts/
directory - Put reusable components in
partials/
- Organize page templates in
pages/
- Use subdirectories for complex projects
- Keep base templates in a
-
Performance:
- Call
Load()
once at startup - Templates are cached after loading
- Use
embed.FS
for production deployments
- Call
-
Error Handling:
- Always check errors from
Load()
andRender()
- Use the logger interface for debugging template issues
- Always check errors from
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details
Inspired by Django and Jinja2 template inheritance systems while maintaining Go's template syntax and security model.