|
| 1 | +--- |
| 2 | +draft: false |
| 3 | +date: 2026-03-13 |
| 4 | +categories: |
| 5 | + - Release |
| 6 | +authors: |
| 7 | + - kylebarron |
| 8 | +links: |
| 9 | + - CHANGELOG.md#0130-2025-11-05 |
| 10 | +--- |
| 11 | + |
| 12 | +# Releasing lonboard 0.15! |
| 13 | + |
| 14 | +Lonboard enables fast, interactive geospatial data visualization in Jupyter. |
| 15 | + |
| 16 | +This post gives an overview of what's new in Lonboard version 0.15. |
| 17 | + |
| 18 | +<!-- more --> |
| 19 | + |
| 20 | +Refer to the [changelog] for all updates. |
| 21 | + |
| 22 | +## New logo! |
| 23 | + |
| 24 | +Lonboard has a new logo! |
| 25 | + |
| 26 | +<img src="../../assets/lonboard-logo.png" width="400" /> |
| 27 | + |
| 28 | +This logo was designed by [Gus Becker], and continues with the pun behind Lonboard: |
| 29 | + |
| 30 | +[Gus Becker]: https://gusbus.space/ |
| 31 | + |
| 32 | +Lonboard connects to the [deck.gl] geospatial data visualization library. A "deck" is the part of a skateboard you ride on. What's a fast, geospatial skateboard? A <em>lon</em>board. |
| 33 | + |
| 34 | +[deck.gl]: https://deck.gl |
| 35 | + |
| 36 | +## Geocoder control |
| 37 | + |
| 38 | +Lonboard introduced [_map controls_][lonboard.controls] in [version 0.14](lonboard-0.14.md) to extend client-side map functionality. Lonboard is now adding support for a [`GeocoderControl`][lonboard.controls.GeocoderControl]! |
| 39 | + |
| 40 | +This allows you to include a drop-down element on the map for easily finding locations of interest on the map. |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +> Screenshot from [Geocoding with GeoPy](../../../../../examples/geocoder-control) example |
| 45 | +
|
| 46 | +To use, create a [`GeocoderControl`][lonboard.controls.GeocoderControl] and add it to your `Map` via the `controls` parameter. |
| 47 | + |
| 48 | +### Using with GeoPy |
| 49 | + |
| 50 | +The `GeocoderControl` has integration with [GeoPy](https://geopy.readthedocs.io/en/stable/), a Python library that [supports many geocoder providers](https://geopy.readthedocs.io/en/stable/#module-geopy.geocoders). |
| 51 | + |
| 52 | +In order to use the GeoPy integration, create a geocoder of your choice in [async mode](https://geopy.readthedocs.io/en/stable/#async-mode). Then pass to [`GeocoderControl.from_geopy`][lonboard.controls.GeocoderControl.from_geopy]. |
| 53 | + |
| 54 | +```py |
| 55 | +from geopy.adapters import AioHTTPAdapter |
| 56 | +from geopy.geocoders import Nominatim |
| 57 | +from lonboard import Map |
| 58 | +from lonboard.controls import GeocoderControl |
| 59 | + |
| 60 | +geocoder = Nominatim(user_agent="lonboard-app", adapter_factory=AioHTTPAdapter) |
| 61 | +geocoder_control = GeocoderControl.from_geopy(geocoder) |
| 62 | +m = Map([], controls=controls) |
| 63 | +``` |
| 64 | + |
| 65 | +### Custom geocoder |
| 66 | + |
| 67 | +The GeoPy integration is provided for easy use, but it's possible to customize the `GeocoderControl` to use _any_ provider you could think of. Just provide an async function that implements the [GeocoderHandler][lonboard.controls.GeocoderHandler] protocol. |
| 68 | + |
| 69 | +```py |
| 70 | +from lonboard import Map |
| 71 | +from lonboard.controls import ( |
| 72 | + GeocoderControl, |
| 73 | + GeocoderFeature, |
| 74 | + GeocoderFeatureCollection, |
| 75 | +) |
| 76 | + |
| 77 | +async def my_custom_geocoder( |
| 78 | + query: str, |
| 79 | +) -> GeocoderFeatureCollection | GeocoderFeature | None: |
| 80 | + # Implement your custom geocoding logic here, e.g. by querying an API. |
| 81 | + # This is just a placeholder implementation that returns a fixed location. |
| 82 | + return { |
| 83 | + "type": "FeatureCollection", |
| 84 | + "features": [ |
| 85 | + { |
| 86 | + "type": "Feature", |
| 87 | + "properties": {}, |
| 88 | + "geometry": { |
| 89 | + "type": "Point", |
| 90 | + "coordinates": (-122.4194, 37.7749), |
| 91 | + }, |
| 92 | + "text": "San Francisco, CA, USA", |
| 93 | + "place_name": "San Francisco, CA, USA", |
| 94 | + "place_type": ["custom-result"], |
| 95 | + "center": (-122.4194, 37.7749), |
| 96 | + }, |
| 97 | + ], |
| 98 | + } |
| 99 | + |
| 100 | +geocoder_control = GeocoderControl(client=my_custom_geocoder) |
| 101 | +m = Map([], controls=[geocoder_control]) |
| 102 | +``` |
| 103 | + |
| 104 | +### Limitations |
| 105 | + |
| 106 | +This integration works by message passing between the browser and Python, using the Jupyter communication mechanism. |
| 107 | + |
| 108 | +When you perform a search in the geocoder UI element on the map, that fires off a request to Python, which routes the query string to the Python async callback. When that callback returns, Lonboard sends the result back to the browser, which displays the available results from the geocoder service. |
| 109 | + |
| 110 | +So all queries are proxied _through Python_. This makes the maintenance of this feature much simpler, because Lonboard doesn't have to connect to any geocoder providers itself. It also means that the end user has full control over which geocoder API they use, and any relevant API keys never leave the Python environment. |
| 111 | + |
| 112 | +The one downside here, is that, for now, if you export a map with a geocoder control to a static HTML file using the [HTML export functionality][lonboard.Map.to_html], the geocoder will no longer function, as there's no running Python service for it to connect to. |
| 113 | + |
| 114 | +## All updates |
| 115 | + |
| 116 | +Refer to the [changelog] for all updates. |
| 117 | + |
| 118 | +[changelog]: ../../CHANGELOG.md/#0150-2026-03-13 |
0 commit comments