Something went wrong

Thank you for being patient! We're working hard on resolving the issue

Weather - Lona Docs Log in

Weather Template

There are two weather templates with the same expanded shape but different sourcing for locationId:

TemplatelocationId sourceWhen to use
weatherprops.locationId (per-row)Sheet-specific rows ("Perth at the office")
preferences-default-weatherprefs.defaultWeatherLocation (per-user)The user's default weather row

Both expand to the same data-source + data-renderer + logs triple. The preferences-default-weather template wires an onAttach listener so every alias instance fans out when the user changes their default location preference; the weather template is purely static and only re-expands when its own props mutate.

Wire shape: weather

{
  "type": "alias",
  "label": "Perth",
  "attributes": {
    "template": "weather",
    "props": { "locationId": "2063523" }
  }
}
PropTypeRequiredMeaning
locationIdstringyesOpenWeatherMap city id (e.g. 2063523 for Perth)

Wire shape: preferences-default-weather

{
  "type": "alias",
  "label": "Weather",
  "attributes": { "template": "preferences-default-weather" }
}

This template takes no props. The locationId is read from CalendarPreferences.defaultWeatherLocation — a LiveData<string> backed by localStorage under the lona-pref-default-weather-location key. Updating the preference fans out via sheet.reexpandAliasesByTemplate(...) to every sheet that has a preferences-default-weather alias attached, so all default-weather rows pick up the new location simultaneously.

The canonical builtin :~lona:weather resolves server-side to the preferences-default-weather template — linkRow(sheet, ":~lona:weather") is the one-liner that adds a default-weather row.

Default alias: :~lona:weather

The canonical builtin :~lona:weather resolves to the preferences-default-weather template. The wire form is one row with no props; hydration reads the user's preferred location from CalendarPreferences.defaultWeatherLocation (default Honolulu, 2550002) and expands to the standard triple:

:~lona:weather                    ← wire row, type=alias
│                                 template=preferences-default-weather
│                                 (no props; locationId from prefs)
├─ data-source                    lookupKey=:~weather:2550002    ← from prefs
│  │                              attrs={dtype:"obj", lid:2550002}
│  └─ data-renderer               type=weather                  ← column.weather plugin
└─ logs                           lookupKey=:~weather:2550002:logs
                                  attrs.logType=weather

When the user changes their default location preference, the alias re-expands in place — both the data-source and logs lookup keys flip, the renderer child's identity is preserved, and every sheet's default weather row updates simultaneously. There is no per-row setProp for this template.

Custom-location alias

When a user picks a city in the location modal, the alias carries an explicit locationId (here Perth, 2063523):

alias                             template=weather
│                                 label="Perth"
│                                 props.locationId=2063523
├─ data-source                    lookupKey=:~weather:2063523
│  │                              attrs={dtype:"obj", lid:2063523}
│  └─ data-renderer               type=weather
└─ logs                           lookupKey=:~weather:2063523:logs
                                  attrs.logType=weather

The shape is identical to the default — only the locationId prop and the derived lookup keys differ.

Anatomy of the children

  • The data-source lookup key follows :~weather:{lid}. The server's weather provider syncs into that key; cells encode as weather.v1.
  • The data-renderer is a data-renderer of type weather — the FE's column.weather plugin paints daily forecast tiles in a week-span layout.
  • The logs row is keyed :~weather:{lid}:logs and carries attributes.logType = "weather" so the logs viewer filters to weather sync events only.

Without the template: a "normal" weather row

If you bypassed the template entirely and shipped the equivalent tree as plain rows, you'd write four rows (the alias replaces this with one):

data-source                       lookupKey=:~weather:2063523
│                                 attrs={dtype:"obj", lid:2063523}
│                                 label="Perth"
└─ data-renderer                  type=weather
                                  storage=parent

logs                              lookupKey=:~weather:2063523:logs
                                  attrs.logType=weather
                                  label="Sync Logs"

(The two trees are peers — logs is a top-level row, not a child of data-source. The alias bundles them as siblings under itself; the hand-built form makes that explicit.)

Two reasons we don't do this:

  1. Mutation cost. Switching cities is a one-prop edit on the alias versus three coordinated row edits (source key, source attrs, logs key). Templates make the canonical mutation atomic.

  2. Schema versioning. Renaming column.weathercolumn.weather.v2 or adding a new sibling renderer is a template-factory edit; with hand- built rows you'd migrate every persisted row.

The hand-built shape is still legal — it's how the renderers actually load. Templates are sugar that produces this tree on hydrate.

Renderer routing

The data-renderer child is storage: "parent" — it lives on the data-source, not on the alias. That matters for two reasons:

  • The renderer paints at the data-source's column position, not at the alias's. The alias is a logical wrapper; visible cells come from the source.
  • Multiple renderers on one source paint into different layout slots (see the task-list template for the multi-slot example). Weather only needs one slot today.

Switching cities

(applies to the weather template only — preferences-default-weather rows update via CalendarPreferences.defaultWeatherLocation; see the Default alias section.)

const row = sheet.row({ rowLabel: "Perth" });
row?.alias?.setProp("locationId", "2193733");  // → Auckland

This re-expands both child rows with the new lookup keys (:~weather:2193733 and :~weather:2193733:logs) without dropping the renderer child or the row label. The new lookup keys then drive the canonical-cell stream through SheetsAccessor.

Lookup-key precedence

(applies to the weather template only — preferences-default-weather takes no props.)

The weather template may carry an explicit lookupKey prop in addition to locationId. When both are present, lookupKey wins for the source key and the logs key derives ${lookupKey}:logs. This is how migrations stage custom keys; in normal use, you only set locationId.

If neither prop is present, hydration fails with Alias template "weather" requires non-empty string prop "locationId".

Server flow

linkRow → server dispatches via the rowkey schema (:~weather provider) → upserts a canonical weather SheetRowDb row → ships it back in the sheet payload. The FE creates the alias row in insertTopLevelRow, which mirrors it into the rows-side Sheet so hydration runs immediately — no full-sheet refetch required.

See also