8.5 KiB
Report Templates
This guide is for maintainers editing Weatherreporter's embedded Markdown templates. Templates format already validated report inputs; they do not select sources, derive weather facts, or validate generated prose. For those details, see Generated Text internals and Report Template internals.
Template Assets
Only the generated-text reports use repository-native Markdown templates. Each report has one matching template ID, generated-text schema ID, and prompt source:
| Report | Template | Schema | Prompt ID and source |
|---|---|---|---|
| Daily | templates/daily.md.tmpl (daily) |
daily |
weather.daily_generated_text; internal/promptassets/assets/prompts/daily/ |
| Today | templates/today.md.tmpl (today) |
today |
weather.today_generated_text; internal/promptassets/assets/prompts/today/ |
| Tomorrow | templates/tomorrow.md.tmpl (tomorrow) |
tomorrow |
weather.tomorrow_generated_text; internal/promptassets/assets/prompts/tomorrow/ |
| Hourly | templates/hourly.md.tmpl (hourly) |
hourly |
weather.hourly_generated_text; internal/promptassets/assets/prompts/hourly/ |
The matching schemas and Promptkit definitions are embedded by
internal/promptassets. The generated-text catalog pairs each schema ID with
its template ID; keep the matching prompt definition aligned with that pair.
Shared partials are under internal/reporttemplate/templates/partials/:
| Partial | Used by |
|---|---|
alert_digest.md.tmpl |
Daily, Today, Tomorrow, and Hourly |
precipitation_timing.md.tmpl |
Daily, Today, Tomorrow, and Hourly |
daypart_forecast.md.tmpl |
Daily and Tomorrow |
today_daypart_forecast.md.tmpl |
Today |
All shared partials are parsed whenever any top-level template is rendered. A syntax error in a partial can therefore prevent every generated-text report from rendering.
Editing Rules
- Use Go
text/templatesyntax and keep changes to Markdown structure, ordering, and display conditions. - Templates use
missingkey=error; reference only documented fields and guard optional module pointers withwithorif. - Prefer
.Modulesfor deterministic display values. Do not add weather calculations, source selection, or prompt-input shaping to a template. - Keep generated prose in
.GeneratedText; do not restate deterministic facts in generated prose merely to compensate for a template change. - When changing the generated-prose contract, update the matching prompt, schema, validator, render context, and template together. The validation and catalog rules are owned by Generated Text internals.
- Use
.Modules.Daypartsfor ordered daypart output. Do not range over.Modules.DerivedDaypartSummaries, which is a map.
Minimal optional-value pattern:
{{ with .Modules.CurrentConditions }}
Currently, it is {{ with .TemperatureF }}{{ . }}°F{{ end }}.
{{ else }}
Current conditions are unavailable.
{{ end }}
Minimal list pattern:
{{ range .GeneratedText.ForecastDiscussion }}
{{ . }}
{{ end }}
Registered Functions
Templates have these helpers in addition to Go template built-ins:
| Function | Accepts | Returns true when |
|---|---|---|
hasRelevantAlerts |
an alert-digest value or pointer | its Relevant slice is nonempty |
hasEnhancedOrHigherSPCRisk |
an SPC outlook value or pointer | its RiskDigest contains an Enhanced, Moderate, or High Risk entry |
isEnhancedOrHigherSPCRisk |
one SPC risk-digest entry | its LabelText, or fallback RiskLabel, is Enhanced, Moderate, or High Risk |
For example, the alert partial uses the first two functions to decide whether to render the section:
{{ if hasRelevantAlerts .Modules.AlertDigest }}
## Alert Digest
{{ end }}
Render Context
Every rendered template receives one typed context with these five top-level fields:
| Field | Purpose |
|---|---|
.Report |
Display labels and canonical report timing metadata. |
.GeneratedText |
Validated prose supplied by Promptkit. |
.Modules |
Deterministic, typed values prepared for Markdown rendering. |
.Collected |
Normalized upstream facts for advanced use. |
.Derived |
Shared calculated facts for advanced use. |
.Collected and .Derived are available for an exceptional display need, but
they are lower-level contracts. Keep reusable weather derivation in Go and use
the module surface for normal template work.
Report Metadata
All contexts provide .Report.Title, .Report.GeneratedAt,
.Report.GeneratedAtLabel, .Report.ValidPeriod, and .Report.Timezone.
Hourly additionally provides .Report.LocationName and
.Report.ValidPeriodLabel.
Daily, Today, and Tomorrow additionally provide .Report.ForecastDate,
.Report.ForecastDateLabel, and .Report.ForecastDayName. Their valid-period
field remains canonical timing data; use the supplied display labels instead
of formatting timestamps in a template.
Validated GeneratedText Prose
GeneratedText is prose returned by Promptkit and validated before rendering. It is not a source for deterministic weather facts.
| Field | Hourly type | Daily, Today, and Tomorrow type | Notes |
|---|---|---|---|
.GeneratedText.Summary |
string |
string |
Required. |
.GeneratedText.ForecastDiscussion |
string |
[]string |
Required; range over the day-style paragraph slice. |
.GeneratedText.PrecipitationTiming |
string |
string |
Required field; an empty string represents no supported prose. The precipitation partial uses nonempty prose only when deterministic windows exist. |
The JSON schema rejects unknown properties and defines the required fields, but the schema body and validation behavior are documented in Generated Text internals.
Deterministic Module Values
Module values are deterministic outputs built from collected and derived facts. Module pointers can be nil when their source or policy permits omission.
| Module field | Available in |
|---|---|
.Modules.Metadata, .Modules.CurrentConditions, .Modules.HourlyForecast, .Modules.PrecipTiming, .Modules.AlertDigest, .Modules.SPCConvectiveOutlooks, .Modules.AreaForecastDiscussion, .Modules.SPCConvectiveDiscussion, .Modules.WeatherStory |
All four contexts |
.Modules.DerivedDailySummary, .Modules.DerivedDaypartSummaries, .Modules.Dayparts |
Daily, Today, Tomorrow |
.Modules.OutdoorWindows, .Modules.DailyPlanning |
Daily |
.Modules.TodayPlanning |
Today |
.Modules.TomorrowPlanning |
Tomorrow |
The repository templates currently use the following nested display values. They are the preferred surface for comparable edits:
| Area | Values |
|---|---|
| Current conditions | .TemperatureF, .ConditionText, .ConditionTextLower, .ApparentTemperatureF, .RelativeHumidityPercent, .WindDirectionText, .WindSpeedMph |
| Hourly periods | .Periods, .HourLabel, .Name, .TemperatureF, .TextDescription, .TextDescriptionLower, .MentionPrecipitation, .ProbabilityOfPrecipitationPercent |
| Dayparts | .Dayparts[].Key and .Dayparts[].Summary fields DisplayName, DominantCondition, DominantConditionDisplay, TemperatureTrend, TemperatureStartPhraseF, TemperatureEndPhraseF, TemperaturePeakPhraseF, TemperatureSteadyPhraseF, TemperaturePhraseF, MentionPrecipitation, and MaxPopPercent |
| Precipitation timing | .PrecipitationWindows, plus each window's PeriodBegins, PeriodBeginsHourLabel, PeriodEnds, PeriodEndsHourLabel, ExpectationPhrase, MaxPopPercent, MaxPopTime, and MaxPopHourLabel |
| Alert digest | .AlertDigest.Relevant entries' Event, Headline, PeriodBegins, and PeriodEnds |
| SPC risk digest | .SPCConvectiveOutlooks.RiskDigest entries' LabelText, RiskLabel, PeriodBegins, and PeriodEnds |
Other fields on these typed modules remain available when a template has a well-defined display need. Their module contracts and weather derivation belong to Module contract internals, Module builder internals, and Forecast derivation internals.
Validate Changes
Run the focused checks after editing templates, partials, prompts, or schemas:
go test ./internal/reporttemplate ./internal/generatedtext ./internal/app
git diff --check
The render-context and template tests cover Daily, Today, Tomorrow, and Hourly contexts. Run the repository-wide test suite before merging a broader change.