Views
Template Data And Helpers
Pass controller data to templates and use registered helper functions.
Set template data
Controllers pass data to templates with Set:
func (c *PostsController) Show(
_ http.ResponseWriter,
r *http.Request,
) error {
post, ok := c.posts.Get(r.PathValue("post_id"))
if !ok {
return lazycontroller.Error(http.StatusNotFound, fmt.Errorf("post not found"))
}
c.Set("title", post.Title)
c.Set("post", post)
return nil
}
The view reads those values by name:
<h1>{{.title}}</h1>
<article>{{.post.Body}}</article>
Use built-in helpers
lazyapp registers route, asset, form, and Turbo helpers:
<a href="{{path_for "posts"}}">Posts</a>
{{stylesheet "/styles.css"}}
{{importmap "/assets/importmap.json"}}
Helpers return ordinary strings or trusted fragments, depending on what the helper renders.
Register app helpers
Application helpers are passed to lazyapp.New:
func RegisterHelpers() map[string]any {
return map[string]any{
"read_time": ReadTime,
}
}
Wire them during startup:
func App() *lazyapp.App {
return lazyapp.New(lazyapp.Config{
Name: "sample_app",
Drawer: Draw,
Public: app.Public,
Views: app.Views,
Dependencies: Dependencies,
Helpers: lazyapp.Helpers{helpers.RegisterHelpers()},
})
}
Then call the helper from a template:
<p>{{read_time .post.Body}} min read</p>
Add SEO metadata
lazyapp installs SEO helpers automatically. Configure application defaults
with a context-aware SEO function, normally in init/seo.go, and wire it
through lazyapp.Config.SEO:
func App() *lazyapp.App {
return lazyapp.New(lazyapp.Config{
Name: "sample_app",
Drawer: Draw,
Public: app.Public,
Views: app.Views,
Dependencies: Dependencies,
SEO: SEO,
})
}
func SEO(ctx context.Context) []lazyseo.Option {
return []lazyseo.Option{
lazyseo.SiteName("GoLazy"),
lazyseo.Description("A GoLazy application."),
lazyseo.Language("en"),
lazyseo.TwitterCardType("summary"),
}
}
lazyapp.New calls Dependencies before SEO, so SEO defaults can read
dependency-backed values from the app context.
Call {{seo_lang}} from the opening <html> tag and {{seo}} from the layout
<head>:
<html lang="{{seo_lang}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{seo}}
</head>
</html>
Read SEO And Sitemaps for controller metadata,
structured data, robots.txt, and sitemap generation.
Use view variants
View variants are server-side template variants for the same route and format.
They use the Rails-style +variant segment after the format:
app/views/posts/show.svg.tpl
app/views/posts/show.svg+square.tpl
Rendering show as svg with variant square tries the square template first
and falls back to show.svg.tpl. Use this for generated image shapes such as a
default social image and a square social image. These are not SEO alternates;
SEO alternates are public URLs declared with c.Alternate(...).
Controllers can render that SVG content as a string:
svg, err := c.RenderSVGString("show", "square")
if err != nil {
return err
}
That gives image-generation code a normal Go string to write, rasterize, or
register as an asset before setting the public URL with c.SEOImage(...).