{{/* Health & Trends Page Content */}} {{/* Support both direct context and dict with context/repoKey */}} {{ $context := . }} {{ $repoKey := "" }} {{ if reflect.IsMap . }} {{ with .context }}{{ $context = . }}{{ end }} {{ with .repoKey }}{{ $repoKey = . }}{{ end }} {{ end }} {{ $data := partial "load-metrics.html" (dict "context" $context "repoKey" $repoKey) }} {{ $m := $data.metrics }} {{ $snapshots := $data.snapshots }} {{ $versions := $data.versions }} {{ if not $m }}
No data available. Run the aggregation script.
{{ else }} {{ if $m.hotspots }}

Code Hotspots

Files most frequently modified in merged PRs (last 90 days)

{{ if $m.hotspots.by_file }} {{/* Build GitHub base URL */}} {{ $ghFileBase := printf "https://github.com/%s/blob/main" $repoKey }}

Top Files

{{/* Find max PR count for scaling */}} {{ $maxPR := 0 }} {{ range $m.hotspots.by_file }} {{ if gt .pr_count $maxPR }}{{ $maxPR = .pr_count }}{{ end }} {{ end }}
{{ range first 10 $m.hotspots.by_file }} {{ $ratio := div (float .pr_count) (float $maxPR) }} {{ $filled := int (math.Round (mul $ratio 10)) }} {{ if lt $filled 1 }}{{ $filled = 1 }}{{ end }} {{ $level := int (math.Round (mul $ratio 4)) }} {{ if lt $level 1 }}{{ $level = 1 }}{{ end }} {{ if gt $level 4 }}{{ $level = 4 }}{{ end }} {{ $fileLink := printf "%s/%s" $ghFileBase .path }}
{{ .path }}
{{ range seq 10 }} {{ if le . $filled }} {{ else }} {{ end }} {{ end }}
{{ .pr_count }}PRs {{ lang.FormatNumber 0 .total_changes }}Δ
{{ end }}
{{ end }} {{ if $m.hotspots.by_directory }} {{/* Build GitHub base URL for directories */}} {{ $ghDirBase := printf "https://github.com/%s/tree/main" $repoKey }}

Top Directories

{{/* Find max PR count for scaling */}} {{ $maxDirPR := 0 }} {{ range $m.hotspots.by_directory }} {{ if gt .pr_count $maxDirPR }}{{ $maxDirPR = .pr_count }}{{ end }} {{ end }}
{{ range first 10 $m.hotspots.by_directory }} {{ $ratio := div (float .pr_count) (float $maxDirPR) }} {{ $filled := int (math.Round (mul $ratio 10)) }} {{ if lt $filled 1 }}{{ $filled = 1 }}{{ end }} {{ $level := int (math.Round (mul $ratio 4)) }} {{ if lt $level 1 }}{{ $level = 1 }}{{ end }} {{ if gt $level 4 }}{{ $level = 4 }}{{ end }} {{ $dirLink := printf "%s/%s" $ghDirBase .path }}
{{ .path }}
{{ range seq 10 }} {{ if le . $filled }} {{ else }} {{ end }} {{ end }}
{{ .pr_count }}PRs {{ .file_count }}files
{{ end }}
{{ end }}
{{ end }}

Historical Trends

{{ if $snapshots }} {{/* Collect snapshots into a sortable slice */}} {{ $entries := slice }} {{ range $filename, $data := $snapshots }} {{ $entries = $entries | append (dict "date" $data.date "issues_open" $data.issues.open "pulls_open" $data.pulls.open "stars" $data.repository.stars) }} {{ end }} {{/* Sort by date ascending */}} {{ $sorted := sort $entries "date" "asc" }} {{/* Extract sorted arrays */}} {{ $dates := slice }} {{ $issuesOpen := slice }} {{ $pullsOpen := slice }} {{ $stars := slice }} {{ range $sorted }} {{ $dates = $dates | append .date }} {{ $issuesOpen = $issuesOpen | append .issues_open }} {{ $pullsOpen = $pullsOpen | append .pulls_open }} {{ $stars = $stars | append .stars }} {{ end }} {{ if gt (len $dates) 1 }}

Open Issues (UTC)

Open PRs (UTC)

Stars (UTC)

{{ else }}
Not enough historical data yet. Trends will appear after multiple data syncs.
{{ end }} {{ else }}
No snapshot data available yet. Trends will appear after daily snapshots accumulate.
{{ end }}
{{ if $versions }} {{ $unit := $versions.unit | default "daily" }} {{ $unitLabel := cond (eq $unit "last_week") "7-day rolling" (cond (eq $unit "cumulative") "Cumulative" "Daily") }} {{ $unitBlurb := cond (eq $unit "last_week") "7-day rolling downloads per version (npm /versions API)" (cond (eq $unit "cumulative") "All-time cumulative downloads per version (NuGet search API)" "Per-version daily downloads via BigQuery") }}

Downloads by Version

{{ $unitBlurb }} {{ with $versions.lastUpdated }}· updated {{ dateFormat "Jan 2 15:04 UTC" (time .) }}{{ end }}

{{/* Rank versions by total and pick top 10 */}} {{ $ranked := slice }} {{ $grandTotal := 0 }} {{ range $v, $n := $versions.totals }} {{ $ranked = $ranked | append (dict "version" $v "count" $n) }} {{ $grandTotal = add $grandTotal $n }} {{ end }} {{ $ranked = sort $ranked "count" "desc" }} {{ $top := first 10 $ranked }} {{ $topVersions := slice }} {{ range $top }}{{ $topVersions = $topVersions | append .version }}{{ end }}
{{ range $top }} {{ $pct := 0.0 }} {{ if gt $grandTotal 0 }}{{ $pct = mul (div (float .count) (float $grandTotal)) 100 }}{{ end }} {{ end }}
Version Downloads Share
{{ .version }} {{ lang.FormatNumber 0 .count }} {{ printf "%.1f%%" $pct }}

{{ $unitLabel }} by Version (top 10, UTC) Top 10 versions by total downloads are plotted individually. The other series sums all remaining versions together so the stacked total equals overall {{ lower $unitLabel }} downloads.

{{/* Build sorted date axis and one data series per top-N version plus "other" */}} {{ $vDates := slice }} {{ range $d, $_ := $versions.daily }}{{ $vDates = $vDates | append $d }}{{ end }} {{ $vDates = sort $vDates }} {{ $palette := slice "#2563eb" "#16a34a" "#dc2626" "#ca8a04" "#9333ea" "#0891b2" "#db2777" "#65a30d" "#ea580c" "#475569" }} {{ $datasets := slice }} {{ range $i, $v := $topVersions }} {{ $series := slice }} {{ range $d := $vDates }} {{ $dayMap := index $versions.daily $d }} {{ $series = $series | append (or (index $dayMap $v) 0) }} {{ end }} {{ $datasets = $datasets | append (dict "label" $v "data" $series "borderColor" (index $palette $i) "backgroundColor" (index $palette $i) "fill" true "tension" 0.2 "borderWidth" 1 "pointRadius" 0) }} {{ end }} {{/* "other" bucket: per-day sum of versions outside the top 10 */}} {{ $otherSeries := slice }} {{ range $d := $vDates }} {{ $dayMap := index $versions.daily $d }} {{ $dayOther := 0 }} {{ range $v, $n := $dayMap }} {{ if not (in $topVersions $v) }}{{ $dayOther = add $dayOther $n }}{{ end }} {{ end }} {{ $otherSeries = $otherSeries | append $dayOther }} {{ end }} {{ $datasets = $datasets | append (dict "label" "other" "data" $otherSeries "borderColor" "#94a3b8" "backgroundColor" "#94a3b8" "fill" true "tension" 0.2 "borderWidth" 1 "pointRadius" 0) }}
{{ end }} {{ end }}