Background
Currently deploying the Climate API requires cloning the repository and modifying config files in-place. Country teams and HISP groups must maintain a fork to add custom extents or dataset templates, and must track upstream changes manually.
A better model — inspired by how frameworks like Django or FastAPI apps work — would be to install the core API as a Python package and drive all instance configuration from a single config file:
pip install climate-api
CLIMATE_API_CONFIG=./climate-api.yaml uvicorn climate_api:app
# climate-api.yaml
extent:
id: rwa
name: Rwanda
bbox: [28.8, -2.9, 30.9, -1.0]
country_code: RWA
datasets_dir: ./datasets/ # optional — defaults to built-in templates
Since each instance serves exactly one spatial extent, the extent belongs in the main config rather than a separate extents.yaml. The config file becomes the only file a country team needs to create. Deployment-specific settings (base URL, credentials, cache paths) can be supplied as env vars or via ${VAR:-default} substitution inside the config — following the same pattern as pygeoapi.
What this enables
- Single config file to set up an instance — no fork, no in-place edits
- Built-in dataset templates (CHIRPS, ERA5, WorldPop) ship as package data and work out of the box
- Custom dataset YAMLs are layered on top via
datasets_dir
- Custom download functions via
eo_function: in YAML work as plugins installed alongside
- Core API updates arrive as
pip install --upgrade climate-api, not merge conflicts
- The
create_app(config) entry point makes the API embeddable in downstream FastAPI apps
Design notes from pygeoapi
pygeoapi uses the same env var → YAML → runtime dict → API(config) pattern and is worth following closely:
- Plugin loading via dotted path —
eo_function: mypackage.sources.enacts.download in YAML already implements this; no entry-points system needed
- Framework-agnostic core —
create_app(config) should be the public entry point, with the HTTP layer (uvicorn) separate, so the API can be mounted in larger apps
${VAR:-default} substitution — keeps secrets out of the config file for Docker/k8s deployments
- Bundled templates — the one gap vs pygeoapi: built-in CHIRPS/ERA5/WorldPop YAMLs must ship as
importlib.resources package data and be discoverable without any user config
Implementation outline
- Move
data/datasets/ into the package as importable resources (importlib.resources)
- Replace
data/extents.yaml (list) with a single extent: block in CLIMATE_API_CONFIG
- Make
datasets_dir overridable, falling back to package-bundled defaults
- Expose
create_app(config) as the public entry point
- Publish to PyPI
Relationship to other issues
Background
Currently deploying the Climate API requires cloning the repository and modifying config files in-place. Country teams and HISP groups must maintain a fork to add custom extents or dataset templates, and must track upstream changes manually.
A better model — inspired by how frameworks like Django or FastAPI apps work — would be to install the core API as a Python package and drive all instance configuration from a single config file:
Since each instance serves exactly one spatial extent, the extent belongs in the main config rather than a separate
extents.yaml. The config file becomes the only file a country team needs to create. Deployment-specific settings (base URL, credentials, cache paths) can be supplied as env vars or via${VAR:-default}substitution inside the config — following the same pattern as pygeoapi.What this enables
datasets_direo_function:in YAML work as plugins installed alongsidepip install --upgrade climate-api, not merge conflictscreate_app(config)entry point makes the API embeddable in downstream FastAPI appsDesign notes from pygeoapi
pygeoapi uses the same
env var → YAML → runtime dict → API(config)pattern and is worth following closely:eo_function: mypackage.sources.enacts.downloadin YAML already implements this; no entry-points system neededcreate_app(config)should be the public entry point, with the HTTP layer (uvicorn) separate, so the API can be mounted in larger apps${VAR:-default}substitution — keeps secrets out of the config file for Docker/k8s deploymentsimportlib.resourcespackage data and be discoverable without any user configImplementation outline
data/datasets/into the package as importable resources (importlib.resources)data/extents.yaml(list) with a singleextent:block inCLIMATE_API_CONFIGdatasets_diroverridable, falling back to package-bundled defaultscreate_app(config)as the public entry pointRelationship to other issues
climate_api.client.open_dataset()from Python client: climate_api.open() convenience function for dataset access #60 becomes importable in external projects without a separate package