Files
ai-resume/internal/web/templates/view.go
Documenter 286aa12bb0 site: cut the template's own labels out of the pages
Point 7 of the page-wording review. The pages no longer show their data
structure as headings, and they no longer explain their own conventions.

- Level 1 is one screen: claim, status badge, three figures, the technology
  row, and one sentence carrying one link. Measured in headless Chrome at
  1440x900: 1404-1845 px tall before, exactly 900 px (no scroll) after, on
  all six area pages.
- DocPage: no kicker line, no visible level label, no "Evidence for this
  page" heading or instruction note, no "Drill-downs" list, no
  "Status <word> - sentence" footer. The artefact table starts at level 2,
  under the heading "Artefacts"; the history timeline is level 2 only.
- Landing page: "Start here" link text gone, "How to read this site" panel
  gone, the footer's status-label explainer gone.
- Content, presentation only, no claim softened: the leading H1 that
  duplicated the page title removed from all 41 documents; level 1 bodies
  reduced to the constraint as ordinary prose plus the way in;
  "**Status: ...**" prefixes removed from the artefact stubs; "## Drill-downs"
  and "## Period and confidence" removed from the level 2 pages, with the
  cross-area links moved into the prose.
- The six level 1 claims are now sentences with a subject, and use commas
  instead of middots. Same facts, no new ones.

Not in this commit: the 35 level 2 and 3 claims still use the compact CV
style. That is a voice decision for Sam, not a wording tidy-up.

make validate: 41 documents, 0 violations. go test ./...: pass.

(cherry picked from commit 03009f80fc7815ad7719412e125df9297a6e653f)
2026-10-28 15:55:33 +11:00

198 lines
4.6 KiB
Go

// Package templates holds every templ component and the view models they read.
// Layout never branches on the stage driver: it renders the binding it is given.
//
// The generated *_templ.go files are not committed; `make generate` writes them
// from the repository root before every build. There is deliberately no
// //go:generate directive: templ records the .templ path in its error messages,
// so generating from a package directory and generating from the root produce
// different files. One entry point keeps the output byte-identical.
package templates
import (
stdhtml "html"
"strings"
"github.com/a-h/templ"
"gitea.lab.audasmedia.com.au/sam/ai-resume/internal/content"
"gitea.lab.audasmedia.com.au/sam/ai-resume/internal/search"
"gitea.lab.audasmedia.com.au/sam/ai-resume/internal/stage"
)
// NavItem is one left-nav entry.
type NavItem struct {
Title string
Href string
Gutter string
Current bool
}
// Crumb is one breadcrumb.
type Crumb struct {
Label string
Href string
}
// LayoutView is everything the chrome needs.
type LayoutView struct {
Title string
Description string
Area string
Nav []NavItem
Crumbs []Crumb
Stage stage.Binding
SearchQuery string
Year int
SkipAI bool // true on Mode A pages, which never need a model
}
// StageView wraps the binding so the Stage component has one argument.
type StageView struct {
Binding stage.Binding
// Fragment, when set, is rendered into the panel at build time.
Fragment *stage.Fragment
}
// MetricView is one approved chip.
type MetricView struct {
Label string
Value string
}
// LinkView is a drill-down link. HXGet makes it a stage trigger; Href keeps it
// a working link when JavaScript is off.
type LinkView struct {
Label string
Href string
HXGet string
Kind string
Note string
Confidence string
}
// EvidenceRow is one row of an EvidenceTable.
type EvidenceRow struct {
Label string
Href string
HXGet string
Kind string
Confidence string
}
// EvidenceGroup groups rows by area on the evidence index.
type EvidenceGroup struct {
AreaTitle string
Href string
Rows []EvidenceRow
}
// TimelineItem is one row of a timeline.
type TimelineItem struct {
Period string
Title string
Href string
Confidence string
Claim string
}
// PillarCardView is one of the six landing cards.
type PillarCardView struct {
Area content.Area
Title string
Claim string
Href string
Metrics []MetricView
Tech []string
Confidence string
Level int
Pages int
}
// Layout of each page kind.
type (
// HomeView is the landing page.
HomeView struct {
Layout LayoutView
Positioning string
Support string
Location string
Cards []PillarCardView
Artifacts int
Pages int
Areas int
}
// DocView is an L1, L2 or L3 content page.
DocView struct {
Layout LayoutView
Doc *content.Document
Role string
Body templ.Component
Metrics []MetricView
Tech []string
Evidence []LinkView
Backlinks []LinkView
SubPages []LinkView
Timeline []TimelineItem
}
// EvidenceView is the index of every artefact.
EvidenceView struct {
Layout LayoutView
Groups []EvidenceGroup
Total int
}
// SearchView is the keyword search page.
SearchView struct {
Layout LayoutView
Query string
Results []search.Result
Total int
Indexed int
Failed bool
}
// StreamView is the SSE-driven stage demonstration page.
StreamView struct {
Layout LayoutView
Frames int
Fragment []LinkView
}
// NotFoundView is the 404 page.
NotFoundView struct {
Layout LayoutView
}
)
// MarkdownBody wraps pre-rendered Markdown HTML.
func MarkdownBody(html string) templ.Component { return templ.Raw(html) }
// SafeSnippet escapes a search snippet but keeps the <mark> tags the index
// inserted. Content is in-repo and trusted; escaping is defence in depth.
func SafeSnippet(s string) templ.Component {
s = stdhtml.EscapeString(s)
s = strings.ReplaceAll(s, "&lt;mark&gt;", "<mark>")
s = strings.ReplaceAll(s, "&lt;/mark&gt;", "</mark>")
return templ.Raw(s)
}
// ConfidenceClass maps a confidence value onto a CSS class. The value itself is
// always displayed — never softened.
func ConfidenceClass(c string) string {
switch c {
case content.ConfidenceDelivered:
return "conf conf-delivered"
case content.ConfidenceRunning:
return "conf conf-running"
case content.ConfidenceInProgress:
return "conf conf-in-progress"
case content.ConfidenceAbandoned:
return "conf conf-abandoned"
case content.ConfidenceHistoric:
return "conf conf-historic"
}
return "conf"
}