How to use partials in html/template

What’s the preferred approach to passing data to a template and partials inside a page?

I have a block “thread” with replies, whos appearance depends on the page it is rendered on:

{{define "thread"}}
    {{$isThreadPage := .IsThreadPage}}
    {{$thread := .Thread}}

    {{if $threadPage}}
        {{$thread.Subject}}
    {{else}}
        <a href="/threads/{{$thread.ID}}">{{$thread.Subject}}</a>
    {{end}}
    {{range $thread.Replies}}
        {{template "reply" .}}
    {{end}}
{{end}}

I use it in my thread page like this, where dict is a function I defined to create a map with key/value pairs:

{{define "title"}}
    {{with .Thread}}
        {{.Subject}}
    {{end}}
{{end}}
    
{{define "content"}}
    {{with .Thread}}
        {{template "thread" (dict "Thread" . "ThreadPage" true)}} 
    {{end}}
{{end}}

I think for a simple website this approach would work, but I want to learn and hear if there is anything I can do to improve my workflow with html/template.

Two things first.

You have a bug: you assign $isThreadPage but test $threadPage — that variable doesn’t exist, so the condition is always false and the link always renders.

Second, dict returns map[string]any. A typo in a key name produces no error at all, just silent wrong behavior.

For the architecture question: the root problem is that html/template gives you a single . and you lose parent context on every range. Passing context down manually works but scales poorly as nesting deepens.

The cleaner approach is a recursive node struct that carries its own render context — each node holds its data, its children, and whatever flags it needs. The template just recurses and never needs to ask “where am I being rendered?”.

I built something along these lines for a forum system here: https://github.com/hazyhaar/horum — might be worth a look if you’re going deeper with recursive thread/reply structures.

One question though: are you learning html/template specifically, or are you building something you intend to ship?

If it’s the latter, templ is worth considering. Components are typed Go functions with explicit parameters — your ThreadView struct becomes a function signature, the compiler checks everything, and context propagation through nested components is trivial. The entire class of problem you’re hitting doesn’t exist in templ.