Lightning uses Go’s standard text/template package for server-side rendering. Load templates once at startup with app.LoadHTMLGlob(), then render them from any handler with ctx.HTML().
Loading Templates
Call app.LoadHTMLGlob(pattern) before starting the server. The pattern follows the same glob syntax as filepath.Glob.
app.LoadHTMLGlob("templates/*.html")
LoadHTMLGlob panics if the pattern matches no files or if any template fails to parse. Always verify your template paths before deploying.
Custom Template Functions
Register custom functions with app.SetFuncMap() before calling app.LoadHTMLGlob(). The function map is applied when templates are parsed.
import (
"fmt"
"text/template"
"time"
"github.com/go-labx/lightning"
)
func formatDate(t time.Time) string {
year, month, day := t.Date()
return fmt.Sprintf("%d-%02d-%02d", year, month, day)
}
func main() {
app := lightning.DefaultApp()
// Register custom functions first
app.SetFuncMap(template.FuncMap{
"formatDate": formatDate,
})
// Then load templates (so they can use the functions)
app.LoadHTMLGlob("templates/*.tmpl")
}
Rendering a Template
Call ctx.HTML(code, name, data) from a handler. name is the template file name as registered by the glob, and data is any value passed as the template’s dot (.).
app.Get("/", func(ctx *lightning.Context) {
ctx.HTML(lightning.StatusOK, "index.tmpl", lightning.Map{
"title": "My App",
"description": "Built with Lightning",
"now": time.Now(),
})
})
If template execution fails, Lightning responds with 500 and the error message as plain text.
Complete Example
Create the template file
templates/index.tmpl:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.title}}</title>
<link rel="stylesheet" href="/static/css/style.css" />
</head>
<body>
<h1>{{.title}}</h1>
<p>{{.description}}</p>
<p>Today is {{.now | formatDate}}</p>
</body>
</html>
Write the server code
main.go:package main
import (
"fmt"
"text/template"
"time"
"github.com/go-labx/lightning"
)
func formatDate(t time.Time) string {
year, month, day := t.Date()
return fmt.Sprintf("%d-%02d-%02d", year, month, day)
}
func main() {
app := lightning.DefaultApp()
// Serve CSS/JS from ./public at /static
app.Static("./public", "/static")
// Register custom template functions before loading
app.SetFuncMap(template.FuncMap{
"formatDate": formatDate,
})
// Load all templates from the templates directory
app.LoadHTMLGlob("templates/*.tmpl")
app.Get("/", func(ctx *lightning.Context) {
ctx.HTML(lightning.StatusOK, "index.tmpl", lightning.Map{
"title": "Lightning",
"description": "A fast web framework for Go.",
"now": time.Now(),
})
})
app.Run(":8080")
}
Run and visit the page
go run main.go
# open http://localhost:8080
Use lightning.Map (a map[string]any alias) to pass ad-hoc template data without defining a dedicated struct.