Skip to content

Conversation

@chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Jan 20, 2026

Supporting #9944 #9947 #9939

Summary

Added batched rendering toggle and multi-view examples to the basemap-browser for testing interleaved rendering features.

Batched Rendering Toggle

  • UI control to toggle batched rendering (_renderLayersInGroups added in fix(mapbox): MapboxOverlay: render deck layers in batches #9939) for Mapbox and MapLibre examples (default: true)
  • Only shows for mapbox/maplibre when interleaved mode is enabled
  • Allows testing the batched rendering mode for cross-layer extensions

Multi-View Examples

Added multi-view React examples for both Mapbox and MapLibre demonstrating:

  • Minimap with OSM 2D tiles in bottom-right corner
  • Fullscreen orthographic view with text layer overlay showing example name
  • Per-view initial view states (MapView for minimap, OrthographicView for text)
  • Layer filtering to control which layers render in which views
  • Support for both Mapbox (using slot) and MapLibre (using beforeId) interleaved props
Screenshot 2026-01-20 at 12 40 59 PM

Test Plan

  • Tested batched rendering toggle in interleaved mode for Mapbox and MapLibre
  • Verified multi-view examples work in both interleaved and overlaid modes

🤖 Generated with Claude Code


Note

Medium Risk
Touches the demo’s core wiring (state/config generation and renderer mounts) and introduces multi-view + performance/stress paths, which may cause regressions in basemap-specific behavior and view-state syncing, but remains confined to an example app.

Overview
The basemap-browser example is refactored from a fixed set of “examples” into a dimension-driven configuration system (Dimensions -> buildConfig -> Config), with URL-synced state and validation warnings surfaced as an in-map overlay.

It adds new testing capabilities: batched rendering toggle wired to Mapbox/MapLibre’s _renderLayersInGroups, multi-view mode (OSM minimap + orthographic text overlay via views/layerFilter), a Deck.gl-only basemap option (including globe support), plus stress-test point layers with cached binary data and an FPS meter/view-state debug readouts in the control panel.

Renderer plumbing is reorganized under src/renderers/* and the old per-example modules are removed, updating both pure-JS and React mounts to consume the unified Config.

Written by Cursor Bugbot for commit 0623055. This will update automatically on new commits. Configure here.

@coveralls
Copy link

coveralls commented Jan 20, 2026

Coverage Status

coverage: 91.101%. remained the same
when pulling 0623055 on basemap-multiview
into 9d4542b on master.

chrisgervang added a commit that referenced this pull request Jan 20, 2026
…multi-view consistency

When custom views are provided without a view with id 'mapbox', MapboxOverlay
now automatically injects the default 'mapbox' view in overlaid mode, matching
the behavior in interleaved mode (where getViewport() already does this fallback).

This ensures consistent behavior between interleaved and overlaid modes, and
allows users to only specify additional views (like minimap, ortho) without
having to manually include the base map view.

The bug was discovered while implementing multi-view examples in #9946. When
interleaved was false (overlaid mode), the multi-view example did not render
airports/arcs layers because there was no 'mapbox' view for them to render in.
In interleaved mode, the same example worked because getViewport() in deck-utils
falls back to creating a 'mapbox' view when not found in custom views.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@chrisgervang chrisgervang requested a review from zbigg January 23, 2026 17:08
…amples

Added batched rendering toggle:
- UI control to toggle batched rendering (_renderLayersInGroups) for
  Mapbox and MapLibre examples (default: true)
- Only shows for mapbox/maplibre when interleaved mode is enabled
- Allows testing the batched rendering mode for cross-layer extensions

Added multi-view React examples for Mapbox and MapLibre:
- Minimap with OSM 2D tiles in bottom-right corner
- Fullscreen orthographic view with text layer overlay showing example name
- Per-view initial view states (MapView for minimap, OrthographicView for text)
- Layer filtering to control which layers render in which views
- Support for both Mapbox (using slot) and MapLibre (using beforeId)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Add globe toggle for MapLibre examples to enable/disable globe projection
- Add multi-view toggle for Mapbox and MapLibre examples
- Add URL query parameter support to persist configuration state
  (example, interleaved, batched, globe, multiView) across page refreshes
- Update pure JS and React implementations to support dynamic toggle state
- Control panel now saves all settings to URL and restores them on load

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
chrisgervang and others added 2 commits January 29, 2026 22:10
…ystem

Replace example-based architecture with dimension-based approach where users
select independent dimensions (basemap, framework, interleaved, batched, globe,
multiView, stressTest) and buildConfig() computes the configuration.

- Add config/ directory with centralized layer, view, and validation logic
- Rename examples-react/ and examples-pure-js/ to renderers/
- Add deck-only renderer with GlobeView support
- Add view state display in control panel
- Add validation warnings (no auto-correction)
- Support globe + multiView combinations
- Add stress test layer options (10k to 5M points)

Co-Authored-By: Claude (global.anthropic.claude-opus-4-5-20251101-v1:0) <[email protected]>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 6 potential issues.

useEffect(() => {
onConfigChange(config);
setUrlFromDimensions(dimensions);
}, [dimensions, config, onConfigChange]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config object triggers useEffect on every render

High Severity

The config object is created via buildConfig() on every render without memoization, and is then included in the useEffect dependency array. Since config is a new object reference on every render, the effect runs on every render. Combined with the FPS counter updating state on every animation frame, this causes onConfigChange to be called continuously, which schedules map destruction and recreation via setTimeout. The result is the map being constantly destroyed and recreated, making the example unusable.

Additional Locations (1)

Fix in Cursor Fix in Web

}
}, []);

if (!container) return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code and misleading comment in WarningsOverlay

Low Severity

The WarningsOverlay component creates a DOM element and appends it to #map, but never uses it for rendering. The container state is only used as a render gate. The comment says "Use ReactDOM.createPortal equivalent" but the component just renders a fixed-position div directly - it doesn't actually implement a portal. The created warnings-overlay div is orphaned in the DOM.

Fix in Cursor Fix in Web

// OSM tiles only in minimap
if (layer.id === 'osm-tiles') {
return viewportId === 'minimap';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TileLayer sublayers excluded from minimap by filter

Medium Severity

The layer filter checks layer.id === 'osm-tiles' for exact match, but TileLayer is a composite layer whose sublayers (BitmapLayer instances) have IDs like osm-tiles-0-0-0 based on tile coordinates. These sublayers don't match the exact ID check and fall through to the default case, which excludes layers from the minimap viewport. As a result, the OSM tiles intended only for the minimap won't actually render there.

Fix in Cursor Fix in Web

: basemap === 'maplibre'
? {beforeId: 'watername_ocean'}
: {}
: {};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated interleaved props logic across files

Low Severity

The logic to compute interleaved positioning props ({slot: 'middle'} for mapbox, {beforeId: 'watername_ocean'} for maplibre) is duplicated. layers.ts has a getInterleavedProps function, but stress-test.ts reimplements the same logic inline. The buildStressTestLayer function could import and reuse getInterleavedProps instead of duplicating the conditional logic.

Additional Locations (1)

Fix in Cursor Fix in Web

*/
export function clearStressTestCache(): void {
dataCache.clear();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused exported function clearStressTestCache

Low Severity

The clearStressTestCache function is exported from stress-test.ts and re-exported from the config module's index.ts, but it's never called anywhere in the codebase. This is dead code that adds unnecessary API surface area without providing any value.

Additional Locations (1)

Fix in Cursor Fix in Web

// ===== Legacy Types (for migration) =====

/** @deprecated Use Basemap instead */
export type MapType = Basemap;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused deprecated type alias MapType

Low Severity

The MapType type alias is defined as deprecated and marked for migration purposes, but it's never used anywhere in the codebase. Since all code in this PR already uses the new Basemap type, this deprecated alias serves no purpose and can be removed.

Fix in Cursor Fix in Web

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.

5 participants