<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jupyter Blog - collaboration</title><link href="https://blog.jupyter.org/" rel="alternate"/><link href="https://blog.jupyter.org/feeds/tag-collaboration.atom.xml" rel="self"/><id>https://blog.jupyter.org/</id><updated>2026-08-24T16:09:00+00:00</updated><subtitle>Real-time collaboration, with several people editing the same notebook or document at once.</subtitle><entry><title>JupyterGIS 0.16: New visualization capabilities, collaborative Story Maps, and more</title><link href="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/" rel="alternate"/><published>2026-08-24T16:09:00+00:00</published><updated>2026-08-24T16:09:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:blog.jupyter.org,2026-08-24:/posts/2026/jupytergis-0-16-new-visualization-capabilities/</id><summary type="html">&lt;p&gt;This release adds support for new geospatial formats, tighter integration with the scientific Python ecosystem, a redesigned Story Map editor, and a more expressive way to style geographic data.&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Read this article in Notebook.link, as a live story-map! &lt;a href="https://notebook.link/@martinRenou/jupytergis-announcement"&gt;https://notebook.link/@martinRenou/jupytergis-announcement&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://blog.jupyter.org/posts/2026/expanding-geospatial-workflows-in-jupytergis-stac/"&gt;Earlier this year, we introduced STAC browsing and Story Maps in JupyterGIS&lt;/a&gt;, making it easier to discover geospatial datasets and communicate results without leaving Jupyter.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/geojupyter/jupytergis/releases/tag/v0.16.0"&gt;JupyterGIS 0.16&lt;/a&gt; continues in the same direction. This release adds support for new geospatial formats, tighter integration with the scientific Python ecosystem, a redesigned Story Map editor, and a more expressive way to style geographic data.&lt;/p&gt;
&lt;h2 id="story-maps-are-getting-a-new-look"&gt;Story Maps are getting a new look!&lt;/h2&gt;
&lt;p&gt;Story Maps in JupyterGIS let you build a scrollable presentation around your map. A Story Map is made up of a sequence of segments that can combine Markdown content with map views, so you can guide the reader through a geographic story as they scroll.&lt;/p&gt;
&lt;p&gt;Each segment can define its own map state, including the current map location, visible layers, and layer styling. This means that the map can change as the reader moves through the story: layers can appear or disappear, the view can move to a new location, and symbology can change to highlight different aspects of the data.&lt;/p&gt;
&lt;p&gt;Story Maps have received a significant update in this release.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Read this article in Notebook.link, as a live story-map! &lt;a href="https://notebook.link/@martinRenou/jupytergis-announcement"&gt;https://notebook.link/@martinRenou/jupytergis-announcement&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img alt="The Story-map associated to this release annoucement. It contains Text, images, and map views with associated layer states." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/001-1_gyuKfOzFSbmRhH9LVBTJiA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The Story-map associated to this release annoucement. It contains Text, images, and map views with associated layer states.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="a-better-story-maps-editing-experience"&gt;A better Story Maps editing experience&lt;/h2&gt;
&lt;p&gt;We’ve also made substantial improvements to the Story Map editing experience.&lt;/p&gt;
&lt;p&gt;The editor has been redesigned around Jupyter’s &lt;strong&gt;real-time collaboration infrastructure, allowing multiple people to edit the same Story Map simultaneously&lt;/strong&gt;. Changes appear immediately for everyone, making it much easier to prepare presentations, reports, or educational material as a team.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Collaboratively edit the Story Map markdown." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/002-1_yLMypnIGkeKXrR1BfXgvHg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Collaboratively edit the Story Map markdown.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The editor now gives you a much better sense of what the final story will look like while you are working on it. Markdown sections can be previewed directly in the editor, and a new Story Map preview makes it possible to see the complete presentation without leaving the editing workflow. This makes it easier to write, arrange, and refine a story while keeping an eye on the final result. We’ve also introduced a new layout that is better suited for long-form content. In addition to guided geographic narratives, Story Maps can now be used to create richer articles combining text, maps, images, and other interactive content.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="New Story Map editor: Set story segment viewport, preview markdown, set layers properties for the story segment." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/003-1_1eO0MShCVn71uIhAkC61ZA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;New Story Map editor: Set story segment viewport, preview markdown, set layers properties for the story segment.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="openeo-layers"&gt;OpenEO layers&lt;/h2&gt;
&lt;p&gt;More and more geospatial workflows rely on remote processing instead of downloading datasets locally. openEO provides a common API to describe these processing pipelines as process graphs that are executed by a backend.&lt;/p&gt;
&lt;p&gt;JupyterGIS can now display &lt;strong&gt;openEO&lt;/strong&gt; process graphs directly as map layers. Instead of exporting intermediate results before visualizing them, you can connect an openEO backend and inspect the output of your processing pipeline directly in the map.&lt;/p&gt;
&lt;p&gt;The visualization is tile-based and lazy: JupyterGIS only requests the data needed for the current map view and zoom level. This makes it possible to explore large remote sensing workflows interactively, without materializing the full result locally.&lt;/p&gt;
&lt;p&gt;JupyterGIS can make use of any openEO server that supports tiling, such as &lt;a href="https://sentinel-hub.github.io/titiler-openeo"&gt;titiler-openeo&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openeo&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jupytergis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GISDocument&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openeo.processes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;

&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openeo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticate_basic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BASIC_AUTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BASIC_AUTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;sentinel-2-global-mosaics&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bands&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;B03&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;B08&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;temporal_extent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2022-04-15&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2022-12-31&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce_dimension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;t&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;first&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;

&lt;span class="c1"&gt;# NDWI = (GREEN - NIR) / (GREEN + NIR)&lt;/span&gt;
&lt;span class="n"&gt;ndwi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndvi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ndwi_vis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ndwi&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;ndwi_png&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ndwi_vis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linear_scale_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;input_min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;input_max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ndwi_png&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PNG&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GISDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;40.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mf"&gt;73.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_openeo_tile_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Define a process graph to compute a NDWI, using the Python API of OpenEO and JupyterGIS. It is then lazily evaluated on a per-tile basis while the user pans/zooms on the map." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/004-1_L5MrEnxXuvIkT5rVl0dahw.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Define a process graph to compute a NDWI, using the Python API of OpenEO and JupyterGIS. It is then lazily evaluated on a per-tile basis while the user pans/zooms on the map.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In addition to defining openEO process graphs from the scripting Python API, JupyterGIS provides an advanced openEO process graph editor, allowing you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connect to an openEO tile server&lt;/li&gt;
&lt;li&gt;define the graph graphically, with boxes and arrows&lt;/li&gt;
&lt;li&gt;load data collections and define processes with a drag-and-drop UI&lt;/li&gt;
&lt;li&gt;directly edit the JSON content&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Editing an openEO process graph from the JupyterGIS front-end" src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/005-1_3AGsNcwe384V1P4-ZkzcYw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Editing an openEO process graph from the JupyterGIS front-end&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another interesting aspect of openEO is that process graphs have a well-defined, declarative JSON representation. Because of this structured format, &lt;strong&gt;they are a natural target for LLM-assisted workflows&lt;/strong&gt;. Users can describe the analysis they want in natural language, have an LLM generate or refine the corresponding process graph (e.g. using jupyterlite-ai), and immediately visualize the result in JupyterGIS. Combined with the lazy, tile-based rendering, this makes it possible to quickly iterate on processing pipelines without waiting for complete datasets to be exported or downloaded.&lt;/p&gt;
&lt;h2 id="lazy-visualization-of-xarray-datasets-with-jupyter-tiler"&gt;Lazy visualization of Xarray datasets with jupyter-tiler&lt;/h2&gt;
&lt;p&gt;JupyterGIS now integrates with the new &lt;a href="https://jupyter-tiler.readthedocs.io"&gt;jupyter-tiler&lt;/a&gt; package, making it straightforward to visualize Xarray datasets from Python.&lt;/p&gt;
&lt;p&gt;Datasets can come from anywhere: they may already exist in your notebook, or they can be loaded on demand from a STAC catalog using stackstac. Once you have an Xarray object, JupyterGIS can display it in the map without requiring an export to another format.&lt;/p&gt;
&lt;p&gt;Rendering happens lazily, generating only the tiles needed for the current view. This makes it possible to explore datasets that are much larger than memory while keeping navigation responsive.&lt;/p&gt;
&lt;p&gt;The result is a smoother workflow from data loading, to analysis, to visualization, all within the same notebook.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_data_array_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;NDSI Layer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data_array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ndsi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;colormap_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;viridis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;colormap_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Visualizing an Xarray dataset in JupyterGIS." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/006-1_GsxLjpQu33wvCx8KZxBUWA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Visualizing an Xarray dataset in JupyterGIS.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This feature requires the optional dependency jupyter-tiler to be installed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;jupyter-tiler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="a-more-expressive-symbology-model"&gt;A more expressive symbology model&lt;/h2&gt;
&lt;p&gt;Styling geographic data often requires combining multiple visual properties to communicate patterns effectively.&lt;/p&gt;
&lt;p&gt;JupyterGIS 0.16 introduces a &lt;strong&gt;new symbology model inspired by the Grammar of Graphics.&lt;/strong&gt; Instead of relying on a fixed set of styling options, visual properties such as color, size, and opacity can be defined in a more flexible and composable way.&lt;/p&gt;
&lt;p&gt;This makes it easier to build everything from simple thematic maps to more advanced visualizations while keeping styling definitions consistent and reproducible.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A symbology example: apply a Viridis color map to the circle colors, a linear scale to the radius of circles, and a fixed stroke color." src="https://blog.jupyter.org/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/007-1_SU9Ll713eVozkjVQNQNmMA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A symbology example: apply a Viridis color map to the circle colors, a linear scale to the radius of circles, and a fixed stroke color.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="geozarr-and-geopackage-support"&gt;GeoZarr and GeoPackage support&lt;/h2&gt;
&lt;p&gt;This release also expands the range of formats that JupyterGIS can open directly.&lt;/p&gt;
&lt;p&gt;Support for GeoZarr makes it possible to work with cloud-native multidimensional geospatial datasets, while GeoPackage support improves interoperability with existing GIS software and common data exchange workflows.&lt;/p&gt;
&lt;h2 id="new-collaborative-editing-capabilities"&gt;New Collaborative Editing Capabilities&lt;/h2&gt;
&lt;p&gt;JupyterGIS 0.16 also brings collaborative editing to vector layers. When working on a shared JupyterGIS document, multiple users can now edit the same vector data at the same time.&lt;/p&gt;
&lt;p&gt;Features can be created, moved, and edited collaboratively, with changes synchronized in real time between users. This makes it possible to work together on tasks such as digitizing features, annotating a map, or refining a dataset without having to exchange files or manually merge changes.&lt;/p&gt;
&lt;p&gt;Combined with the collaborative Story Map editor, this makes collaboration a more integral part of JupyterGIS: users can work together on the data itself, and then use the same shared document to explore and communicate their results.&lt;/p&gt;
&lt;h2 id="a-new-r-api"&gt;A new R API&lt;/h2&gt;
&lt;p&gt;JupyterGIS 0.16 also introduces an R client, bringing JupyterGIS to R users through the new &lt;a href="https://github.com/geojupyter/r-jupytergis"&gt;&lt;code&gt;r-jupytergis&lt;/code&gt;&lt;/a&gt; package. The R client provides bindings for interacting with JupyterGIS widgets from an R notebook, using the same JavaScript front-end as the Python client.&lt;/p&gt;
&lt;p&gt;The main interface is the &lt;code&gt;GISDocument&lt;/code&gt; widget, which can be used to create and manipulate JupyterGIS documents directly from R. This makes it possible to build geospatial workflows in R while using the same interactive map interface available to Python users.&lt;/p&gt;
&lt;p&gt;The R client also uses the same underlying collaborative infrastructure as the Python client, including the Yrs CRDT library. This means that R users can participate in the same collaborative JupyterGIS workflows rather than working in a separate environment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GISDocument&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;france_hiking.jGIS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;add_raster_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://mt1.google.com/vt/lyrs=y&amp;amp;x={x}&amp;amp;y={y}&amp;amp;z={z}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Google Satellite&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Google&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;opacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.6&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="bug-fixes-and-performance-improvements"&gt;Bug fixes and performance improvements&lt;/h2&gt;
&lt;p&gt;As usual, this release also includes many smaller improvements throughout the project.&lt;/p&gt;
&lt;p&gt;We’ve fixed a number of bugs, improved performance in several parts of the application, and continued polishing both the user interface and the Python API.&lt;/p&gt;
&lt;p&gt;JupyterGIS continues to evolve as a collaborative GIS environment that fits naturally within the Jupyter ecosystem. Whether your workflow starts from a notebook, a STAC catalog, an openEO backend, or a local dataset, the goal remains the same: make it easier to move between analysis, visualization, and communication without switching tools.&lt;/p&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;This work on JupyterGIS by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; was funded by &lt;a href="https://www.esa.int/"&gt;the European Space Agency (ESA)&lt;/a&gt; for the Story-maps development, the R API, openEO layers support and the collaborative labelling. Additionally, QuantStack was funded by &lt;a href="https://cnes.fr/"&gt;the French National Centre for Space Studies (CNES)&lt;/a&gt; for the lazy visualization of xarray datasets.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="contributors-to-this-release"&gt;Contributors to this release&lt;/h2&gt;
&lt;p&gt;By order of &lt;a href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports"&gt;number of contributions&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/arjxn-py"&gt;&lt;strong&gt;Arjun Verma&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. He worked on the server-side geoprocessing infrastructure and on the openEO editor in the JupyterGIS front-end.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/martinRenou"&gt;&lt;strong&gt;Martin Renou&lt;/strong&gt;&lt;/a&gt; is a Technical Director at QuantStack and a maintainer of JupyterGIS. For this release, Martin coordinated and guided much of the development, and worked on the integration of openEO layers.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/gjmooney"&gt;&lt;strong&gt;Gregory Mooney&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack and a long-time contributor to JupyterGIS. He led much of the work on the new Story Map editor and its collaborative editing capabilities.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/MMesch"&gt;&lt;strong&gt;Matthias Meschede&lt;/strong&gt;&lt;/a&gt; is Chief Operating Officer at QuantStack. He introduced the new Grammar of Graphics-inspired symbology model, bringing a more expressive and composable approach to styling geographic data.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mfisher87"&gt;&lt;strong&gt;Matt Fisher&lt;/strong&gt;&lt;/a&gt; is the Community Manager of &lt;a href="https://github.com/geojupyter"&gt;GeoJupyter&lt;/a&gt;. He contributed to many of the discussions around the release and helped shape several of the design decisions across the project.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nakul-py"&gt;&lt;strong&gt;Nakul Verma&lt;/strong&gt;&lt;/a&gt; is an open-source contributor to JupyterGIS. He contributed numerous bug fixes and improvements throughout the release, and introduced support for Vega expressions in the new symbology system.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/AntoinePrv"&gt;&lt;strong&gt;Antoine Prouvost&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. He led the initial work on the R API for JupyterGIS, building its first skeleton and establishing the foundations for the &lt;code&gt;r-jupytergis&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/SandrineP"&gt;&lt;strong&gt;Sandrine Pataut&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. She worked on bringing many of JupyterGIS’s features to the R API, helping make the new client more complete and useful for R users.&lt;/p&gt;
&lt;p&gt;We are grateful to everyone who contributed code, reviews, ideas, discussions, and feedback to this release. JupyterGIS continues to benefit from an increasingly diverse community of contributors, and we look forward to seeing what comes next!&lt;/p&gt;
</content><category term="collaboration"/><category term="geoscience"/><category term="JupyterGIS"/><category term="releases"/><category term="science"/></entry><entry><title>Collaborative editing for GIS workflows with Jupyter and QGIS</title><link href="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/" rel="alternate"/><published>2025-02-26T18:50:00+00:00</published><updated>2025-07-16T19:41:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:blog.jupyter.org,2025-02-26:/posts/2025/real-time-collaboration-and-collaborative-editing-for/</id><summary type="html">&lt;p&gt;The QGIS open-source project is a cornerstone in the geosciences ecosystem, providing robust tools for spatial data analysis and visualisation.&lt;/p&gt;</summary><content type="html">&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/001-1__WoRjRDGSKbaUY6b4TsndA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;The QGIS open-source project is a cornerstone in the geosciences ecosystem, providing robust tools for spatial data analysis and visualisation. While QGIS excels in empowering researchers and engineers, the evolving landscape of geospatial research demands enhanced collaboration and accessibility, prompting a shift towards web-based technologies.&lt;/p&gt;
&lt;h2 id="collaboration-in-jupyter"&gt;Collaboration in Jupyter&lt;/h2&gt;
&lt;p&gt;Collaboration has long been a key requirement for data science and scientific computing workflows, but Jupyter Notebooks historically lacked built-in real-time collaboration features.&lt;/p&gt;
&lt;p&gt;To bridge this gap, the &lt;a href="https://github.com/jupyterlab/jupyter-collaboration"&gt;&lt;strong&gt;jupyter-collaboration&lt;/strong&gt;&lt;/a&gt; project has focused on integrating multi-user editing capabilities directly into JupyterLab and Jupyter Notebook. This effort builds on foundational work in conflict-free replicated data types (CRDTs), leveraging technologies like &lt;a href="https://github.com/yjs/yjs"&gt;&lt;strong&gt;Yjs&lt;/strong&gt;&lt;/a&gt;, and required integration into the Notebook document model and WebSocket-based architecture.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/0e8IQ76sulI" title="Notebook code suggestions in collaboration mode" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;
&lt;p&gt;Making Notebook code suggestions in collaboration mode with &lt;a href="https://github.com/jupyterlab-contrib/jupyter-suggestions"&gt;https://github.com/jupyterlab-contrib/jupyter-suggestions&lt;/a&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This approach did not only enable collaborative editing of notebooks, but also opened the door for collaboration on other editing UIs. This was done e.g. in &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;&lt;strong&gt;JupyterCAD&lt;/strong&gt;&lt;/a&gt;, a 3D parametric modeler that allows multiple users to collaboratively design and manipulate CAD models within JupyterLab.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Read more about JupyterCAD here &lt;a href="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/"&gt;Announcing JupyterCAD 3.0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Zu0AT6IRA98" title="JupyterCAD suggestions" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;
&lt;p&gt;Collaboration in JupyterCAD&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="introducing-jupytergis"&gt;Introducing JupyterGIS&lt;/h2&gt;
&lt;p&gt;Today, we are excited to announce &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt;, a web-based, collaborative, and extensible interface for GIS, leveraging the JupyterLab application framework and integrating seamlessly with the Jupyter notebook interface.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; provides the following key features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a JupyterLab extension for collaborative editing of geospatial data files: with COG, Shapefile, GeoJSON data source support,&lt;/li&gt;
&lt;li&gt;support for &lt;strong&gt;importing, exporting and collaborating with QGIS files,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;advanced analysis and editing features with an &lt;strong&gt;identify tool&lt;/strong&gt; and a &lt;strong&gt;symbology panel&lt;/strong&gt; approaching what QGIS provides,&lt;/li&gt;
&lt;li&gt;easily &lt;strong&gt;share and deploy GIS projects&lt;/strong&gt; using JupyterLite.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: JupyterGIS is not an official Jupyter subproject.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="gis-features"&gt;GIS features&lt;/h2&gt;
&lt;h3 id="raster-and-vector-layers"&gt;Raster and vector layers&lt;/h3&gt;
&lt;p&gt;JupyterGIS allows you to create multiple types of raster and vector layers, including local or remote GeoTIFFs, GeoJSON, shapefiles, and tile services.&lt;/p&gt;
&lt;p&gt;You can select from a set of pre-defined tile services in our gallery, or you can provide your own source.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/4_voiMm2zPk" title="JupyterGIS: raster and vector layers" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="identify-tool-and-filtering"&gt;Identify tool and filtering&lt;/h3&gt;
&lt;p&gt;Akin to QGIS, we provide an identify tool and filtering capabilities, helping you to inspect your datasource.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Cs500f7eQMA" title="JupyterGIS: identify tool and filtering" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="symbology"&gt;Symbology&lt;/h3&gt;
&lt;p&gt;The symbology of a layer refers to its visual representation on the map, helping you to analyze your data comfortably. JupyterGIS provides a similar feature for its raster and vector layers.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/nyFPZCShyxs" title="JupyterGIS: symbology" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="spatio-temporal-data"&gt;Spatio-temporal data&lt;/h3&gt;
&lt;p&gt;You can easily animate and analyze your spatio-temporal data.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/y6OSPdlW_kU" title="JupyterGIS: spatio-temporal data" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="python-api"&gt;Python API&lt;/h3&gt;
&lt;p&gt;Even though you can do most operations from the UI, JupyterGIS also provides a Python API enabling scripting capabilities, which can be used to process data and operate on JupyterGIS documents programmatically from a Jupyter notebook.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/gUn1JHg1y4Y" title="JupyterGIS: Python API" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id="collaborative-features"&gt;Collaborative features&lt;/h2&gt;
&lt;p&gt;Building upon our previous work to enable collaborative editing in JupyterCAD, we developed a shared document model to support multi-user workflows in JupyterGIS.&lt;/p&gt;
&lt;p&gt;Everything is shared between collaborators, from layers data to symbology and filtering rules.&lt;/p&gt;
&lt;p&gt;We also provide some collaboration features like the ability to see other collaborators’ cursors, follow collaborators’ viewports, add geolocated Google Docs-like comment conversations, and see what layer features collaborators are identifying.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/FzHYYCvWyu0" title="JupyterGIS: collaborative features" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id="try-it"&gt;Try it!&lt;/h2&gt;
&lt;p&gt;You can directly try &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; in your browser, without installing anything, thanks to &lt;a href="https://github.com/jupyterlite/jupyterlite"&gt;JupyterLite&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html?path=france_hiking.jGIS/"&gt;https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;p&gt;Check out the Python API reference and tutorials on how to get started in our documentation:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jupytergis.readthedocs.io/"&gt;https://jupytergis.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;We are excited to welcome new contributors and see the &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; community grow. Here are some exciting developments on our radar for the future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for more data source types.&lt;/li&gt;
&lt;li&gt;Processing tools,&lt;/li&gt;
&lt;li&gt;Support for suggestions by collaborators, similar to the inline suggestions feature of JupyterCAD,&lt;/li&gt;
&lt;li&gt;An improved and more featureful Python API,&lt;/li&gt;
&lt;li&gt;A better coverage of QGIS features.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-can-you-support-our-work"&gt;How can you support our work?&lt;/h2&gt;
&lt;p&gt;Your support is important, if you would like to help us build more exciting tools around JupyterGIS, do not hesitate to contact us &lt;a href="https://jupyter.zulipchat.com/#narrow/channel/471314-geojupyter"&gt;on the public geojupyter Zulip channel!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additionally, you can join us for the bi-weekly GeoJupyter hackathon on Wednesday &lt;a href="https://geojupyter.org/calendar.html"&gt;https://geojupyter.org/calendar.html&lt;/a&gt;&lt;/p&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;This work on JupyterGIS by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and &lt;a href="https://www.simula.no/"&gt;Simula Research Lab&lt;/a&gt; (Simula) &lt;a href="https://blog.jupyter.org/posts/2024/jupytergis/"&gt;was funded by the European Space Agency (ESA) for our proposal “&lt;em&gt;Real-time collaboration and collaborative editing for GIS workflows with Jupyter and QGIS&lt;/em&gt;”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We are also grateful to &lt;a href="https://dse.berkeley.edu"&gt;The Eric and Wendy Schmidt Center for Data Science &amp;amp; Environment (DSE) at UC Berkeley&lt;/a&gt; for funding the work of Matt Fisher on the project.&lt;/p&gt;
&lt;p&gt;Finally, this wouldn’t have been possible without the foundational work on &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;JupyterCAD&lt;/a&gt; initiated by &lt;a href="https://github.com/trungleduc"&gt;Duc Trung Le&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-jupytergis-contributors"&gt;About the JupyterGIS contributors&lt;/h2&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/002-1_FvjrRTQuLq-RcpISEHyB8w.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/meriem-ben-ismail-163042230/"&gt;Meriem Ben Ismail&lt;/a&gt; is a Scientific Software Developer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;. She just completed her Software Engineering degree at &lt;a href="https://insat.rnu.tn"&gt;INSAT&lt;/a&gt; (National Institute of Applied Sciences and Technology in Tunisia) and her six-month internship as an open-source scientific software engineer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/003-1_XiLiEd21JkqLBa_SjgN4gg.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/nicolas-brichet-a26369150/"&gt;Nicolas Brichet&lt;/a&gt; is a Scientific Software Developer at QuantStack. He holds a master’s degree in robotics from the University of Montpellier. Prior to joining Quantstack, Nicolas worked for almost fourteen years in French research institutes (INRAE and CNRS), as software developer for scientific research. He also worked on different parts of the data lifecycle, such as data acquisition, analysis, and storage.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/004-1_wLk7y0bKAluKt1Du2r2MfA.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/david-brochart-4208721/"&gt;David Brochart&lt;/a&gt; is a Technical Director at QuantStack. David used to work in the semiconductor industry as a digital circuit designer, mostly using FPGAs. He studied telecommunications at the French “Telecom Bretagne” engineering school, with major in digital circuit design. David also worked as a researcher in hydrology at Irstea, a French scientific research institute, where he heavily used the Python scientific stack.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/005-1_zPpzRreH5i7dnvg6L9DK_A.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mfisher87"&gt;Matt Fisher&lt;/a&gt; is a Research Software Engineer and Community Manager at &lt;a href="https://dse.berkeley.edu"&gt;Schmidt Center for Data Science &amp;amp; Environment&lt;/a&gt;. Matt is passionate about open science, community-owned software, teaching and learning, accessibility, and inclusion. It is his treasured privilege to support researchers and educators in their missions by working on projects like &lt;a href="https://qgreenland.org"&gt;QGreenland&lt;/a&gt; and &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS!&lt;/a&gt;&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/006-1_J4D8_KdSR60tPA_TVAhURA.jpeg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/annefouilloux/"&gt;Anne Fouilloux&lt;/a&gt;, a Senior Research Engineer, specializes in Open Science, FAIR data, and Big Data analytics. With a PhD in Atmospheric Physics, she has contributed to Pangeo and EOSC (European Open Science Cloud), focusing on data management, Earth system modeling, and scalable computing. A strong advocate for Open Science, she advances data accessibility and interoperability to drive scientific innovation.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/007-1_z2By7q9wyJvunxZNezKHxg.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/gjmooney/"&gt;Greg Mooney&lt;/a&gt; is a Scientific Computing Developer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;. He received a Bachelors degree in Software Engineering from &lt;a href="https://www.asu.edu/"&gt;Arizona State University (ASU)&lt;/a&gt;. Before joining QuantStack, he worked as an Aegis Computer Network Technician, working on the network infrastructure connecting various sensor systems onboard naval vessels.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/008-1_rliFUY5GuF6sqKnjho66EQ.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Technical Director at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and a maintainer of &lt;a href="https://jupyter.org/"&gt;Project Jupyter&lt;/a&gt;. Among other projects Martin is a core team member of the ipywidgets project and maintains many Jupyter widget packages such as &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt;, &lt;a href="https://github.com/bloomberg/ipydatagrid"&gt;ipydatagrid&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/ipygany"&gt;ipygany&lt;/a&gt;, &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt;, and &lt;a href="https://github.com/bqplot/bqplot"&gt;bqplot&lt;/a&gt;. He is a co-creator of the &lt;a href="https://github.com/voila-dashboards/voila/"&gt;Voilà&lt;/a&gt; dashboarding system, and the &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; kernel.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/009-1_0_qw_xXLELz_8gHUB-3JZw.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/arjxn-py"&gt;Arjun Verma&lt;/a&gt; is a Scientific Software Development Intern at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. He is also a final year undergraduate student at Cluster Innovation Centre, University of Delhi. He loves 3D &amp;amp; GIS and also contributes to &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;JupyterCAD&lt;/a&gt; and is one of the maintainers of &lt;a href="https://pybamm.org/"&gt;PyBaMM&lt;/a&gt; where he has also been &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt; contributor and mentor.&lt;/p&gt;
</content><category term="collaboration"/><category term="geoscience"/><category term="JupyterGIS"/><category term="science"/></entry><entry><title>Announcing JupyterCAD 3.0</title><link href="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/" rel="alternate"/><published>2025-02-17T09:38:00+00:00</published><updated>2025-02-17T09:38:00+00:00</updated><author><name>Arjun Verma</name></author><id>tag:blog.jupyter.org,2025-02-17:/posts/2025/announcing-jupytercad-3-0/</id><summary type="html">&lt;p&gt;The latest iteration of the web-based collaborative CAD editor&lt;/p&gt;
</summary><content type="html">&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/001-1_m9xr-RYt-bA0tfE6YwjNMQ.webp" alt="Screenshot of JupyterCAD, showing a model of gear, with an anotation editor opened." loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;We are thrilled to introduce JupyterCAD 3.0, the newest version of the collaborative CAD modeler designed for JupyterLab.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/jupytercad/jupytercad"&gt;JupyterCAD&lt;/a&gt; is an unofficial JupyterLab extension for 3D geometry modeling with collaborative editing support. It is designed to allow multiple people to work on the same file at the same time, and to facilitate discussion and collaboration around the 3D shapes being created.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;JupyterCAD 3.0 represents a significant leap forward in usability and user experience compared to the previous release.&lt;/p&gt;
&lt;h2 id="whats-new-in-jupytercad-30"&gt;What’s new in JupyterCAD 3.0?&lt;/h2&gt;
&lt;h3 id="color-customization"&gt;Color customization&lt;/h3&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/kTePlIUbgik" title="JupyterCAD color customization" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;JupyterCAD 3.0 allows you to customize object colors directly within the application, while we were limited to gray models in earlier versions. Adjust colors easily to suit your design needs or preferences.&lt;/p&gt;
&lt;h3 id="embedded-python-console"&gt;Embedded Python console&lt;/h3&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/eyZmY9jt6GY" title="JupyterCAD embedded console" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;The new embedded Python console offers advanced users direct access to JupyterCAD’s Python API, enabling on-the-fly scripting and automation for power users.&lt;/p&gt;
&lt;h3 id="ux-improvements"&gt;UX improvements&lt;/h3&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/j5ypepW8QxU" title="JupyterCAD Axes Helper" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;The new &lt;strong&gt;AxesHelper&lt;/strong&gt; provides a clear visual reference for coordinate axes, making it easier to navigate and align models in 3D space.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/lxYKdLS62Zw" title="JupyterCAD copy-paste functionality" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;We have also added &lt;strong&gt;copy-paste functionality&lt;/strong&gt; using &lt;strong&gt;Ctrl+C&lt;/strong&gt; and &lt;strong&gt;Ctrl+V&lt;/strong&gt; shortcuts, making it faster and easier to duplicate objects within your models.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Dx13O7adpj8" title="JupyterCAD 3.0 improved toolbar" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;An &lt;strong&gt;improved toolbar&lt;/strong&gt; now includes options to &lt;strong&gt;toggle wireframe&lt;/strong&gt;, &lt;strong&gt;toggle transform controls&lt;/strong&gt;, &lt;strong&gt;toggle clip plane&lt;/strong&gt; and a &lt;strong&gt;toggleable console&lt;/strong&gt;, giving users quick access to essential tools.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/790f6Wc4_Wk" title="JupyterCAD smooth camera tracking" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;JupyterCAD 3.0 also introduces &lt;strong&gt;smooth camera tracking&lt;/strong&gt;, where selecting an object from the object tree triggers a smooth transition of the camera to focus on the selected object, enhancing navigation and model exploration.&lt;/p&gt;
&lt;h3 id="mouse-based-3d-controls"&gt;Mouse-based 3D controls&lt;/h3&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/xMCvxiIglZk" title="JupyterCAD Mouse-based 3D transform controls" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Move or rotate your 3D models effortlessly with &lt;strong&gt;mouse-based controls&lt;/strong&gt; that bring fluidity and precision to model editing and interaction.&lt;/p&gt;
&lt;h3 id="suggestions-support"&gt;Suggestions support&lt;/h3&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Zu0AT6IRA98" title="JupyterCAD suggestions" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;With JupyterCAD 3.0, collaboration becomes even more seamless with suggestions. Collaborators can propose changes to a model, which can be reviewed and applied collaboratively, fostering a dynamic and efficient workflow.&lt;/p&gt;
&lt;h2 id="try-it"&gt;Try it!&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of the JupyterCAD GitHub repository." src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/002-1_DmBkGvfYG37OR0UueGpdag.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;JupyterCAD GitHub repository&lt;/a&gt;, with a link to try JupyterCAD (circled in red) with JupyterLite. This is simply deployed as a static website on “GitHub Pages”.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Explore JupyterCAD 3.0 in action with our &lt;strong&gt;JupyterLite deployment&lt;/strong&gt; — no installation required. Visit us at &lt;a href="https://jupytercad.github.io/JupyterCAD"&gt;jupytercad.github.io/JupyterCAD&lt;/a&gt; and start modeling directly in your browser.&lt;/p&gt;
&lt;h2 id="installing-jupytercad"&gt;Installing JupyterCAD&lt;/h2&gt;
&lt;p&gt;You can easily install JupyterCAD with pip or mamba:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;jupytercad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;mamba&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;conda&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forge&lt;/span&gt; &lt;span class="n"&gt;jupytercad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Additionally, you can install FreeCAD along with the JupyterCAD-FreeCAD plugin to enable support for FCstd files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;mamba&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;conda&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forge&lt;/span&gt; &lt;span class="n"&gt;freecad&lt;/span&gt; &lt;span class="n"&gt;jupytercad&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;freecad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="whats-next"&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;JupyterCAD is evolving rapidly, with some exciting updates just around the corner and others in active development:&lt;/p&gt;
&lt;h3 id="upcoming-features"&gt;Upcoming Features&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enhanced User Experience&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Smoother exploded view&lt;/li&gt;
&lt;li&gt;Support for renaming objects directly from object tree&lt;/li&gt;
&lt;li&gt;Incremental rotation controls for precise adjustments&lt;/li&gt;
&lt;li&gt;Enhanced 3D view settings for better customization.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nested &amp;amp; Refined Side Panel&lt;/strong&gt;: Navigate and organize objects more easily with a refined and nested side panel experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support for more File Formats&lt;/strong&gt;: Broaden compatibility with support for more file formats.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="features-in-development"&gt;Features in Development&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New CAD Operations&lt;/strong&gt;: New tools for operations like &lt;strong&gt;linear&lt;/strong&gt; and &lt;strong&gt;radial patterns&lt;/strong&gt; to expand modeling capabilities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support for measuring distances&lt;/strong&gt;: Tools to measure distances and dimensions directly in the viewport.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved 2D Sketcher&lt;/strong&gt;: Enhanced features to make 2D sketching more intuitive and robust.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;The development of the JupyterCAD open-source project by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; was funded by a grant from &lt;a href="https://ecologie.gouv.fr/direction-generale-laviation-civile-dgac"&gt;DGAC&lt;/a&gt; in the framework of the French “Plan de Relance” (refinanced by &lt;a href="https://next-generation-eu.europa.eu/index_en"&gt;Next generation EU&lt;/a&gt;) as part of a collaboration between &lt;a href="https://www.safran-group.com/companies/safran-aircraft-engines"&gt;Safran Aircraft Engines&lt;/a&gt;, &lt;a href="https://www.inria.fr/en"&gt;INRIA&lt;/a&gt;, and &lt;a href="https://www.akkodis.com/"&gt;Akkodis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We also extend our gratitude to the &lt;a href="https://github.com/jupytercad/JupyterCAD/graphs/contributors"&gt;external contributors&lt;/a&gt; whose efforts and feedback have been instrumental in shaping this release. Your support and collaboration drive the ongoing success of JupyterCAD.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/003-1_4LK5G7er7fRNtT4gbUoWWw.webp" alt="Logo of Safran Aircraft Engines" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;This work was built upon the strong foundation laid by open-source software projects such as &lt;a href="https://threejs.org/"&gt;&lt;strong&gt;Three.js&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://dev.opencascade.org/"&gt;&lt;strong&gt;OpenCascade&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://ocjs.org/"&gt;&lt;strong&gt;OpenCascade.js&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.freecad.org/"&gt;&lt;strong&gt;FreeCAD&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/jupyterlab/jupyterlab"&gt;&lt;strong&gt;JupyterLab&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://github.com/jupyterlite/jupyterlite"&gt;&lt;strong&gt;JupyterLite&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-authors"&gt;About the authors&lt;/h2&gt;
&lt;p&gt;JupyterCAD is an open-source project resulting from &lt;a href="https://github.com/jupytercad/JupyterCAD/graphs/contributors"&gt;contributors&lt;/a&gt;’ collective efforts. Below, we highlight the primary contributors for this release:&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/004-0_lIAP4xLgMI8KptQn.jpg" alt="Portrait of Trung Le" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/trungleduc"&gt;Le Duc Trung&lt;/a&gt; is a Scientific Software Developer at QuantStack. He works on several projects within the Jupyter ecosystem, from the main projects like &lt;a href="https://github.com/jupyterlab/jupyterlab"&gt;JupyterLab&lt;/a&gt;, &lt;a href="https://github.com/voila-dashboards/voila/"&gt;Voilà&lt;/a&gt;, and &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;ipywidgets&lt;/a&gt; to various JupyterLab extensions and widgets.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/005-0_RPV4uLZ7SYZ0_KwH.jpg" alt="Portrait of Martin Renou" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Technical Director at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and a maintainer of &lt;a href="https://jupyter.org/"&gt;Project Jupyter&lt;/a&gt;. Among other projects Martin is a core team member of the ipywidgets project and maintains many Jupyter widget packages such as &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt;, &lt;a href="https://github.com/bloomberg/ipydatagrid"&gt;ipydatagrid&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/ipygany"&gt;ipygany&lt;/a&gt;, &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt;, and &lt;a href="https://github.com/bqplot/bqplot"&gt;bqplot&lt;/a&gt;. He is a co-creator of the &lt;a href="https://github.com/voila-dashboards/voila/"&gt;Voilà&lt;/a&gt; dashboarding system, and the &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; kernel.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2025/announcing-jupytercad-3-0/images/006-1_ne6lm0Wifp81ZLEIB6fxiQ.webp" alt="Portrait of Arjun Verma" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/arjxn-py"&gt;Arjun Verma&lt;/a&gt; is a Scientific Software Development Intern at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. He is also a final year undergraduate student at Cluster Innovation Centre, University of Delhi. He loves 3D &amp;amp; GIS and also contributes to &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; and is one of the maintainers of &lt;a href="https://pybamm.org/"&gt;PyBaMM&lt;/a&gt; where he has also been &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt; contributor and mentor.&lt;/p&gt;
</content><category term="collaboration"/><category term="JupyterCAD"/><category term="releases"/></entry><entry><title>Exploring a Document’s Timeline in JupyterLab</title><link href="https://blog.jupyter.org/posts/2024/exploring-a-documents-timeline-in-jupyterlab/" rel="alternate"/><published>2024-09-13T19:15:00+00:00</published><updated>2024-09-13T19:15:00+00:00</updated><author><name>Meriem Ben Ismail</name></author><id>tag:blog.jupyter.org,2024-09-13:/posts/2024/exploring-a-documents-timeline-in-jupyterlab/</id><summary type="html">&lt;p&gt;Introducing a document timeline component for JupyterLab&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In collaborative environments, keeping track of changes and understanding the evolution of a document is crucial. This is especially true in fields like scientific computing and data science, where multiple contributors work together on complex projects. To address this need, we’re excited to introduce a document timeline component, a new feature that ships with the &lt;a href="https://jupyterlab-realtime-collaboration.readthedocs.io/en/latest/"&gt;Jupyter Collaboration&lt;/a&gt; extension and enhances how teams interact with shared documents.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;timeline component&lt;/strong&gt; is designed to give users control over a document’s history. Positioned as a slider in the JupyterLab status bar, it allows users to navigate through the timeline of a document. You can explore past versions, compare changes over time without altering the original document, and even restore specific versions. This feature is compatible with all types of shared documents within Jupyter, including notebooks, text files, and even third-party document types like &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;&lt;strong&gt;JupyterCAD&lt;/strong&gt;&lt;/a&gt; models.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Exploring the history of a Jupyter Notebook with the timeline component." src="https://blog.jupyter.org/posts/2024/exploring-a-documents-timeline-in-jupyterlab/images/001-1_iGMClCbnpOvUlZ5xoiAASA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Exploring the history of a Jupyter Notebook with the timeline component&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="how-does-it-work"&gt;How Does it Work ?&lt;/h2&gt;
&lt;p&gt;Co-editing of notebooks and other documents was introduced in JupyterLab 3.1 and has been improved and consolidated in subsequent releases. The feature can be enabled by installing the &lt;a href="https://jupyterlab-realtime-collaboration.readthedocs.io/en/latest/"&gt;Jupyter Collaboration&lt;/a&gt; extension, which is built upon the &lt;a href="https://github.com/yjs/yjs"&gt;&lt;strong&gt;Yjs&lt;/strong&gt;&lt;/a&gt; framework, an implementation of CRDTs (Conflict-free Replicated Data Types). An important byproduct enabling real-time collaboration was the introduction of a journal of updates capturing all changes made by collaborators, which we leveraged to implement document timeline navigation.&lt;/p&gt;
&lt;p&gt;Two key changes to Jupyter collaboration underlie the timeline component:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The ability to &lt;em&gt;fork&lt;/em&gt; the document history, which is required to visualize the past state of the document without altering it.&lt;/li&gt;
&lt;li&gt;The support of Undo/Redo operations in the Python implementation of &lt;strong&gt;Yjs&lt;/strong&gt;, &lt;a href="https://jupyter-server.github.io/pycrdt/"&gt;&lt;strong&gt;PyCRDT&lt;/strong&gt;&lt;/a&gt;, through the implementation of an &lt;a href="https://github.com/jupyter-server/pycrdt/blob/main/python/pycrdt/_undo.py"&gt;undo manager&lt;/a&gt;. While this was already available in &lt;strong&gt;Yjs&lt;/strong&gt;, it was missing in &lt;strong&gt;PyCRDT&lt;/strong&gt; until now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you move the slider to go back in time, the first operation that takes place is &lt;strong&gt;forking&lt;/strong&gt; the document. Forking creates a new branch of the document at the selected point in history. This approach ensures that the most recent version of the document remains unaltered while you explore earlier versions. The forked version essentially acts as a sandbox where you can navigate through the document’s history, test out changes, and decide on the best course of action without modifying the main document.&lt;/p&gt;
&lt;p&gt;When you navigate through the document’s timeline using the slider, the undo manager allows you to reverse or reapply any series of changes, stepping back through the document’s history &lt;strong&gt;without&lt;/strong&gt; losing any information. If you decide to move forward again, the undo manager reapplies those changes in the exact order they were originally made, preserving the document’s integrity.&lt;/p&gt;
&lt;p&gt;After reviewing the timeline, you can choose to restore a particular version at a selected timestamp. This restored version becomes the new active state of the document, effectively merging the changes from the forked branch back into the main document.&lt;/p&gt;
&lt;p&gt;The document timeline component in the status bar offers an intuitive, flexible way to manage document history. Users can confidently experiment with different versions of their work, knowing that every action is reversible and that no progress will be lost. Whether you’re refining a piece of code, iterating on a design, or reviewing past contributions, the timeline equips you to iterate efficiently and effectively.&lt;/p&gt;
&lt;h2 id="seamless-integration-with-jupytercad"&gt;Seamless Integration with JupyterCAD&lt;/h2&gt;
&lt;p&gt;The document timeline is not just limited to text-based documents or notebooks. It was designed in a document-agnostic way, allowing its usage for any collaborative document. Consequently, it integrates seamlessly with &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;&lt;strong&gt;JupyterCAD&lt;/strong&gt;&lt;/a&gt;, JupyterLab’s extension for creating and manipulating 3D models. For engineers and designers, this integration is a game-changer.&lt;/p&gt;
&lt;p&gt;In complex engineering projects, design iterations are common, and the ability to track the evolution of a 3D model is crucial. With the document timeline, users can effortlessly navigate through different stages of their design process. If a recent change in the 3D model doesn’t yield the desired results, the document timeline allows you to slide back to a previous version and pick up your work from there.&lt;/p&gt;
&lt;p&gt;By combining the power of &lt;strong&gt;JupyterCAD&lt;/strong&gt; with the document timeline’s history management, a team can achieve a more dynamic and flexible design process, ensuring that every idea is captured and every change is reversible. This integration exemplifies how the Jupyter Collaboration extension is enhancing not just collaborative editing but also specialized workflows in engineering and design.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Exploring the history of a JupyterCAD document with the timeline component." src="https://blog.jupyter.org/posts/2024/exploring-a-documents-timeline-in-jupyterlab/images/002-1_0hhaIizZhuUGbSRCcsuZLA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Exploring the history of a JupyterCAD document with the timeline component&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="a-new-era-of-collaboration-in-jupyter"&gt;A New Era of Collaboration in Jupyter&lt;/h2&gt;
&lt;p&gt;The document timeline is a significant step forward in our ongoing work to make Jupyter a user-friendly platform for collaborative technical computing. By leveraging the advanced capabilities of the &lt;strong&gt;PyCRDT&lt;/strong&gt; &lt;a href="https://github.com/jupyter-server/pycrdt/blob/main/python/pycrdt/_undo.py"&gt;undo manager&lt;/a&gt;, we’ve created a tool that simplifies document history management and enhances the overall collaborative experience.&lt;/p&gt;
&lt;p&gt;As we continue to innovate and expand the Jupyter Collaboration extension, we invite the community to try out the new document timeline feature and share their feedback. Together, we can further refine these tools and ensure that Jupyter remains at the forefront of collaborative computing, empowering users across all disciplines to achieve more.&lt;/p&gt;
&lt;hr&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The development of the document timeline and its integration into the Jupyter Collaboration extension has been a true team effort, made possible by the dedication and expertise of many individuals. Special thanks are extended to the following team members for their invaluable contributions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;David Brochart :&lt;/strong&gt; For their innovative approach to integrating the &lt;a href="https://github.com/jupyter-server/pycrdt/blob/main/python/pycrdt/_undo.py"&gt;undo manager&lt;/a&gt; within &lt;strong&gt;PyCRDT&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Afshin T. Darian :&lt;/strong&gt; For their supervision and feedback, which have been crucial in refining the functionality of the timeline component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duc Trung Le :&lt;/strong&gt; For their expertise in &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;&lt;strong&gt;JupyterCAD&lt;/strong&gt;&lt;/a&gt; and for ensuring that the timeline component seamlessly integrates with 3D model workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/meriem-ben-ismail-163042230/"&gt;Meriem Ben Ismail&lt;/a&gt; just completed her Software Engineering degree at &lt;a href="https://insat.rnu.tn"&gt;INSAT&lt;/a&gt; (National Institute of Applied Sciences and Technology in Tunisia) and her six-month internship as an open-source scientific software engineer at QuantStack.&lt;/p&gt;
</content><category term="collaboration"/><category term="JupyterCAD"/><category term="JupyterLab"/></entry><entry><title>JupyterGIS</title><link href="https://blog.jupyter.org/posts/2024/jupytergis/" rel="alternate"/><published>2024-06-12T17:09:00+00:00</published><updated>2024-06-12T17:09:00+00:00</updated><author><name>Sylvain Corlay</name></author><id>tag:blog.jupyter.org,2024-06-12:/posts/2024/jupytergis/</id><summary type="html">&lt;p&gt;Pioneering Web-based, Collaborative, and Open-source GIS Tools&lt;/p&gt;
</summary><content type="html">&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2024/jupytergis/images/001-1_IkYCf2cbk3SaxaROQ0eUsA.webp" alt="The logo of Project Jupyter next to a stylised terrestrial globe" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;We are thrilled to announce that the European Space Agency (ESA) is funding our proposal “&lt;em&gt;Real-time collaboration and collaborative editing for GIS workflows with Jupyter and QGIS&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;The consortium spearheading this project comprises &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and &lt;a href="https://www.simula.no/"&gt;Simula Research Lab&lt;/a&gt; (Simula), two organizations with a long history of contributions to the Jupyter project and the broader open-source scientific computing ecosystem.&lt;/p&gt;
&lt;p&gt;The goal of the project is to build solid foundations for a versatile web-based user interface for Geographic Information Systems (GIS) workflows. It will comprise several components, including a JupyterLab extension for collaboratively editing QGIS project files and the integration of these APIs in the Jupyter Notebook. We will then explore integration with platforms like the &lt;a href="https://dataspace.copernicus.eu/"&gt;Copernicus Data Space Ecosystem&lt;/a&gt; (CDSE) and the &lt;a href="https://eosc.eu/"&gt;European Open Science Cloud&lt;/a&gt; (EOSC).&lt;/p&gt;
&lt;h2 id="collaborative-workflows-in-geosciences"&gt;Collaborative workflows in geosciences&lt;/h2&gt;
&lt;p&gt;Collaborative editing of documents has become an integral part of our digital lives and has made us collectively more productive. Gone are the days of cumbersome email exchanges with documents shuttling back and forth.&lt;/p&gt;
&lt;p&gt;Looking ahead, the potential of co-editing extends far beyond text documents and will apply to all authoring UIs, from CAD to image processing. We think that the shift to collaborative editing will be even more transformative for larger and more complex projects, which are inherently social and require the concerted effort of large teams. Whether you are designing a stadium, a plane, or an ocean liner, you need to coordinate a diverse expertise to build a unified model. In geosciences, it may range from climate modeling to agriculture, ecology, urban planning, and many more areas of expertise. For such endeavors, we must embrace tools favoring collaboration, and this applies to the future web-based user interfaces for geoscience research.&lt;/p&gt;
&lt;p&gt;We have been working on collaborative editing in the core of JupyterLab for the past three years. Our approach is based on the &lt;a href="https://yjs.dev/"&gt;Yjs framework&lt;/a&gt;, an implementation of CRDT data structures (Conflict-free Replicated Data Type). We have learned that since it is so tied to the data model, retrofitting these features into an existing application is considerably more arduous than building the initial data model on the appropriate paradigm from inception. This is why JupyterGIS will be built from the ground up with collaborative editing in mind.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;JupyterGIS will be the first open-source GIS tool to provide collaborative editing features.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Importantly, JupyterGIS is part of a broader mission to enable collaborative workflows in open-source technical computing. The &lt;a href="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/"&gt;JupyterCAD&lt;/a&gt; project, a collaborative CAD modeler, is another example of this endeavor. By sharing knowledge and resources, both JupyterGIS and JupyterCAD will benefit from and contribute to each other’s progress, ultimately driving innovation and productivity in their respective fields.&lt;/p&gt;
&lt;h2 id="from-the-desktop-to-the-web"&gt;From the desktop to the web&lt;/h2&gt;
&lt;p&gt;Advanced authoring tools, including IDEs, CAD modelers, image processing software, and GIS applications, are essential for professionals who rely on them for extended periods. These users have high expectations and demand key features to optimize their productivity and workflow. Among these features are extensibility with plugins, configurable keyboard shortcuts, themability, internationalization, scriptability, a unified settings system, and the ability to operate across multiple browser windows and devices.&lt;/p&gt;
&lt;p&gt;Developing a new application from the ground up that meets all these requirements is a formidable challenge. This is where the JupyterLab application framework proves invaluable. By leveraging this framework, developers can build custom, feature-rich authoring tools that incorporate these essential features from the outset, making it an ideal solution for creating modern, user-centric applications.&lt;/p&gt;
&lt;p&gt;Beyond the pure authoring user interface, for which JupyterLab is a great tool, it is also the &lt;em&gt;perfect&lt;/em&gt; tool for integration with notebook-based workflows. As part of this project, we will develop an advanced Python API to manage JupyterGIS sessions, leveraging Jupyter’s robust display system to incorporate sophisticated GIS features inline in Jupyter notebooks and consoles. This integration will further enhance the capabilities and versatility of our application. This feature will follow the same architecture as that of JupyterCAD for the integration with the notebook user interface.&lt;/p&gt;
&lt;h2 id="real-world-applications"&gt;Real-world applications&lt;/h2&gt;
&lt;p&gt;JupyterGIS is meant to become a &lt;em&gt;general-purpose&lt;/em&gt; tool. However, we will work with teams of practitioners on &lt;em&gt;specific&lt;/em&gt; real-world applications to ensure that it addresses their needs.&lt;/p&gt;
&lt;p&gt;One such project concerns the use of digital and GIS solutions for emergency management. While practitioners involved in emergency management already have experience with such tools, we are convinced that web-based applications built with collaboration in mind from the start can foster improved coordination and collaboration, and therefore the effectiveness of the response.&lt;/p&gt;
&lt;p&gt;Response teams comprise different organizations, including the affected municipalities, police, emergency response organizations like the Red Cross, and advisers such as the U.S. Army Corps of Engineers (USACE) in the United States or the Norwegian Water Resources and Energy Directorate (NVE) in Norway. Even when using the same incident management system, miscommunications and misunderstandings can occur between these stakeholders, resulting in delays or improper use of resources. An improved integration of collaborative GIS software can improve upon the existing tooling.&lt;/p&gt;
&lt;h2 id="building-collaborations-in-europe-and-beyond"&gt;Building collaborations in Europe and beyond&lt;/h2&gt;
&lt;p&gt;We will partner with key practitioners and make sure JupyterGIS addresses their use cases. Integration in the &lt;a href="https://dataspace.copernicus.eu/"&gt;Copernicus Data Space Ecosystem&lt;/a&gt; (CDSE) and the &lt;a href="https://eosc.eu/"&gt;European Open Science Cloud&lt;/a&gt; (EOSC) will be key to the adoption of JupyterGIS and demonstrate its deployment in such environments.&lt;/p&gt;
&lt;p&gt;Beyond Europe, we are currently working on including this project into a broader scope. We are excited to be partnering with the “&lt;a href="https://www.live-env.org/"&gt;LIVE-Env&lt;/a&gt;” project, an open-source initiative spearheaded by Alyssa Goodman at Harvard University. Furthermore, we are establishing a key collaboration with the &lt;a href="https://bids.berkeley.edu/home"&gt;Berkeley Institute for Data Sciences&lt;/a&gt; (BIDS) and the &lt;a href="https://dse.berkeley.edu/"&gt;Schmidt Center for Data Science and Environment&lt;/a&gt; (DSE) at UC Berkeley and &lt;a href="https://2i2c.org/"&gt;2i2c&lt;/a&gt;, with a focus on Jupyter-based geosciences.&lt;/p&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="affiliations"&gt;Affiliations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sylvain Corlay: &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anne Fouilloux: &lt;a href="https://www.simula.no/"&gt;Simula&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Monika Weissschnur: &lt;a href="https://www.simula.no/"&gt;Simula&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><category term="collaboration"/><category term="funding"/><category term="geoscience"/><category term="JupyterGIS"/><category term="science"/></entry><entry><title>Collaborative CAD in JupyterLab</title><link href="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/" rel="alternate"/><published>2023-06-02T15:15:00+00:00</published><updated>2023-06-16T14:55:00+00:00</updated><author><name>Duc Trung Le</name></author><id>tag:blog.jupyter.org,2023-06-02:/posts/2023/collaborative-cad-in-jupyterlab/</id><summary type="html">&lt;p&gt;We are thrilled to introduce JupyterCAD, a tool that integrates Computer-Aided Design (CAD) capabilities into JupyterLab.&lt;/p&gt;</summary><content type="html">&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/001-1_9r3Xz-v5wyuz8aAKY2WV-A.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;We are thrilled to introduce &lt;a href="https://jupytercad.readthedocs.io/"&gt;JupyterCAD&lt;/a&gt;, a tool that integrates &lt;strong&gt;Computer-Aided Design&lt;/strong&gt; (CAD) capabilities into JupyterLab. With its &lt;strong&gt;JupyterLab extension&lt;/strong&gt;, dedicated &lt;strong&gt;JupyterCAD application&lt;/strong&gt;, and &lt;strong&gt;Python API for CAD operations&lt;/strong&gt;, JupyterCAD allows users to effortlessly create, edit and share 3D designs without leaving the Jupyter ecosystem.&lt;/p&gt;
&lt;p&gt;This blog post provides an overview of JupyterCAD’s features and highlights its &lt;strong&gt;collaborative editing capabilities&lt;/strong&gt; which enable teamwork in the realm of CAD.&lt;/p&gt;
&lt;p&gt;Everything that is shown below can be tested by installing JupyterCAD from PyPI:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# From PyPI&lt;/span&gt;
pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;jupytercad
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="one-extension-three-interfaces"&gt;One extension, three interfaces&lt;/h2&gt;
&lt;p&gt;Built using the latest JupyterLab 4 release, JupyterCAD combines CAD functionalities with the &lt;a href="https://blog.jupyter.org/posts/2022/accelerating-jupyterlab/"&gt;enhanced performance&lt;/a&gt; and &lt;a href="https://blog.jupyter.org/posts/2023/improving-the-accessibility-of-jupyter/"&gt;accessibility improvements&lt;/a&gt; introduced in JupyterLab 4. The flexibility of JupyterLab allows us to create the extension once but deploy it in multiple ways to target three groups of audiences: users who prefer working in the JupyterLab environment, users who favor dedicated applications, and those advanced users who do everything programmatically.&lt;/p&gt;
&lt;h3 id="jupyterlab-extension"&gt;JupyterLab Extension&lt;/h3&gt;
&lt;p&gt;Experience CAD features directly within JupyterLab with the JupyterCAD extension. Open and edit &lt;a href="https://www.freecad.org/"&gt;FreeCAD&lt;/a&gt; files, perform CAD operations, including creating 3D primitives, applying boolean operators, and exploding the view. JupyterCAD’s extension integrates seamlessly into JupyterLab, providing an intuitive environment for CAD enthusiasts and data scientists alike.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The integrated interface of JupyterCAD inside JupyterLab" src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/002-1_gnukYLJE43zcmuaEAwCuOA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;JupyterCAD extension inside JupyterLab&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="jupytercad-application"&gt;JupyterCAD Application&lt;/h3&gt;
&lt;p&gt;For a streamlined CAD experience, JupyterCAD offers a dedicated application that eliminates distractions and emphasizes CAD features.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="An interface of the standalone JupyterCAD application" src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/003-1_AcyuVpviiNtSal9Wi4CDYQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The standalone JupyterCAD Application.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Starting the dedicated JupyterCAD application is as simple as starting JupyterLab or Jupyter Notebook:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;jupyter&lt;span class="w"&gt; &lt;/span&gt;cad
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This dedicated application has been built in a similar way to the coming &lt;a href="https://jupyter.org/enhancement-proposals/79-notebook-v7/notebook-v7.html"&gt;Jupyter Notebook 7&lt;/a&gt;. It’s a JupyterLab “remix” built from the ground up using JupyterLab core components and custom extensions. Much like JupyterLab, it offers theming and localization support, and more planned features on the horizon.&lt;/p&gt;
&lt;h3 id="python-api-for-cad-operations"&gt;Python API for CAD Operations&lt;/h3&gt;
&lt;p&gt;Advanced users can unlock the full potential of CAD operations with JupyterCAD’s Python API. JupyterCAD allows users to programmatically visualize, create, and manipulate the shapes from a Jupyter Notebook. For example, one can open a FreeCAD file and start modifying it from the notebook with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jupytercad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CadDocument&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CadDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;example.FCStd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Create a cone, a sphere then cut the cone with the sphere.&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_cone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_sphere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="An animation of using JupyterCAD python API in notebook" src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/004-1_I_XVE0J8vjYne5wnsZ9WuA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Adding object to FreeCAD file from Jupyter Notebook.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;JupyterCAD API also integrates nicely with the &lt;a href="https://github.com/tpaviot/pythonocc-core"&gt;OpenCascade Python API&lt;/a&gt;, providing expanded capabilities for working with shapes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jupytercad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CadDocument&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;# Create a prism shape with OpenCascade&lt;/span&gt;
&lt;span class="n"&gt;prism&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BRepPrimAPI_MakePrism&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CadDocument&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_occ_shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prism&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Visualize OpenCascade shape object with JupyterCAD." src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/005-1_4qvN9PdUYf5-jq5rjYUAEQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Visualize OpenCascade shape object with JupyterCAD.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="unlocking-teamwork-with-real-time-collaboration"&gt;Unlocking teamwork with real-time collaboration&lt;/h2&gt;
&lt;h3 id="collaborative-editing"&gt;Collaborative Editing&lt;/h3&gt;
&lt;p&gt;One of the standout features of JupyterCAD is its shared editing functionality, which seamlessly &lt;strong&gt;connects users across different interfaces within the JupyterCAD ecosystem&lt;/strong&gt;. Whether collaborators are using the dedicated JupyterCAD application, the JupyterLab extension, or working with the Python API in a Notebook, any changes made to a shared document are instantly reflected for all users.&lt;/p&gt;
&lt;p&gt;Real-time collaboration allows individuals working in the Python API to make modifications to the CAD document, while simultaneously providing a synchronized view for collaborators using the JupyterLab extension or the JupyterCAD application. This ensures that all participants have access to the most up-to-date version of the design, fostering efficient communication and &lt;strong&gt;eliminating the need for manual synchronization or file exchange&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Real-time collaborative editing in JupyterCAD" src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/006-1_4lDSgoYLrUqX7SQul_yXxw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Real-time collaborative editing in JupyterCAD.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="follow-mode"&gt;Follow Mode&lt;/h3&gt;
&lt;p&gt;With JupyterCAD’s follow-mode feature, collaboration becomes even more fluid. You can follow another user’s camera movements and view adjustments in real-time. This mode allows you to gain insights into the design process, and enhance communication among team members.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Follow Mode in action." src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/007-1_DgAD-S5mvLOEK6RtDM8GZA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Follow Mode in action.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="annotations-system"&gt;Annotations System&lt;/h3&gt;
&lt;p&gt;The annotations system in JupyterCAD adds an interactive layer to 3D designs. Now you can add annotations to specific shapes within a CAD file, give context, provide feedback, or write instructions.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Adding annotation at precise positions" src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/008-1_QD98Lrlr7_CJfgVbxHhf6w.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Adding annotation at precise positions&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr&gt;
&lt;h2 id="what-goes-on-under-the-hood"&gt;What goes on under the hood?&lt;/h2&gt;
&lt;p&gt;All the above features are made possible thanks to two major open-source components: &lt;a href="https://ocjs.org/"&gt;&lt;strong&gt;OpenCascade.js&lt;/strong&gt;&lt;/a&gt;, the WebAssembly build of OpenCascade, and &lt;a href="https://github.com/jupyterlab/jupyter_collaboration"&gt;&lt;strong&gt;jupyter_collaboration&lt;/strong&gt;&lt;/a&gt;, the real-time collaboration framework of JupyterLab.&lt;/p&gt;
&lt;h3 id="in-browser-geometric-modeling-kernel"&gt;In-browser geometric modeling kernel&lt;/h3&gt;
&lt;p&gt;To execute all geometric operations, JupyterCAD uses a custom build of &lt;strong&gt;OpenCascade.js,&lt;/strong&gt; which is a port of the OpenCascade library to JavaScript and WebAssembly via Emscripten. Running on a separate thread, the CAD Kernel of JupyterCAD allows users to perform complex operations at near-native speed. It also helps to lower the load of the server while serving JupyterCAD to many users.&lt;/p&gt;
&lt;h3 id="jupyterlab-real-time-collaboration-framework"&gt;JupyterLab Real-Time Collaboration framework&lt;/h3&gt;
&lt;p&gt;In JupyterLab 4, Real-Time Collaboration (RTC) is not only about editing notebooks but it has become a framework for building collaborative applications. Using the components of &lt;strong&gt;jupyter_collaboration&lt;/strong&gt; helps us accelerate the development of the RTC features in JupyterCAD. Collaborative Editing is built upon a shared data model where &lt;strong&gt;jupyter_collaboration&lt;/strong&gt; handles all the transportation and conflict resolution, while Follow Mode makes use of Awareness, a lightweight notification system provided by the library.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="future-work"&gt;Future work&lt;/h2&gt;
&lt;p&gt;The current state of JupyterCAD illustrates the capabilities of JupyterLab as a foundation to build complex applications, not just for scientific computing but also for more general technical computing applications.&lt;/p&gt;
&lt;p&gt;We will continue to improve JupyterCAD on two axes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enhancing the 3D viewer with features to help users interact with the objects&lt;/li&gt;
&lt;li&gt;Enriching the Python API to improve interoperability with other CAD libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We plan on upstreaming some of the features of JupyterCAD, like the annotations system and the Follow Mode, to jupyter_collaboration to enable it in other file contexts in JupyterLab (Notebooks, text files, etc).&lt;/p&gt;
&lt;p&gt;User feedback from the community also plays a big role in the project roadmap. Try JupyterCAD and share your feedback with us using the project’s &lt;a href="https://github.com/QuantStack/jupytercad/issues"&gt;GitHub issues&lt;/a&gt;!&lt;/p&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
&lt;h2 id="about-the-authors"&gt;About the Authors&lt;/h2&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/009-0_3Y8y-PCaP2B9a6de.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/trungleduc"&gt;Le Duc Trung&lt;/a&gt; is a Scientific Software Developer at QuantStack. He works on several projects within the Jupyter ecosystem, from the main projects like JupyterLab, Voilà, and ipywidgets to various JupyterLab extensions and widgets.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2023/collaborative-cad-in-jupyterlab/images/010-0_A1jOuQ60SPZ_NTVv.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Technical Director at &lt;a href="https://quantstack.net/"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt; and a maintainer of &lt;a href="https://jupyter.org/"&gt;&lt;strong&gt;Project Jupyter&lt;/strong&gt;&lt;/a&gt;. Among other projects Martin is a core team member of the ipywidgets project and maintains many Jupyter widget packages such as &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt;, &lt;a href="https://github.com/bloomberg/ipydatagrid"&gt;ipydatagrid&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/ipygany"&gt;ipygany&lt;/a&gt;, &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt;, and &lt;a href="https://github.com/bqplot/bqplot"&gt;bqplot&lt;/a&gt;. He is a co-creator of the &lt;a href="https://github.com/voila-dashboards/voila/"&gt;Voilà&lt;/a&gt; dashboarding system, and the &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; kernel.&lt;/p&gt;
</content><category term="collaboration"/><category term="JupyterCAD"/><category term="JupyterLab"/></entry><entry><title>How we made Jupyter Notebooks collaborative with Yjs</title><link href="https://blog.jupyter.org/posts/2021/how-we-made-jupyter-notebooks-collaborative-with-yjs/" rel="alternate"/><published>2021-06-04T18:46:00+00:00</published><updated>2021-06-11T12:41:00+00:00</updated><author><name>Kevin Jahns</name></author><id>tag:blog.jupyter.org,2021-06-04:/posts/2021/how-we-made-jupyter-notebooks-collaborative-with-yjs/</id><summary type="html">&lt;p&gt;Collaborative editing — à la Google Docs — is a feature that you still rarely find in applications. One of the few good things that came out of this pandemic is that more people seem to care about making their applications fit for remote collaboration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Collaborative editing — &lt;em&gt;à la&lt;/em&gt; Google Docs — is a feature that you still rarely find in applications. One of the few good things that came out of this pandemic is that more people seem to care about making their applications fit for remote collaboration. Of course, they always cared about real-time collaboration. It’s just a very hard feature to add to your application. It took the Jupyter project several years to land this feature. Finally, they ended up with a solution that is based on the &lt;a href="https://github.com/yjs/yjs"&gt;Yjs Framework&lt;/a&gt; which I authored. This article gives an overview of all the work that was put into Jupyter Notebooks and finally describes how we want to make even more components collaborative.&lt;/p&gt;
&lt;p&gt;Jupyter Notebooks &lt;a href="https://www.techrepublic.com/article/jupyter-has-revolutionized-data-science-and-it-started-with-a-chance-meeting-between-two-students/"&gt;started&lt;/a&gt; in 2011 (back then IPython Notebook) as an effort to make data science reproducible and more accessible by visualizing data dynamically in a notebook. Basically, it allows you to write markdown and code directly in a document. The code can be executed interactively directly from the notebook and shows the result immediately below the code. This is great for data scientists that want to share their research with others. But it’s also a great tool for learning programming because it doesn’t require setting up a programming environment.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2021/how-we-made-jupyter-notebooks-collaborative-with-yjs/images/001-0_HvwrxmA_sBtU0SaO.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Right from the beginning, collaborative editing was on the agenda for Jupyter Notebooks. In 2012, core Jupyter contributor and creator/lead of JupyterHub, @minrk, wrote in the GitHub issue tracker:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] This will finally make decent live collaboration feasible, which is our &lt;strong&gt;single most-requested and highest-priority new feature.&lt;/strong&gt; &lt;a href="https://github.com/ipython/ipython/issues/977#issuecomment-5559489"&gt;(source)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Back then, everyone tried to replicate Google Docs’ collaborative editing functionality. Google Docs was released in 2006 and was the first web application that supported collaborative editing on rich text. In many ways, Google Docs was ahead of its time. It will take years for others to reproduce this functionality. Even today, collaborative editing is far from being ubiquitously available, even though the technology has been available since the ‘80s.&lt;/p&gt;
&lt;p&gt;No wonder, that the first collaborative Jupyter Notebook implementation, &lt;a href="https://github.com/jupyter/colaboratory"&gt;Colaboratory&lt;/a&gt; (or &lt;a href="https://colab.research.google.com"&gt;Colab&lt;/a&gt;), was created by Google engineers. They rewrote the UI for Jupyter Notebooks and gave it a collaborative notebook model via Google’s Realtime API, which was &lt;a href="https://developers.google.com/realtime/deprecation"&gt;deprecated in 2017&lt;/a&gt;. This history underscores how challenging it is to build real-time collaboration into applications: when the Google Realtime API was deprecated, Colab lost its real-time collaboration capabilities, a gap which continues to this day.&lt;/p&gt;
&lt;p&gt;In 2013 William Stein launched &lt;a href="https://cocalc.com/"&gt;CoCalc&lt;/a&gt;, a Jupyter notebook service with collaborative editing support right from the beginning. Like Colaboratory, CoCalc wrote a new UI for Jupyter Notebooks, while reusing other parts of the Jupyter architecture. They made different choices and implemented a custom solution for conflict resolution. I highly recommend watching the below talk where William Stein shared his experience about the state-of-the-art solutions for shared editing back then.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/bjAE82dyDZ8" title="Real-time collaboration with Jupyter notebooks using CoCalc- William Stein (SageMath, Inc)" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;
&lt;p&gt;Exploration of different solutions for collaborative editing by CoCalc.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Still, the open-source JupyterLab project didn’t include collaborative editing. What follows is &lt;a href="https://github.com/ipython/ipython/issues/7784#issuecomment-74533054"&gt;a series of discussions&lt;/a&gt; about the best shared-editing solution to integrate into Jupyterlab to make collaborative editing available to the users of the open-source project. In 2017 Brian Granger, Chris Colbert, and Ian Rose shared their work that integrated the Google Realtime API into the existing JupyterLab project, where they showed &lt;a href="https://www.youtube.com/watch?v=dSjvK-Z3o3U"&gt;an awesome demo&lt;/a&gt; of what collaborative editing could become.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/dSjvK-Z3o3U" title="Brian Granger, Chris Colbert &amp;amp; Ian Rose - JupyterLab+Real Time Collaboration" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;During my research, I found several PRs by Ian Rose that separated the view (how the Jupyter editor is rendered) from the model (how the data is represented). I haven’t talked to him, but I assume what he found is that it is helpful to have observable data structures that can be synced using some framework for conflict resolution. In this case, he just happened to use the Google Realtime API for synchronization. His work included the abstract factory &lt;a href="https://github.com/jupyterlab/jupyterlab/blob/dbdefed9db9332381fe4104bdf53ec314451951f/packages/observables/src/modeldb.ts"&gt;IModelDB&lt;/a&gt; for creating observable data structures that are used to this day. In theory, one just needs to implement the IModelDB interface with observable data structures that synchronize automatically through some real-time API.&lt;/p&gt;
&lt;p&gt;But the provided solution was still based on a proprietary API that requires you to hand over your data to Google services. So the Jupyter community was looking into implementing their own solution for conflict resolution. Different people started to explore Concurrent Replicated Data Types (“CRDTs”) for automatic conflict resolution on their observable data structures. This technology has become very popular in recent years as a solution to synchronize data that can be manipulated by many peers at the same time. If you are interested in the topic, I recommend reading some introductory material on &lt;a href="https://crdt.tech/"&gt;https://crdt.tech/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lumino (formerly PhosphorJS) is a JS toolkit that underlies the JupyterLab IDE, by providing a rich toolkit of widgets, layouts, events, data structures, and a plugin system at the foundation of the JupyterLab extension system. Specifically for our use-case, it provides observable data structures that are used as a model for all Jupyter packages. In 2017, Chris Colbert started the ambitious endeavor to build high-performance CRDT data structures that can be used as an observable data model. In theory, we could have used that to make any application, that is based on Jupyter data structures, collaborative. Although the Lumino CRDT is little known, to this day it remains the second-fastest CRDT implementation that works on the web.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyterlab/lumino/blob/8726968af142e44ca61ba28ab5f9f6911f34ee3f/datastore-benchmarks/results.md"&gt;jupyterlab/lumino&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In 2019, Vidar Tonaas Fauske, Ian Rose, and Saul Shanabrook started work to integrate the Lumino CRDT into JupyterLab. Their work lived for a time in &lt;a href="https://github.com/jupyterlab/jupyterlab/pull/6871"&gt;JupyterLab#6871&lt;/a&gt; and has later been moved to a separate repository &lt;a href="https://github.com/jupyterlab/rtc/"&gt;JupyterLab/rtc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is basically where I come in. While the Lumino CRDT is pretty awesome, in 2020 Brian Granger created a &lt;a href="https://github.com/jupyterlab/lumino/pull/78"&gt;Lumino CRDT performance benchmark&lt;/a&gt; that revealed critical performance and algorithm issues (such as the so-called &lt;a href="https://dl.acm.org/doi/10.1145/3301419.3323972"&gt;interleaving anomoly&lt;/a&gt;). In the process, Brian discovered my CRDT implementation Yjs and the two of us began to discuss CRDT implementations and Yjs in particular.&lt;/p&gt;
&lt;p&gt;To add collaborative editing functionality rivaling Google Docs, we need a bunch of features aside from automatic conflict resolution. For example, we expect that we never revert changes from other users when we hit the undo button. So we need a selective undo-manager that somehow ignores changes from remote users. Something like this is really hard to implement correctly on top of a CRDT.&lt;/p&gt;
&lt;p&gt;Brian eventually asked me to work with &lt;a href="https://twitter.com/quantstack"&gt;QuantStack&lt;/a&gt; to bring collaborative editing to JupyterLab. Yjs has ready-to-use solutions for most problems related to building collaborative applications and is the only CRDT implementation that beats the Lumino CRDT in performance.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/yjs/yjs"&gt;yjs/yjs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I heard that JupyterLab was pushing for collaborative editing for 8 years, I was determined to produce results as fast as possible. I appreciate all the work that came before me because the codebase was already clearly separating the view from the model. My work was just to exchange the existing observable data structures with Yjs’ shared types (which is a fairly similar concept). After one month of work, I was able to produce the first prototype.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyterlab/jupyterlab/pull/9785"&gt;[WIP] Collaborative editing using Yjs by dmonad · Pull Request #9785 · jupyterlab/jupyterlab&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But there was a problem. Another group, led by Eric Charles, also acquired funding to work on collaborative editing and they chose another approach. While I simply replaced the existing observable data structures, they were trying to reuse the existing data structures. I wanted to make full use of Yjs’ features and didn’t want to build extra abstraction layers just to be able to switch to another CRDT implementation. For some time, it seemed we could not reconcile our approaches.&lt;/p&gt;
&lt;p&gt;After many discussions with Eric, we finally came up with a compromise that I’m now really excited about. Yjs and ModelDB only provide raw data structures to build collaborative applications. Our plan was to build a notebook model with an easy-to-use API to manipulate, observe, and synchronize changes on the notebook. This would make it possible for other applications to keep compatibility with JupyterLab without forking the whole JupyterLab repository. My hope is that other notebook-related products like CoCalc or VSCode will eventually use this collaborative model to provide cross-compatibility with other Jupyter services. Everything collaborative, of course.&lt;/p&gt;
&lt;p&gt;Since February Eric Charles, Carlos Herrero, Jeremy Tuloup, and I have been working on designing and integrating this collaborative model into JupyterLab. Others can use the &lt;a href="https://www.npmjs.com/package/@jupyterlab/shared-models"&gt;@jupyterlab/shared-models&lt;/a&gt; package from the npm registry to build their own interfaces for Jupyter Notebooks using the same shared editing technology. Our changes have finally been merged into JupyterLab and are already available in the alpha releases of JupyterLab v3.1.0. Simply start JupyterLab with the &lt;code&gt;--collaborative&lt;/code&gt; flag to enable collaborative editing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://x.com/ProjectJupyter"&gt;@ProjectJupyter&lt;/a&gt; is collaborative! JupyterLab just merged our collaborative-editing branch that &lt;a href="https://x.com/echarles"&gt;@echarles&lt;/a&gt; @CarlosHerreroB &lt;a href="https://x.com/jtpio"&gt;@jtpio&lt;/a&gt; and me have been working on.&lt;a href="https://t.co/7Tm0WXnfkS"&gt;https://t.co/7Tm0WXnfkS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— &lt;a href="https://x.com/kevin_jahns"&gt;Kevin Jahns (@kevin_jahns)&lt;/a&gt;, &lt;a href="https://x.com/kevin_jahns/status/1391766296937832453"&gt;May 10, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Making the separation between model and shared data structure has been quite a revelation for me. Yjs’ shared types are very powerful and allow you to make any kind of application collaborative. But shared models that define an application-specific API make it easier for developers to manipulate the data without understanding how the data is represented in the CRDT. This is particularly relevant because CRDT implementations are almost always schemaless (&lt;a href="https://www.inkandswitch.com/cambria.html"&gt;Cambria&lt;/a&gt; being the exception). A well-maintained model could ensure that the model is compatible with previous versions. In the future, I want to define more shared models for things that are not trivial to represent in Yjs like calendars, contacts, drawings, and graphs.&lt;/p&gt;
&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;
&lt;p&gt;I’m currently working with &lt;a href="https://bartoszsypytkowski.com/"&gt;Bartosz Sypytkowski&lt;/a&gt; on a Rust implementation of Yjs. The Rust implementation will be the baseline for all other ports of the Yjs CRDT to other languages. Thanks to Pierre-Olivier Simonard and &lt;a href="https://github.com/PyO3/pyo3"&gt;PyO3&lt;/a&gt; we already have the template to create language bindings from the Yrs CRDT to a Python package “y-py”. In the coming months, we will implement a Python CRDT that is fully compatible with the web-based CRDT that is used in JupyterLab. This will allow for backends and frontends to efficiently exchange data that can be manipulated simultaneously.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/yjs/y-crdt"&gt;yjs/y-crdt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, we still send HTTP PUT requests to save a document to the file system via the Jupyter Server. Once we have the Yjs CRDT working in Python, we will create a Python implementation of the shared notebook model which will allow the Jupyter Server to directly access the collaborative state and synchronize that with the file system. Moreover, this will finally resolve a long-awaited issue that allows the kernel to write the output directly to the notebook without first connecting to a client. Why is that important? This will enable you to run a notebook and then close the browser to run your computations overnight. The kernel will compute the output in the background, and write it to the shared model which is then saved to the filesystem by Jupyter Server.&lt;/p&gt;
&lt;p&gt;We want to provide more than a collaborative text editing experience. Yjs provides the data structures to make any kind of application collaborative. Users of Yjs use it to build collaborative drawing-, and diagraming- solutions. &lt;a href="https://relm.us/"&gt;Relm.us&lt;/a&gt;, for example, uses the collaborative data structures that Yjs provides for modeling a 3D world that thousands of users can visit to work together. We are exploring heavily how we can make Jupyter widgets collaborative using the same technology.&lt;/p&gt;
&lt;p&gt;Carlos Herrero is working on a &lt;a href="https://github.com/QuantStack/jupyterlab-drawio"&gt;drawio widget&lt;/a&gt; for JupyterLab that automatically synchronizes using a custom shared model that he developed. We want to produce documentation on how you can create custom collaborative widgets for JupyterLab. Jupyter widgets will be able to leverage the rich ecosystem of the Yjs CRDT to create widgets. You want, for example, to add a WYSIWYG rich-text editor widget? Sure, just add the awesome &lt;a href="https://www.tiptap.dev/"&gt;TipTap editor&lt;/a&gt; to your widget, as it already uses Yjs as the default shared editing technology.&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;img src="https://blog.jupyter.org/posts/2021/how-we-made-jupyter-notebooks-collaborative-with-yjs/images/002-1_BBSKYgAom2NJoQLvOwyJLg.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Jeremy Tuloup is working on a WASM-powered JupyterLab distribution that I’m particularly excited about. &lt;a href="https://github.com/jtpio/jupyterlite"&gt;JupyterLite&lt;/a&gt; runs entirely in the browser using only static assets. The code cells are executed using a WebAssembly-based Python runtime. This is already awesome mad science. Now he integrated our collaborative editing approach but uses WebRTC to synchronize peers without the need to set up a central server for conflict resolution. This gives you an offline-ready, collaborative editing experience without setting up any server. Pretty cool!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Real time collaboration in JupyterLite coming soon: &lt;a href="https://t.co/rbEvEPMv17"&gt;https://t.co/rbEvEPMv17&lt;/a&gt;&lt;/p&gt;
&lt;p class="standalone-image"&gt;&lt;a href="https://x.com/jtpio/status/1398390350989889537"&gt;&lt;img src="https://blog.jupyter.org/posts/2021/how-we-made-jupyter-notebooks-collaborative-with-yjs/images/003-Q9a7WbZP3-6tQUoJ.jpg" alt="Video" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— &lt;a href="https://x.com/jtpio"&gt;Jeremy Tuloup (@jtpio)&lt;/a&gt;, &lt;a href="https://x.com/jtpio/status/1398390350989889537"&gt;May 28, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I hope this got you excited about the future of Jupyter. For sure, I am.&lt;/p&gt;
&lt;p&gt;At last, I hope we can appreciate the amazing open-source work that so many people put into this project. I’m looking forward to a future where people take collaborative editing for granted. It has been a rough road and we all needed to learn our lessons to arrive at a solution that works.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Funding acknowledgement: My work on this effort at QuantStack has been funded by Schmidt Futures and the Alfred P. Sloan Foundation through grants to Cal Poly San Luis Obispo.&lt;/em&gt;&lt;/p&gt;
&lt;div class="main-content-end" aria-hidden="true"&gt;&lt;/div&gt;
</content><category term="collaboration"/><category term="JupyterLab"/></entry></feed>