- The app should revolve around one simple mental model:
- one anchor city
- one ordered list of target cities
- The
TimeandCurrencypanels should stay aligned to that same selection model. - Weather remains anchored to New Zealand and does not generalise with the rest of the app.
- The map is optional, not foundational. It may be disabled entirely, even for NZ-focused use.
- The current config editor, draft workflow, and snapshot restore behaviour remain useful and should be preserved while the data model is simplified.
- Reference data should move out of hand-written Rust arrays and into checked-in source files with generated Rust output.
- Anchor city is the primary user choice.
- Target cities are the primary comparison list.
- Time behaviour derives from
anchor_city -> target_cities. - Currency behaviour derives from the countries and currencies of those same target cities.
- If the user adds a country or currency that does not yet have a matching target city, the app may default to that country’s capital city as a convenience.
- That capital-city fallback is a helper, not the core model. The primary model remains city-based.
- Weather stays NZ-only for now.
- The map should be user-toggleable and may be removed from non-NZ workflows if that keeps the product cleaner.
/currencyshould no longer behave like a separate FX-configuration command. It should resolve currency to country, then country to representative city, and finally add that city to the target-city list./countryand/currencyshould converge on the same internal place-selection path.
- There is one mental model instead of parallel models for time, currency, and map state.
- The
TimeandCurrencywindows become two views over the same user selection. - The editor becomes easier to understand because the user is choosing places, not managing multiple technical lists.
- This reduces drift between panels and avoids surprising state mismatches.
- It also gives the product a clearer identity: NZ weather plus place-to-place comparison.
- Config draft, apply, discard, reset, reload, and restore already exist.
- Snapshot save and restore already exist.
- A visual
/configeditor already exists withPlacesandActions. - Search-backed pickers already exist for anchor city, target city, country, currency, and map visibility.
- The current codebase still carries a few compatibility paths from the older model:
time.city_codescurrency.country_codes
- Reference data now comes from checked-in source files in
data/and is generated at build time throughbuild.rs. - The editor now has a
Placestab with anchor-city selection, target-city add or remove or reorder, country and currency helper flows, and clearer on-panel guidance. /currencynow follows the place model by resolvingcurrency -> country -> representative city -> target city.- Time and currency interactions are re-coupled and now follow the same active target city.
- The map now defaults to off, can be toggled from
/maporActions, disappears from the main layout when disabled, and is fixed to country-level rendering. - Country coverage is now effectively complete, with one representative city per supported country.
- The next major constraint is no longer country coverage. It is whether the app should expose a broader city catalogue beyond one representative city per country.
- The expanded weather grid still has unresolved layout defects. Header cells are too tight, emoji rows do not use width consistently, and the rendered borders can look detached or stray depending on terminal width and whether the map is visible.
- The weather and exchange integrations are functionally acceptable, but the HTTP client paths are still lightly hardened. They rely on third-party API trust, do not yet call
error_for_status(), and the exchange-rate response still uses loose JSON parsing rather than a typed schema.
- Decide whether target-city search should stay at one representative city per country or expand into a broader curated city catalogue.
- Review shared-currency policy country by country, especially where one currency maps to several states.
- Decide whether to expose a small visible indicator for the currently active target city across the time and currency panels.
- Keep
Escin the config editor as “close editor only”; do not silently discard the draft. - Keep direct commands such as
/mapimmediate, even when a draft exists, unless there is a strong reason to route them through the draft. - Rework the expanded weather grid so it uses one deterministic width model across map-on and map-off layouts, with column widths sized from actual content rather than trial-and-error spacing tweaks.
- Remove stray or detached-looking vertical borders in the expanded weather table by rendering the grid inside an exact content rect instead of letting it float inside a wider panel.
- Normalise emoji-cell rendering in the expanded weather grid so icon spacing is visually consistent across
Sunny,Pt cldy,Cloudy, and other labels on terminals with uneven emoji display widths. - Harden the Open-Meteo and ExchangeRate-API client paths with explicit HTTP status handling, stricter response parsing, and clearer separation between offline failures and upstream bad responses.
- One selection model should drive both time and currency.
- City is the core comparison unit.
- Country and currency data should fall out of city metadata by default.
- Weather remains NZ-scoped.
- Map is optional.
- User-authored preferences stay separate from derived runtime state.
- Restore means return to a previously saved preference snapshot.
- Reload means re-read the current config file from disk.
- Reset means replace draft state with built-in defaults, not old user preferences.
- Currency commands should add places, not create an independent list of FX preferences.
- Canonical reference facts and curated product defaults should live in separate source files.
- Keep the TOML schema backward compatible where practical.
- Move toward a primary structure like:
anchor_city_codetarget_city_codesmap.enabled
- Keep the city catalogue:
current_cityhome_citytracked_cities
- Derive runtime behaviour from those fields:
- time: anchor city to each target city
- currency: anchor city currency to each target city currency
- map: anchor city to each target city when enabled
- Treat currency-specific additions as convenience input that resolves back to a city through country.
- If a country is chosen without a city, default to the capital city for that country.
- Keep snapshot metadata and restore support under the config directory.
- Legacy
currencyconfig may continue to load, but the primary runtime path should derive from anchor and target cities.
- Keep runtime fully offline and deterministic.
- Avoid introducing a country or city crate as the primary source of truth.
- Store canonical country and currency facts in
data/countries.csv. - Store curated representative-city defaults in
data/representative_cities.json. - Generate Rust tables from those files in
build.rs. - Keep generated Rust out of hand-edited source modules where practical.
- Treat representative-city choice as a product decision, not raw reference fact.
- Allow multi-timezone countries to start with one default representative city, with optional later expansion.
- Shared-currency cases such as
EURneed an explicit canonical focal-country policy for the/currencyshortcut.
- Existing configs must continue to load.
- Existing
time.city_codesshould map into the new target-city model. - Existing
currency.country_codesshould be treated as legacy override data during migration. - Existing map settings should be preserved where possible, but the end state should prefer
map.enabledplus anchor-to-target rendering. - NYC to BOS migration behaviour must still be preserved.
- City codes remain unique case-insensitively.
- Timezones must parse successfully.
- Every target city code must refer to a known catalogue city.
- Anchor city code must refer to a known catalogue city.
- Any capital-city fallback must resolve to a known city entry before save.
- Legacy fields may still load, but the editor should guide the user toward the simplified model.
/configedits should modify a draft, not live config.- Action meanings remain:
apply: persist the current draft and make it livediscard: drop the draft and return to the last loaded configreset: replace the current draft with built-in defaultsreload: re-read the latest config file from diskrestore: load a previously saved user snapshot
- Snapshot restore restores user preferences, not recomputed defaults.
- Reload should never silently replace preferences with defaults.
- Keep
/configas the entry point for the overlay editor. - Rework the editor around the simplified model.
- Preferred tabs:
PlacesActions
Placesshould own:- anchor city
- target city list
- optional helper actions for adding a country or currency by resolving to a city
Actionsshould keep:- apply
- discard
- reset
- reload
- restore
- map visibility
- Show the current anchor city explicitly.
- Show the ordered target-city list explicitly.
- Allow add, remove, and reorder for target cities.
- Allow changing the anchor city without implicitly rewriting the target list.
- Offer a helper flow for “add country” or “add currency”, which resolves to a city, usually the capital.
- Keep country and currency helpers semantically aligned by resolving both through country to representative city.
- Keep draft lifecycle controls in one place.
- Keep snapshot restore visible.
- Keep map visibility here rather than in a separate config tab.
- Add snapshot browsing later if the single latest snapshot becomes limiting.
- Draft config workflow and snapshots.
- Initial
/configeditor shell. - Search-backed pickers.
- Introduce explicit anchor city and target-city list settings.
- Derive time and currency behaviour from that shared list.
- Keep compatibility shims for old config fields.
- Replace the current split
TimeandCurrencyediting model with a unifiedPlacestab. - Add target-city reordering.
- Add anchor-city selection.
- Add helper flows for country or currency to city resolution.
- Add
map.enabled. - Let the user hide the map panel.
- Reduce map configuration to a simple visibility toggle with country-level rendering.
- Add migration tests.
- Add editor-flow tests.
- Update README and usage text to match the simplified model.
- Remove stale references to
/currencyas a separate FX configuration surface. - Refactor the expanded weather grid into a single width-aware renderer with shared fit checks for map-on and map-off layouts.
- Add UI-level tests for weather-grid width budgeting, border generation, and icon-plus-label cell composition.
- Add
.error_for_status()to third-party API calls and tighten upstream failure reporting. - Replace loose exchange-rate JSON access with a typed response model and add tests for schema expectations and fallback behaviour.
- Add
data/countries.csvfor canonical country and currency metadata. - Add
data/representative_cities.jsonfor curated default city metadata. - Add
build.rsto validate and generate Rust reference tables. - Swap
reference.rsto consume generated data without changing its public lookup API. - Add tests covering country count, representative-city coverage, and shared-currency policy.
- The user can choose one anchor city and one ordered target-city list in
/config. - The
TimeandCurrencypanels derive from that same city selection. - The user does not need to manage separate time and currency lists in normal use.
- Weather remains stable and NZ-scoped.
- The user can disable the map.
- Existing configs still load without breakage.
- Draft apply, discard, reload, reset, and restore continue to work.
/currencybehaves as a place-selection shortcut rather than a separate configuration path.- Country and currency search cover the full supported registry.
- Each supported country resolves to one default representative city.
- Decide whether to keep one representative city per country or introduce a broader curated city list for target search.
- Add more coverage tests around shared-currency choices and command behaviour that should remain immediate.
- Keep tightening editor wording where the behaviour is correct but the panel is easy to misread.