Summary
Replace the current Swarm map with a multi-layer pydeck visualization using a CARTO dark basemap. Three composable layers toggled from the sidebar.
Depends on: #23 (theme foundation)
Basemap
No API key required. Use CARTO's free dark tile style:
CARTO_DARK = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
Layer 1 — HeatmapLayer (density)
Show the geographic density of all check-ins as a smooth heatmap. Default layer when many check-ins exist.
pdk.Layer(
"HeatmapLayer",
data=checkins_df,
get_position=["lng", "lat"],
get_weight="visit_count",
radius_pixels=60,
intensity=1.2,
threshold=0.25,
color_range=[
[12, 17, 32, 0], # transparent (cold)
[99, 102, 241, 120], # indigo
[34, 211, 238, 200], # cyan
[244, 114, 182, 255], # pink (hot)
],
)
Layer 2 — ScatterplotLayer (individual venues)
Individual venue dots with tooltip showing venue name and visit count.
pdk.Layer(
"ScatterplotLayer",
data=venues_df,
get_position=["lng", "lat"],
get_color="[99, 102, 241, 200]",
get_radius="radius", # scaled by visit_count
radius_min_pixels=4,
radius_max_pixels=24,
pickable=True,
)
Tooltip: {"text": "{place_name}\n{visit_count} visits"}
Layer 3 — ColumnLayer (3D visit frequency)
3D columns extruded by visit count, best viewed at 45° pitch. Toggle on from a sidebar checkbox.
pdk.Layer(
"ColumnLayer",
data=grid_df, # venues aggregated to a ~100m grid
get_position=["lng", "lat"],
get_elevation="visit_count",
elevation_scale=30,
radius=80,
get_fill_color="[99, 102, 241, 180]",
pickable=True,
auto_highlight=True,
)
Sidebar controls (new)
- Layer selector:
st.radio("Map style", ["Heatmap", "Venues", "3D"])
- Pitch toggle:
st.checkbox("3D view (45° tilt)") — sets ViewState(pitch=45) vs pitch=0
View state
Default: fit to bounding box of all check-ins. Compute center_lat, center_lng, and zoom from the data rather than hardcoding.
Acceptance criteria
Summary
Replace the current Swarm map with a multi-layer pydeck visualization using a CARTO dark basemap. Three composable layers toggled from the sidebar.
Depends on: #23 (theme foundation)
Basemap
No API key required. Use CARTO's free dark tile style:
Layer 1 — HeatmapLayer (density)
Show the geographic density of all check-ins as a smooth heatmap. Default layer when many check-ins exist.
Layer 2 — ScatterplotLayer (individual venues)
Individual venue dots with tooltip showing venue name and visit count.
Tooltip:
{"text": "{place_name}\n{visit_count} visits"}Layer 3 — ColumnLayer (3D visit frequency)
3D columns extruded by visit count, best viewed at 45° pitch. Toggle on from a sidebar checkbox.
Sidebar controls (new)
st.radio("Map style", ["Heatmap", "Venues", "3D"])st.checkbox("3D view (45° tilt)")— setsViewState(pitch=45)vspitch=0View state
Default: fit to bounding box of all check-ins. Compute
center_lat,center_lng, andzoomfrom the data rather than hardcoding.Acceptance criteria
ruff check .,mypy, andpytestall pass