Skip to content

Add a map view (layout="map") to the embed component #72

Description

@hhkaos

Motivation

The embed (apps/embed, <ote-events>) currently offers list and calendar
layouts. A map view would help visitors explore in-person events
geographically, which is especially useful for people who don't know the
local geography well (e.g. "what's happening near me" browsing).

Proposed behavior

Add layout="map" alongside the existing list/calendar values.

Events with location.geo — plotted as pins. This is the only case that
gets an exact pin.

Events with location.venue but no location.geo — do not
geocode them client-side. We considered a live geocoder (Nominatim, as
apps/editor/src/ui/map.ts#geocodeVenue already does) and a bundled
offline city gazetteer, and rejected both for the embed:

  • A live geocoding call per pageview/per visitor doesn't scale and conflicts
    with Nominatim's usage policy (rate limits, no bulk/automated client use).
  • An offline gazetteer avoids the network problem but not the accuracy one:
    location.venue is a single free-text string with no structured
    city/country, so matching it against a city list is exactly where it's
    fragile — common city names collide worldwide (Valencia, Córdoba,
    Cambridge, San José, Toledo, Guadalajara...). A confidently wrong pin is
    worse than no pin, particularly for the "I don't know this area" use case
    this view is meant to serve.

Instead: these events are excluded from the map and surfaced honestly —
a plain on-page notice near the map (e.g. "N events aren't shown on the map
because they don't have coordinates") plus a console.warn for the
integrating developer, both pointing at how to fix the source data (the
geocoding picker already in apps/editor, where a human confirms the pin
before it's published in location.geo). No pin is invented.

Online-only events (no location.venue at all) — these aren't "missing
coordinates", they have no physical location to plot. Don't lump them into
the "missing coordinates" notice above. Give them their own treatment: a
separate section/badge/count (e.g. "N online events") rather than silently
dropping them or conflating them with unmappable in-person events.

Hybrid events (location.geo and onlineUrl) — get a pin, with the
popup/card also noting the online option.

Non-goals

  • No client-side/live geocoding of any kind in the embed bundle.
  • No exact-vs-approximate pin distinction — an event either has geo and
    gets an exact pin, or it doesn't and isn't plotted.
  • No deep-linkable map center/zoom URL state for this iteration — this ships
    as one view among the existing layouts, not a standalone map component.

Implementation notes

  • Follow the src/calendar-layout.ts pattern: a separate module, never
    statically imported by src/main.ts, loaded via import() only when a
    consumer requests layout="map", so the base ote-events.js bundle stays
    minimal (per apps/embed/CLAUDE.md).
  • Leaflet + OSM tiles is the existing precedent for maps in this repo
    (apps/editor/src/ui/map.ts) — reuse that approach/attribution rather than
    introducing a new mapping dependency.
  • This is a new public layout value → needs a SemVer minor bump in
    apps/embed/package.json, a CHANGELOG.md entry, and the rest of the
    release checklist in apps/embed/CLAUDE.md.
  • Read apps/embed/CLAUDE.md before starting.

Possible follow-up (separate issue)

A non-blocking packages/validate warning for location.venue present
without location.geo would surface this at publish/CI time instead of only
in the embed at render time, following the existing "absent field = absent +
warning" convention. Not part of this issue's scope.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions