| name | description |
|---|---|
templ |
Compile-time HTML templating for Go using templ. Enforces type-safe components, layout composition, fragment rendering, and production-ready best practices for HTTP, SSE, and component-driven UI architectures. |
SKILL.md — templ (https://templ.guide)
This SKILL document defines how Claude CLI and OpenCode CLI should reason about, generate, refactor, and review code that uses templ (https://templ.guide) for Go-based HTML templating.
The purpose is to ensure consistent, idiomatic, production-ready usage of templ across projects.
- templ is a compile-time HTML templating language for Go.
- templ files (
*.templ) compile into Go code. - Components are first-class Go functions.
- Rendering is type-safe.
- No runtime template parsing.
CLI tools MUST:
- Prefer compile-time safety over reflection-based approaches.
- Avoid html/template unless explicitly required.
- Treat templ components as pure view-layer functions.
Recommended structure:
/internal/ui/
layout.templ
page_home.templ
components/
button.templ
card.templ
table.templ
Rules:
- One logical component per file.
- Name components in PascalCase.
- Keep business logic OUT of templ files.
- Use Go services for logic, templ only for rendering.
package ui
templ Hello(name string) {
<div>
Hello { name }
</div>
}Generated usage:
ui.Hello("World").Render(ctx, w)Rules for CLI tools:
- Always generate strongly typed parameters.
- Never pass
interface{}. - Avoid maps for props unless dynamic content is unavoidable.
templ Layout(title string, body templ.Component) {
<html>
<head>
<title>{ title }</title>
</head>
<body>
{ body }
</body>
</html>
}templ HomePage() {
@Layout("Home",
templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
return templ.Render(ctx, w,
<div>Welcome</div>,
)
}),
)
}CLI MUST:
- Prefer nested components over inline ComponentFunc where possible.
- Encourage small reusable blocks.
- Avoid deeply nested inline lambdas.
templ UserBadge(user *User) {
if user != nil {
<span>{ user.Name }</span>
} else {
<span>Guest</span>
}
}Best practices:
- Keep conditionals simple.
- Avoid multi-branch complex logic.
- Precompute complex logic in Go before passing to templ.
templ UserList(users []User) {
<ul>
for _, u := range users {
<li>{ u.Name }</li>
}
</ul>
}Rules:
- Use slices, not channels.
- Do not perform DB access inside loops.
- Ensure data is fully prepared before rendering.
templ automatically escapes values.
Correct:
<a href={ url }>Link</a>Unsafe raw HTML (only when trusted):
{ templ.Raw(htmlContent) }CLI MUST:
- Default to escaped rendering.
- Only use
templ.Rawwhen explicitly justified.
templ LoginForm(action string) {
<form method="POST" action={ action }>
<input type="text" name="email" />
<input type="password" name="password" />
<button type="submit">Login</button>
</form>
}Rules:
- Always pass action as string.
- Do not hardcode URLs.
- Prefer CSRF token component injection.
templ supports rendering fragments.
component := ui.UserList(users)
component.Render(ctx, w)Best practice:
- Build small fragment components.
- Do not re-render full layouts for partial updates.
Rendering returns error:
if err := ui.HomePage().Render(ctx, w); err != nil {
http.Error(w, err.Error(), 500)
}CLI MUST:
- Always check Render error.
- Never ignore returned error.
Example test:
buf := &bytes.Buffer{}
err := ui.Hello("Test").Render(context.Background(), buf)
require.NoError(t, err)
require.Contains(t, buf.String(), "Test")Rules:
- Test rendered HTML via string assertions.
- Avoid brittle full-document comparisons.
- No reflection.
- No runtime parsing.
- Avoid large in-memory HTML assembly when streaming is possible.
- Prefer streaming to io.Writer.
CLI MUST:
- Generate streaming-friendly handlers.
- Avoid building huge strings.
Recommended handler:
func HomeHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if err := ui.HomePage().Render(ctx, w); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}Rules:
- Always use request context.
- Do not create background contexts.
- Do not write to ResponseWriter after error.
CLI tools must avoid generating:
- Business logic inside templ blocks.
- DB queries inside templ.
- Global mutable state.
- Giant monolithic components.
- Inline CSS/JS duplication.
When asked to generate templ code:
- Use typed parameters.
- Separate layout from content.
- Provide minimal but production-ready example.
- Include handler example when relevant.
- Never mix html/template with templ unless required.
- Prefer composition over condition explosion.
- Keep components small and reusable.
When converting from html/template:
- Replace template parsing with compiled templ.
- Convert template blocks into components.
- Replace template data maps with typed structs.
- Escaping by default.
- Explicit raw rendering only.
- No inline JS injection.
- Validate inputs before rendering.
- Component: PascalCase
- File: snake_case.templ
- Package: ui or view
CLI tools should:
- Assume latest stable templ version.
- Avoid deprecated APIs.
- Generate go:generate hint when appropriate:
//go:generate templ generateEND OF SKILL