diff --git a/.github/workflows/python-docs.yml b/.github/workflows/python-docs.yml
new file mode 100644
index 000000000..4355fbfc4
--- /dev/null
+++ b/.github/workflows/python-docs.yml
@@ -0,0 +1,68 @@
+name: Publish Python docs via GitHub Pages
+
+# Only run on new tags starting with `py-v`
+on:
+ push:
+ tags:
+ - 'py-v*'
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Deploy Python core docs
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: python/core/
+ steps:
+ - uses: actions/checkout@v4
+ # We need to additionally fetch the gh-pages branch for mike deploy
+ with:
+ fetch-depth: 0
+
+ - name: Set up Python 3.11
+ id: setup-python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.11"
+
+ - name: Install and configure Poetry
+ uses: snok/install-poetry@v1
+ with:
+ version: 1.7.1
+ virtualenvs-create: true
+ virtualenvs-in-project: true
+ installer-parallel: true
+
+ - name: Load cached venv
+ id: cached-poetry-dependencies
+ uses: actions/cache@v3
+ with:
+ path: .venv
+ key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
+
+ - name: Install dependencies
+ if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
+ run: poetry install --no-interaction --no-root
+
+ - name: Install root project
+ run: poetry install --no-interaction
+
+ - name: Deploy docs
+ env:
+ GIT_COMMITTER_NAME: CI
+ GIT_COMMITTER_EMAIL: ci-bot@example.com
+ run: |
+ # Get most recent git tag
+ # https://stackoverflow.com/a/7261049
+ # https://stackoverflow.com/a/3867811
+ # We don't use {{github.ref_name}} because if triggered manually, it
+ # will be a branch name instead of a tag version.
+ # Then remove `py-` from the tag
+ VERSION=$(git describe --tags --match="py-*" --abbrev=0 | cut -c 4-)
+
+ # Only push docs if no letters in git tag after the first character
+ # (usually the git tag will have v as the first character)
+ if ! echo $VERSION | cut -c 1- | grep -q "[A-Za-z]"; then
+ poetry run mike deploy $VERSION latest --update-aliases --push
+ fi
diff --git a/README.md b/README.md
index efd413aee..ab9aeae81 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,10 @@ This repository also includes [Python bindings](https://github.com/kylebarron/ge
## Documentation
-- Rust library
-- JavaScript library:
-- Rust wasm-bindgen library:
+- [Use from Rust](https://docs.rs/geoarrow2/latest/geoarrow2/)
+- [Use from Python](https://geoarrow.github.io/geoarrow-rs/python/core)
+- [Use from JavaScript](https://geoarrow.github.io/geoarrow-rs/js)
+- [Create your own Rust-JavaScript library with `wasm-bindgen`](https://docs.rs/geoarrow-wasm/latest/geoarrow_wasm/)
## Examples
diff --git a/python/.gitignore b/python/.gitignore
index af3ca5ef1..75304478b 100644
--- a/python/.gitignore
+++ b/python/.gitignore
@@ -1,3 +1,4 @@
+site
/target
# Byte-compiled / optimized / DLL files
@@ -69,4 +70,4 @@ docs/_build/
.vscode/
# Pyenv
-.python-version
\ No newline at end of file
+.python-version
diff --git a/python/core/DEVELOP.md b/python/core/DEVELOP.md
new file mode 100644
index 000000000..c82efc99e
--- /dev/null
+++ b/python/core/DEVELOP.md
@@ -0,0 +1,25 @@
+# Develop Docs
+
+## Docs
+
+View docs:
+
+```
+poetry run mkdocs serve
+```
+
+Deploy docs (automatically):
+
+Push a new tag with the format `py-v*`, such as `py-v0.1.0`.
+
+Deploy docs (manually):
+
+```
+poetry run mike deploy VERSION_TAG --update-aliases --push --deploy-prefix python/core/
+```
+
+This only needs to be run once ever, to set the redirect from `https://geoarrow.github.io/geoarrow-rs/python/core/` to `https://geoarrow.github.io/geoarrow-rs/python/core/latest/`.
+
+```
+poetry run mike set-default latest --deploy-prefix python/core/ --push
+```
diff --git a/python/core/README.md b/python/core/README.md
index 0c1eff938..950dbe963 100644
--- a/python/core/README.md
+++ b/python/core/README.md
@@ -1,5 +1,7 @@
# `geoarrow.rust.core`: Python bindings to `geoarrow-rs`
+## Overview
+
This library contains Python bindings to the [GeoArrow Rust implementation](https://github.com/geoarrow/geoarrow-rs).
- **Fast**: Connects to algorithms implemented in [GeoRust](https://georust.org/), which compile to native code.
@@ -7,7 +9,7 @@ This library contains Python bindings to the [GeoArrow Rust implementation](http
- **Self-contained**: Zero Python dependencies.
- **Easy to install**: Distributed as static binary wheels with zero C dependencies.
- **Strong, static typing**: geometry arrays have a known type
-- **Interoperable ecosystem**: Data can be shared at zero cost with other libraries in the burgeoning [GeoArrow ecosystem](https://geoarrow.org/), such as [geoarrow-c](https://github.com/geoarrow/geoarrow-c/tree/main/python) or [lightning-fast map rendering](https://github.com/developmentseed/lonboard).
+- **Interoperable ecosystem**: Data is shared at zero cost with other Python libraries in the burgeoning [GeoArrow ecosystem](https://geoarrow.org/), such as [geoarrow-c](https://github.com/geoarrow/geoarrow-c/tree/main/python) or [lightning-fast map rendering](https://github.com/developmentseed/lonboard).
More specifically, it contains:
@@ -17,9 +19,15 @@ More specifically, it contains:
- Rust-based algorithms for computations on GeoArrow memory.
- Rust-based parsers for various geospatial file formats.
-Future work:
+## Documentation
+
+Refer to the documentation at [geoarrow.github.io/geoarrow-rs/python/core](https://geoarrow.github.io/geoarrow-rs/python/core).
+
+## Future work:
- [ ] 3D coordinates. Only 2D geometries are supported at this time.
- [ ] CRS management. This currently loses the CRS information in the [GeoArrow metadata](https://geoarrow.org/extension-types#extension-metadata).
+## Background reading
+
Refer to the [GeoArrow Python module proposal](https://github.com/geoarrow/geoarrow-python/issues/38) for more background information.