Skip to content

feat(cms-sections): add Google Maps area selector for format: map#4200

Merged
guitavano merged 1 commit into
mainfrom
guitavano/sections-editor-map-widget
Jul 2, 2026
Merged

feat(cms-sections): add Google Maps area selector for format: map#4200
guitavano merged 1 commit into
mainfrom
guitavano/sections-editor-map-widget

Conversation

@guitavano

@guitavano guitavano commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a MapField widget that renders an interactive Google Map with a draggable/resizable circle for area selection, mirroring admin/components/ui/Map.tsx. Schema string fields tagged with format: "map" (the convention emitted by MapWidget in deco-apps/admin/widgets.ts) now render the map instead of a plain text input.
  • Used by the Location matcher's coordinates field (includeLocations / excludeLocations) so users can pick a center + radius on the map instead of typing "lat,lng,radius" by hand.

Implementation notes

  • New apps/mesh/src/web/components/sections-editor/fields/map-field.tsx. React-19-safe (no useEffect): uses a ref-callback with a cleanup return and pins the initial value in a ref so onChange-driven re-renders don't tear down the map mid-drag.
  • Routes format === "map" to MapField in schema-form.tsx, alongside the existing image-uri / file-uri / location handlers.
  • The Maps JS API key is a runtime server env var (GOOGLE_MAPS_API_KEY), exposed to the client through /api/config — the exact same pattern as POSTHOG_KEY. Read at request time, so it's configurable per environment (dev / staging / prod) without rebuilding the bundle, and belongs in the runtime k8s config (deco-apps-cd), not the build. It's a client-side token by design — the Maps JS API loads in the browser and always ships its key in the request URL, so it can't be hidden and is not a secret; security relies on Google Cloud restrictions (HTTP-referrer allowlist + API restriction to "Maps JavaScript API"). When unset, the field renders an inline "unavailable" note instead of crashing.
  • Adds @types/google.maps devDependency; the field file uses a triple-slash reference instead of widening tsconfig.json's types array.

Setup

  • Dev: set GOOGLE_MAPS_API_KEY in apps/mesh/.env (read at server runtime).
  • Staging / prod: set GOOGLE_MAPS_API_KEY in the runtime env (deco-apps-cd), per environment — same mechanism as DBOS_CONDUCTOR_KEY / POSTHOG_KEY. No CI/build change needed.
  • Confirm the key's referrer allowlist in Google Cloud includes the target domains before enabling — without that the map fails to load.

Test plan

  • GOOGLE_MAPS_API_KEY set in apps/mesh/.env, then bun run dev.
  • Open a variant whose rule is the Location matcher → + Add item under Include Locations → drill in.
  • Area selection field renders a Google Map with a blue circle.
  • Drag the circle, resize via handles, click elsewhere on the map → the value updates as lat,lng,radius.
  • Switching variants / closing & reopening the item restores the map at the saved circle.
  • Unset the env var → the field shows the "unavailable" note instead of crashing.
  • GET /api/config returns googleMapsApiKey (unit tests cover set/unset).

🤖 Generated with Claude Code

@guitavano guitavano force-pushed the guitavano/sections-editor-map-widget branch 7 times, most recently from 17aee27 to 28959a1 Compare July 2, 2026 16:19
Adds a MapField widget that renders an interactive Google Map with a
draggable/resizable circle for selecting an area, mirroring the
admin app's existing MapWidget. Schema string fields tagged with
`format: "map"` (the convention emitted by `MapWidget` in
deco-apps/admin/widgets.ts) now render the map instead of a plain text
input — used by the Location matcher's `coordinates` field
(includeLocations / excludeLocations) so users can pick a center +
radius via the map instead of typing `"lat,lng,radius"` by hand.

- New `fields/map-field.tsx`. React-19-safe (no useEffect): uses a
  ref-callback with a cleanup return and pins the initial value in a
  ref so onChange-driven re-renders don't tear down the map mid-drag.
- Routes `format === "map"` to `MapField` in `schema-form.tsx`.
- The Maps JS API key is a RUNTIME server env var (GOOGLE_MAPS_API_KEY),
  exposed to the client via /api/config (same pattern as POSTHOG_KEY) so
  it's configurable per environment without rebuilding. It's a
  client-side token by design, not a secret; security relies on Google
  Cloud HTTP-referrer + API restrictions. The field shows an inline
  "unavailable" note when the key is unset.
- Adds `@types/google.maps` devDependency; the file uses a triple-slash
  reference instead of widening `tsconfig.json`'s `types` array.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@guitavano guitavano force-pushed the guitavano/sections-editor-map-widget branch from 28959a1 to 9d1a307 Compare July 2, 2026 16:26
@guitavano guitavano merged commit 9fed87e into main Jul 2, 2026
14 checks passed
@guitavano guitavano deleted the guitavano/sections-editor-map-widget branch July 2, 2026 16:31
decocms Bot pushed a commit that referenced this pull request Jul 2, 2026
PR: #4200 feat(cms-sections): add Google Maps area selector for `format: map`
Bump type: minor

- decocms (apps/mesh/package.json): 3.91.0 -> 3.92.0

Deploy-Scope: both
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant