Layer Manager: add "Share layer to external services" to the layer menu
Motivation
Today there's no way to take a layer you're looking at in MMGIS and view it in another GIS tool (QGIS, ArcGIS, or any standards-friendly client). If a science team has tuned a layer — picked a colormap, set the color scale min/max, chosen a time — that styled view lives only inside MMGIS. To reproduce it elsewhere, someone has to hunt down the underlying service URL by hand and manually reconstruct the colormap, rescale, and time parameters, which is tedious and error-prone. The result is that MMGIS layers are effectively trapped in MMGIS.
We want a one-click way to copy a layer's URL out of MMGIS and paste it straight into another GIS tool, reproducing the same layer — same styling, same moment in time — that you see on the map right now.
How it should work
- Each layer in the Layer Manager has a three-dots (overflow) menu. Add a "Share to external services" option to that menu.
- Clicking it surfaces a ready-to-copy URL for that layer, with a copy-to-clipboard affordance. The user copies it and pastes it into QGIS, ArcGIS, or another GIS client, and the layer shows up looking the way it did in MMGIS.
- The URL form adapts to the layer's underlying service type:
- XYZ tile layers → an XYZ tile-template URL. The
{z}/{x}/{y} tile placeholders stay intact (GIS clients need those), but everything else is resolved — the active colormap, the current color-scale min/max, the selected time, and the full service/base URL are all baked in.
- WMTS layers → a WMTS link.
- WMS layers → a WMS link.
- Styling is captured from the current on-screen state, not just the layer's saved defaults: if the user has changed the colormap or color-scale min/max, the shared URL reflects what they're currently looking at.
- Time is baked in as a snapshot. For time-enabled layers, the currently-selected time is resolved into a fixed value in the URL so the external tool shows that exact moment. (No live/dynamic time parameter — most desktop GIS clients wouldn't fill it in anyway.)
- The pasted URL should "just work" — it's the fully-resolved address MMGIS itself uses to render the layer, not a template full of unfilled variables the user has to fix by hand.
Done when
Out of scope
- Vector / GeoJSON (geodatasets) layers — sharing those as a data download or feature URL is a separate concern; this issue is tile-based layers only.
- Offering a live/dynamic time parameter, or a UI toggle between snapshot and dynamic time.
- Any server-side proxy, short-link service, or authentication/token handling for external access — this shares the URL as-is.
- Building a general "share whole map / share view" feature; this is per-layer.
Draft implementation plan — written as of 42b9e0a on 2026-06-18. Rough guide; re-verify against latest code.
Current behavior
- The three-dots menu lives in the modern Layer Manager, not the legacy Layers tool. The kebab button is rendered in
src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx (~lines 176–181) and is currently a placeholder with no click handler and no menu items — a clean insertion point. Menu/handler wiring conventions for this component are in src/essence/Tools/LayerManager/adapters/handlers.ts.
- Layer config is read via the MMGIS API (
L_.layers.data[layerName]); the raw configured url carries scheme prefixes (COG:, stac-collection:, titiler-url:, geodatasets:) and template variables.
- URL resolution already exists and is the thing to surface:
- Tile/COG layers resolve per-tile in
src/essence/Basics/Layers_/leaflet-tilelayer-middleware.js (getTileUrl(), ~21–105): time placeholders replaced (~67–82), STAC/COG datetime injected (~29–40), COG render params applied (~48).
- COG/TiTiler params merged in
src/essence/Basics/Layers_/cogUrlUtils.ts (applyCogFieldsToUrl(), ~33–60): colormap_name (~47), rescale=<min>,<max> (~52), expression, resampling. Uses currentCogMin/Max (runtime) over cogMin/Max (config).
- Vector layers resolve in
src/essence/Basics/Layers_/LayerCapturer.js (~15–72) — out of scope here but shares the time-substitution logic.
- Current vs default styling state for the panel is built in
src/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts (~67–92): currentCogColormap, currentCogMin/Max, titilerUrl. Runtime updates flow through handlers.ts setColormap() / setRescale().
- Time substitution: per-layer
time config (enabled, type, format, start/end); tags {starttime}/{endtime}/{time}/{customtime.N} substituted in both the tile middleware (~67–82) and LayerCapturer; global state in src/essence/Basics/TimeControl_/TimeControl.js (~270–300).
- Existing export precedent (legacy tool, different component) for reference only:
src/essence/Tools/Layers/LayersTool.js (~570–651) — GeoJSON/KML/SHP export and raster downloadURL links. There is no existing "copy URL"/"share link" anywhere; this is greenfield.
Where the change lands & rough plan
- Add a "Share to external services" item to the kebab menu in
LayerLegend.tsx; gate visibility to tile-based layer types.
- Add a builder that, given a layer + current panel state, produces the external URL by layer type:
- XYZ: take the resolved tile URL but preserve
{z}/{x}/{y} while substituting in colormap (colormap_name), rescale (currentCogMin/Max), resolved current time, and the full base/service URL. Reuse applyCogFieldsToUrl() and the time-substitution logic rather than re-deriving them.
- WMTS / WMS: emit the appropriate service link form for those layer types.
- Pull styling from the current/runtime values (
currentCogColormap, currentCogMin/Max) so on-screen changes are reflected, falling back to config defaults.
- Resolve the current time to a fixed value (snapshot) using the same formatting the middleware uses, instead of leaving
{starttime}/{endtime} tags.
- Present the URL in a small dialog/popover with a copy-to-clipboard button.
⚠️ Gotcha: the tile-fetch path resolves {z}/{x}/{y} and the styling/time tags together at request time. For sharing you must resolve everything except {z}/{x}/{y}. Don't just grab a fetched tile URL (those have concrete tile coords) and don't reuse the raw config URL (those have unresolved colormap/rescale/time). The share URL is a third form: tile placeholders in, everything else out.
References
src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx (~176–181) — kebab menu
src/essence/Tools/LayerManager/adapters/handlers.ts — menu/handler wiring conventions
src/essence/Basics/Layers_/cogUrlUtils.ts (applyCogFieldsToUrl, ~33–60) — colormap/rescale params
src/essence/Basics/Layers_/leaflet-tilelayer-middleware.js (getTileUrl, ~21–105) — URL + time resolution
src/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts (~67–92) — current vs default styling state
src/essence/Basics/TimeControl_/TimeControl.js (~270–300) — global time state
Layer Manager: add "Share layer to external services" to the layer menu
Motivation
Today there's no way to take a layer you're looking at in MMGIS and view it in another GIS tool (QGIS, ArcGIS, or any standards-friendly client). If a science team has tuned a layer — picked a colormap, set the color scale min/max, chosen a time — that styled view lives only inside MMGIS. To reproduce it elsewhere, someone has to hunt down the underlying service URL by hand and manually reconstruct the colormap, rescale, and time parameters, which is tedious and error-prone. The result is that MMGIS layers are effectively trapped in MMGIS.
We want a one-click way to copy a layer's URL out of MMGIS and paste it straight into another GIS tool, reproducing the same layer — same styling, same moment in time — that you see on the map right now.
How it should work
{z}/{x}/{y}tile placeholders stay intact (GIS clients need those), but everything else is resolved — the active colormap, the current color-scale min/max, the selected time, and the full service/base URL are all baked in.Done when
{z}/{x}/{y}but has the colormap, color-scale min/max, time, and base/service URL all resolved into it.Out of scope
Draft implementation plan — written as of 42b9e0a on 2026-06-18. Rough guide; re-verify against latest code.
Current behavior
src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx(~lines 176–181) and is currently a placeholder with no click handler and no menu items — a clean insertion point. Menu/handler wiring conventions for this component are insrc/essence/Tools/LayerManager/adapters/handlers.ts.L_.layers.data[layerName]); the raw configuredurlcarries scheme prefixes (COG:,stac-collection:,titiler-url:,geodatasets:) and template variables.src/essence/Basics/Layers_/leaflet-tilelayer-middleware.js(getTileUrl(), ~21–105): time placeholders replaced (~67–82), STAC/COG datetime injected (~29–40), COG render params applied (~48).src/essence/Basics/Layers_/cogUrlUtils.ts(applyCogFieldsToUrl(), ~33–60):colormap_name(~47),rescale=<min>,<max>(~52),expression,resampling. UsescurrentCogMin/Max(runtime) overcogMin/Max(config).src/essence/Basics/Layers_/LayerCapturer.js(~15–72) — out of scope here but shares the time-substitution logic.src/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts(~67–92):currentCogColormap,currentCogMin/Max,titilerUrl. Runtime updates flow throughhandlers.tssetColormap()/setRescale().timeconfig (enabled,type,format,start/end); tags{starttime}/{endtime}/{time}/{customtime.N}substituted in both the tile middleware (~67–82) and LayerCapturer; global state insrc/essence/Basics/TimeControl_/TimeControl.js(~270–300).src/essence/Tools/Layers/LayersTool.js(~570–651) — GeoJSON/KML/SHP export and rasterdownloadURLlinks. There is no existing "copy URL"/"share link" anywhere; this is greenfield.Where the change lands & rough plan
LayerLegend.tsx; gate visibility to tile-based layer types.{z}/{x}/{y}while substituting in colormap (colormap_name), rescale (currentCogMin/Max), resolved current time, and the full base/service URL. ReuseapplyCogFieldsToUrl()and the time-substitution logic rather than re-deriving them.currentCogColormap,currentCogMin/Max) so on-screen changes are reflected, falling back to config defaults.{starttime}/{endtime}tags.References
src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx(~176–181) — kebab menusrc/essence/Tools/LayerManager/adapters/handlers.ts— menu/handler wiring conventionssrc/essence/Basics/Layers_/cogUrlUtils.ts(applyCogFieldsToUrl, ~33–60) — colormap/rescale paramssrc/essence/Basics/Layers_/leaflet-tilelayer-middleware.js(getTileUrl, ~21–105) — URL + time resolutionsrc/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts(~67–92) — current vs default styling statesrc/essence/Basics/TimeControl_/TimeControl.js(~270–300) — global time state