Files
weatherreporter/docs/templates.md

12 KiB

Report Templates

Purpose

This guide describes the implemented Markdown report template surface for weatherreporter. It is for maintainers editing embedded report templates, especially the hourly report template.

Templates are Go text/template files. The current implemented template is:

  • internal/reporttemplate/templates/hourly.md.tmpl

The hourly template is rendered from a structured HourlyRenderContext. Weather data collection, derivation, module execution, generated text validation, and artifact paths are handled before template rendering.

Editing Rules

  • Use Go text/template syntax.
  • Keep templates focused on Markdown layout, headings, ordering, and simple conditional display.
  • Do not put weather derivation, source selection, or path construction logic in templates.
  • Missing template keys are errors. A misspelled variable will fail rendering.
  • No custom template functions are currently registered.
  • Optional module stanzas are pointers and should be guarded with {{ with .Modules.WeatherStory }}...{{ end }}.
  • Slices can be rendered with {{ range .Items }}...{{ else }}...{{ end }}.

Hourly Context

The hourly template receives five top-level values:

Variable Type Description
.Report HourlyReportContext Display metadata and friendly labels for the rendered report.
.GeneratedText Hourly Structured text returned by Scriptorium.
.Modules HourlyTemplateModules Preferred deterministic template surface, keyed by module purpose.
.Collected facts.CollectedFacts Normalized upstream facts for advanced template use.
.Derived facts.DerivedFacts Shared derived facts for advanced template use.

Prefer .Modules for normal template edits. .Collected and .Derived are available when a template needs lower-level facts, but templates should still avoid nontrivial derivation.

Report

Variable Type Description
.Report.Title string Display title. Currently Hourly Report.
.Report.LocationName string Prompt/report location label, such as Brentwood, MO.
.Report.GeneratedAt time.Time Canonical generation timestamp.
.Report.GeneratedAtLabel string Friendly local generation time label.
.Report.ValidPeriod timeutil.Period Canonical valid period.
.Report.ValidPeriodLabel string Friendly local valid period label, such as 2026-05-29 at 8:30 AM to 2026-05-29 at 2:30 PM.
.Report.Timezone string Effective report timezone.

GeneratedText

These fields are written by Scriptorium as structured JSON, validated by weatherreporter, and then inserted into the render context.

Variable Type Description
.GeneratedText.Summary string Required short prose summary.
.GeneratedText.Timing string Required prose about timing of notable weather changes or hazards.
.GeneratedText.Impacts string Required prose about practical near-term impacts.
.GeneratedText.Confidence string Optional confidence or uncertainty note. Empty when omitted by the LLM.

Example:

## Summary

{{ .GeneratedText.Summary }}
{{ with .GeneratedText.Confidence }}

## Confidence

{{ . }}
{{ end }}

Modules

.Modules exposes typed outputs from the same module pipeline used for the prompt data package. Module fields are pointers because missing-data policy may omit a stanza.

Variable Type Description
.Modules.Metadata *briefing.MetadataModule Report metadata module output, when present.
.Modules.CurrentConditions *briefing.CurrentConditionsModule Current conditions from /conditions/current.
.Modules.HourlyForecast *briefing.HourlyForecastModule Hourly forecast periods overlapping the report valid period.
.Modules.PrecipTiming *briefing.PrecipTimingModule Derived precipitation timing facts and threshold windows.
.Modules.AlertDigest *briefing.AlertDigestModule Active alert status and relevant alert overlaps.
.Modules.SPCConvectiveOutlooks *briefing.SPCConvectiveOutlooksModule SPC outlooks that overlap the report valid period.
.Modules.AreaForecastDiscussion *briefing.AreaForecastDiscussionModule AFD key messages and configured discussion sections.
.Modules.SPCConvectiveDiscussion *briefing.SPCConvectiveDiscussionModule SPC discussions retained for qualifying overlapping categorical risk days.
.Modules.WeatherStory *briefing.WeatherStoryModule Latest NWS weather story, when available.

Current Conditions

Common fields:

Variable Type Description
.Modules.CurrentConditions.ConditionText string Current condition text.
.Modules.CurrentConditions.TemperatureF *float64 Current temperature.
.Modules.CurrentConditions.ApparentTemperatureF *float64 Apparent temperature.
.Modules.CurrentConditions.RelativeHumidityPercent *float64 Relative humidity.
.Modules.CurrentConditions.WindDirection string 16-point compass wind direction.
.Modules.CurrentConditions.WindSpeedMph *float64 Wind speed.

Example:

{{ with .Modules.CurrentConditions }}
{{ .ConditionText }}{{ with .TemperatureF }}; {{ . }} F{{ end }}{{ with .WindDirection }}; wind {{ . }}{{ end }}{{ with .WindSpeedMph }} {{ . }} mph{{ end }}
{{ else }}
No current conditions available.
{{ end }}

Hourly Forecast

Common period fields:

Variable Type Description
.Modules.HourlyForecast.Periods []briefing.HourlyForecastPeriod Ordered periods for the hourly report valid period.
.Modules.HourlyForecast.Periods[].PeriodBegins string Friendly local period start label.
.Modules.HourlyForecast.Periods[].PeriodEnds string Friendly local period end label.
.Modules.HourlyForecast.Periods[].Name string Source period name.
.Modules.HourlyForecast.Periods[].TextDescription string Hourly forecast text.
.Modules.HourlyForecast.Periods[].TemperatureF *float64 Forecast temperature.
.Modules.HourlyForecast.Periods[].ProbabilityOfPrecipitationPercent *float64 Forecast precipitation probability.
.Modules.HourlyForecast.Periods[].WindDirection string 16-point compass wind direction.
.Modules.HourlyForecast.Periods[].WindSpeedMph *float64 Wind speed.
.Modules.HourlyForecast.Periods[].WindGustMph *float64 Wind gust.

Example:

{{ with .Modules.HourlyForecast }}{{ range .Periods }}
- {{ .PeriodBegins }}: {{ .TextDescription }}{{ with .TemperatureF }}; {{ . }} F{{ end }}{{ with .ProbabilityOfPrecipitationPercent }}; {{ . }}% precipitation{{ end }}
{{ else }}
- No hourly forecast rows available.
{{ end }}{{ end }}

Precipitation Timing

Common fields:

Variable Type Description
.Modules.PrecipTiming.MaxPopPercent *int Highest hourly precipitation probability in the valid period.
.Modules.PrecipTiming.MaxPopTime string Friendly local time for the highest hourly precipitation probability.
.Modules.PrecipTiming.ProbabilityThreshold float64 Threshold used to define precipitation windows.
.Modules.PrecipTiming.PrecipitationWindows []briefing.PrecipitationWindowModule One or more threshold precipitation windows.
.Modules.PrecipTiming.PrecipitationWindows[].PeriodBegins string Friendly local window start.
.Modules.PrecipTiming.PrecipitationWindows[].PeriodEnds string Friendly local window end; omitted for open windows.
.Modules.PrecipTiming.PrecipitationWindows[].MaxPopPercent *int Highest precipitation probability inside the window.
.Modules.PrecipTiming.PrecipitationWindows[].MaxPopTime string Friendly local time for the window maximum.
.Modules.PrecipTiming.ThunderMentioned bool Whether thunder is mentioned in the forecast text.

Alert Digest

Variable Type Description
.Modules.AlertDigest.Checked bool Whether alert data was checked successfully.
.Modules.AlertDigest.ActiveCount int Active alert count from the source.
.Modules.AlertDigest.RelevantCount int Alert count overlapping the report period.
.Modules.AlertDigest.Missing bool True when alert data is unavailable.
.Modules.AlertDigest.Relevant []briefing.AlertSummary Relevant alert summaries.
.Modules.AlertDigest.Relevant[].Event string Alert event name.
.Modules.AlertDigest.Relevant[].Headline string Alert headline.
.Modules.AlertDigest.Relevant[].Severity string Alert severity.

SPC Outlooks And Discussion

Variable Type Description
.Modules.SPCConvectiveOutlooks.Checked bool Whether SPC outlook data was checked successfully.
.Modules.SPCConvectiveOutlooks.AsOf string Friendly source as-of time.
.Modules.SPCConvectiveOutlooks.IssuedAt string Friendly source issue time.
.Modules.SPCConvectiveOutlooks.Outlooks []briefing.SPCConvectiveOutlookRecord Overlapping outlook records.
.Modules.SPCConvectiveOutlooks.Outlooks[].Day int SPC day number.
.Modules.SPCConvectiveOutlooks.Outlooks[].OutlookType string Outlook type, such as categorical.
.Modules.SPCConvectiveOutlooks.Outlooks[].Label string Short outlook label.
.Modules.SPCConvectiveOutlooks.Outlooks[].LabelText string Human-readable outlook label.
.Modules.SPCConvectiveOutlooks.Outlooks[].PeriodBegins string Friendly outlook period start.
.Modules.SPCConvectiveOutlooks.Outlooks[].PeriodEnds string Friendly outlook period end.
.Modules.SPCConvectiveOutlooks.Outlooks[].ImageURL string Source image URL.
.Modules.SPCConvectiveDiscussion.IncludedBecause string Criterion used to include discussions.
.Modules.SPCConvectiveDiscussion.Discussions []briefing.SPCConvectiveDiscussionRecord Retained discussion records.
.Modules.SPCConvectiveDiscussion.Discussions[].Headline string Discussion headline.
.Modules.SPCConvectiveDiscussion.Discussions[].Summary string Discussion summary.
.Modules.SPCConvectiveDiscussion.Discussions[].Discussion string Full discussion text.

Area Forecast Discussion

Variable Type Description
.Modules.AreaForecastDiscussion.Product string Source product identifier.
.Modules.AreaForecastDiscussion.KeyMessages []string AFD key messages.
.Modules.AreaForecastDiscussion.ShortTerm string AFD short-term section text.
.Modules.AreaForecastDiscussion.LongTerm string AFD long-term section text.

Weather Story

Variable Type Description
.Modules.WeatherStory.Available bool True when a story is available.
.Modules.WeatherStory.OfficeID string Source office ID.
.Modules.WeatherStory.PeriodBegins string Friendly story period start.
.Modules.WeatherStory.PeriodEnds string Friendly story period end.
.Modules.WeatherStory.UpdatedAt *time.Time Canonical update timestamp.
.Modules.WeatherStory.Title string Story title.
.Modules.WeatherStory.Description string Story description.
.Modules.WeatherStory.AltText string Story image alt text.
.Modules.WeatherStory.Priority bool Source priority flag.
.Modules.WeatherStory.Order int Source order.
.Modules.WeatherStory.DownloadURL string Source download URL.

Collected And Derived Facts

The template also receives the full facts.CollectedFacts and facts.DerivedFacts structs:

  • .Collected contains normalized source data and provenance from upstream Weather API fetches.
  • .Derived contains shared slices and calculations used across modules, such as valid-period hourly periods, precipitation timing, alert overlaps, and SPC filtering inputs.

These values are intentionally lower-level than .Modules. Use them when a template needs a specific field that is not exposed by a module, but keep calculation-heavy changes in Go.

Validation

After editing a template, run:

go test ./internal/reporttemplate ./internal/generatedtext ./internal/app

For a full check, run:

go test ./...
go run ./cmd/weatherreporter --help
git diff --check

Template render tests currently exercise the hourly template through internal/generatedtext/render_context_test.go and internal/reporttemplate/reporttemplate_test.go.