3. A layout
A real page wants <html>/<head>/ <body> and a nav — the wrong thing to repeat per page. Give the shell its own component that takes children, pages/layout.templ:
package pages
// Layout is the shell every page wraps: html/head/body, the nav, and
// { children... } where the page's own content goes.
templ Layout(title string, path string, prefix string) {
<!DOCTYPE html>
<html lang={ lang(prefix) }>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>{ title }</title>
</head>
<body>
<nav>
<a href={ prefix + "/" }>My Site</a>
<a href={ prefix + "/projects/" }>Projects</a>
<a href={ prefix + "/about/" }>About</a>
</nav>
<main>
{ children... }
</main>
</body>
</html>
}
// lang maps the locale prefix to an html lang attribute.
func lang(prefix string) string {
if prefix == "" {
return "en"
}
return prefix[1:] // "/de" -> "de"
} is templ's children mechanism: a caller wraps the component instead of passing content in as a parameter. Every link goes through prefix, so the same layout works in every locale. The home page now wraps it:
package pages
templ Home(title string, path string, prefix string) {
@Layout(title, path, prefix) {
<h1>My Site</h1>
<p>A portfolio built with astwerk.</p>
}
}Try it. Add a <footer> to the layout and rebuild.
What you should see
Every page gains the footer — build/index.html changes and no new files appear. The layout is the shell, shared by all pages.
How does a component receive the page's own content?
A component declares { children... } and callers wrap it — the page's markup is passed as children.
Why does the layout build every link through prefix?
A locale subtree renders the same components with prefix set to /de, so links through prefix become /de/… automatically and the layout needs no per-language copy.