Skip to content

Commit 827224b

Browse files
committed
Configure as global-30x30 geo-agent app
Replace template (CA / PAD-US) with a global 30×30 / Target 3 reproduction kit inspired by Fajardo et al. 2026 (Nat Commun, doi:10.1038/s41467-026-71860-8). - layers-input.json: global view, grouped collections for WDPA, LandMark IPLC, WWF ecoregions, IUCN richness, NCP biodiversity + irrecoverable carbon, GHS-POP, and Overture admin boundaries - system-prompt.md: 30×30 framing with explicit "what we don't have" section listing the missing layers (KBA, AOH, MOSAIKS HDI, livelihood datasets) - coverage.md: figure-by-figure reproducibility table against the paper - k8s/: rename slug padus → global-30x30 - Include paper + supplementary PDFs (CC-BY 4.0) for reference
1 parent eff7ed1 commit 827224b

11 files changed

Lines changed: 250 additions & 255 deletions

README.md

Lines changed: 17 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,33 @@
1-
# geo-agent-template
1+
# global-30x30 — geo-agent app
22

3-
A GitHub template for deploying an AI-powered interactive map app.
4-
Users describe in plain language what datasets to show; the app uses an LLM agent with map tools and SQL access to visualize and analyze cloud-native geospatial data.
3+
A geo-agent configuration for exploring the spatial and social context of the **Kunming-Montreal Global Biodiversity Framework Target 3** ("30×30") — the commitment that at least 30% of terrestrial, inland water, marine and coastal areas be effectively conserved by 2030.
54

6-
**No JavaScript to write.** The core modules (map, chat, agent, tools) are loaded from CDN. You configure which data to show via three small files.
5+
Inspired by the analysis in Fajardo et al. 2026, *Social implications of the 30×30 global conservation target* (Nature Communications, [doi:10.1038/s41467-026-71860-8](https://doi.org/10.1038/s41467-026-71860-8)). See [`coverage.md`](coverage.md) for which of that paper's analyses can and cannot be reproduced from the current STAC catalog.
76

8-
**Full documentation:** [boettiger-lab.github.io/geo-agent/docs](https://boettiger-lab.github.io/geo-agent/docs/)
7+
## Layers
8+
9+
- **WDPA December 2025** — current global protected areas
10+
- **LandMark IPLC v202509** — Indigenous and community-mapped lands
11+
- **WWF Terrestrial Ecoregions (2017)** — biodiversity representation framing
12+
- **IUCN Species Richness (2025)** — vertebrate richness rasters
13+
- **NCP — Biodiversity & Natural Habitat** (Chaplin-Kramer 2019) and **Irrecoverable / Vulnerable Carbon** (Noon 2022)
14+
- **GHS-POP 2020** — gridded global population
15+
- **Overture countries / regions** — admin context
916

1017
## Repository structure
1118

1219
```
1320
index.html ← HTML shell — loads core JS/CSS from CDN
14-
layers-input.json ← which STAC collections to show + LLM settings
15-
system-prompt.md ← LLM system prompt (customize per app)
21+
layers-input.json ← STAC collections + LLM settings + welcome examples
22+
system-prompt.md ← LLM system prompt (30×30 framing + caveats)
1623
k8s/ ← Kubernetes deployment manifests (optional)
1724
```
1825

19-
## Quick start
20-
21-
### 1. Create your repo from this template
22-
23-
Click **"Use this template"** on GitHub → **"Create a new repository"**.
24-
25-
### 2. Choose your datasets
26-
27-
Browse the available STAC catalog:
28-
29-
```
30-
https://radiantearth.github.io/stac-browser/#/external/s3-west.nrp-nautilus.io/public-data/stac/catalog.json
31-
```
32-
33-
Edit `layers-input.json` — set your collections and adjust the default map view.
34-
See the [configuration reference](https://boettiger-lab.github.io/geo-agent/docs/guide/configuration) for all fields.
35-
36-
### 3. Edit `system-prompt.md`
37-
38-
Describe the domain, what users are likely to ask, and include SQL examples relevant to your datasets.
39-
40-
### 4. Deploy
41-
42-
#### Option A: GitHub Pages (no server needed)
43-
44-
The `llm` block in `layers-input.json` is already enabled. Each visitor enters their own API key (e.g. from [OpenRouter](https://openrouter.ai)) in the in-app settings panel — keys are stored in the browser only, never on the server.
45-
46-
1. Enable GitHub Pages in your repo: Settings → Pages → Source → **GitHub Actions**
47-
2. Add `.github/workflows/gh-pages.yml`:
48-
49-
```yaml
50-
name: Deploy to GitHub Pages
51-
on:
52-
push:
53-
branches: [main]
54-
permissions:
55-
contents: read
56-
pages: write
57-
id-token: write
58-
jobs:
59-
deploy:
60-
runs-on: ubuntu-latest
61-
environment:
62-
name: github-pages
63-
url: ${{ steps.deployment.outputs.page_url }}
64-
steps:
65-
- uses: actions/checkout@v4
66-
- uses: actions/configure-pages@v5
67-
- uses: actions/upload-pages-artifact@v3
68-
with:
69-
path: .
70-
- id: deployment
71-
uses: actions/deploy-pages@v4
72-
```
73-
74-
3. Push — the workflow deploys automatically on changes to `main`.
75-
76-
#### Option B: Kubernetes
77-
78-
API keys are injected server-side via a ConfigMap + Kubernetes secrets — no user-facing key entry.
79-
80-
1. Delete the `llm` block from `layers-input.json` (the server-injected `config.json` takes precedence anyway)
81-
2. Replace the git clone URL in `k8s/deployment.yaml` with your repo URL
82-
3. Replace the slug `calenviroscreen` throughout `k8s/` with your app name
83-
4. Set your hostname in `k8s/ingress.yaml`
84-
5. Create the required secret:
85-
86-
```bash
87-
kubectl create secret generic llm-proxy-secrets \
88-
--from-literal=proxy-key=YOUR_PROXY_KEY
89-
```
90-
91-
6. Deploy:
92-
93-
```bash
94-
kubectl apply -f k8s/
95-
kubectl rollout status deployment/my-app
96-
```
97-
98-
After pushing changes, redeploy: `kubectl rollout restart deployment/my-app`
99-
100-
See the [deployment guide](https://boettiger-lab.github.io/geo-agent/docs/guide/deployment) for full details on all options including Hugging Face Spaces.
26+
This is a fork of [`boettiger-lab/geo-agent-template`](https://github.com/boettiger-lab/geo-agent-template); the JavaScript runtime is loaded from CDN. See the [geo-agent docs](https://boettiger-lab.github.io/geo-agent/) for the full configuration reference.
10127

102-
## Local development
28+
## Local preview
10329

10430
```bash
10531
python -m http.server 8000
106-
# Open http://localhost:8000 — enter your API key in the settings panel
32+
# Open http://localhost:8000 — enter an API key in the settings panel
10733
```
108-
109-
## More resources
110-
111-
- [Configuration reference](https://boettiger-lab.github.io/geo-agent/docs/guide/configuration) — all `layers-input.json` fields with examples
112-
- [Deployment guide](https://boettiger-lab.github.io/geo-agent/docs/guide/deployment) — GitHub Pages, Hugging Face Spaces, Kubernetes
113-
- [Core library](https://github.com/boettiger-lab/geo-agent) — source code for the map, chat, and agent modules

coverage.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Reproducibility coverage
2+
3+
This app's layers are a partial reproduction kit for Fajardo et al. 2026, *Social implications of the 30×30 global conservation target* (Nature Communications, [doi:10.1038/s41467-026-71860-8](https://doi.org/10.1038/s41467-026-71860-8)). The table below tracks what we can and cannot reproduce against the paper's reported figures.
4+
5+
Datasets we currently lack are tracked in [boettiger-lab/data-workflows#161](https://github.com/boettiger-lab/data-workflows/issues/161) — see also #140 (Theobald gHM), #157 (KBA + IUCN AOH ranges).
6+
7+
## Reproducibility status by figure / table
8+
9+
| Paper artefact | What it shows | Reproducible? | Blocker |
10+
|---|---|:---:|---|
11+
| **Headline: 396 M in existing PAs, 1.15 B within 10 km** | Resident + buffer population for current PA/OECM network | 🟡 Partial | Have WDPA + GHS-POP, missing WD-OECM. Numbers will differ by year (we have 2020 not 2023). |
12+
| **Fig 1 — scenario maps** | Three Target-3 scenarios overlaid with current PAs || Scenario rasters not hosted; the `prioritizr` runs that produced them require species AOH, KBA, NCP, HMI we don't have |
13+
| **Fig 2a — resident + neighbouring population by scenario** | Population in new PAs vs buffer || Same scenario rasters |
14+
| **Fig 2b — HDI breakdown by scenario** | % of scenario population in Low / Medium / High / Very High HDI || MOSAIKS gridded HDI not in catalog |
15+
| **Fig 2c — livelihood overlap (wild harvest / farm / livestock)** | % of scenario area / population overlapping each livelihood class || Wells (wild harvesting), Lesiv/Mehrabi (farm size), GLPS v5 (livestock) all missing |
16+
| **Fig 3 — continental HDI × population** | Per-continent comparison of scenario populations and HDI || Both blockers above |
17+
| **Suppl Table 1 — population in each scenario** | Per-scenario population totals + % of global | 🟡 Partial | Row for "Existing PAs" only; scenario rows need the rasters |
18+
| **Suppl Table 2 — population in scenarios by continent** | Continent-level totals | 🟡 Partial | Existing-PA row only |
19+
| **Suppl Table 3 — population × HDI** | All scenarios × HDI groups || MOSAIKS HDI |
20+
| **Suppl Table 4 — livelihood overlap** | Wild harvesting / farm area / livestock × scenario || Livelihood layers |
21+
| **Suppl Fig 1 — % global area in scenarios + buffers** | Area accounting | 🟡 Partial | Existing-PA portion only |
22+
| **Suppl Fig 2 / 3 — spatial overlap between scenarios** | Venn / overlap maps || Scenario rasters |
23+
| **Suppl Fig 5 — ITT scenario distribution** | 100-replicate ITT map | 🟡 Partial | Have LandMark IPLC as a proxy, not the ICCA Registry + HMI-masked composite the paper uses |
24+
25+
## What we can reproduce today
26+
27+
These analyses are doable with the layers currently configured in `layers-input.json`:
28+
29+
- **Global PA coverage**: `% of land area inside a designated PA``wdpa-december-2025`. Will land short of the paper's 17.2% figure because WD-OECM is missing.
30+
- **Population inside / near PAs**: `ghs-pop-2020` × `wdpa-december-2025`. Comparable to the paper's first row.
31+
- **Country-level PA coverage**: WDPA `ISO3` × Overture countries.
32+
- **Ecoregion representation**: `wwf-ecoregions-2017` × `wdpa-december-2025`. % of each ecoregion inside the PA network — speaks to the biodiversity-representation argument of the paper without reproducing the `prioritizr` optimization.
33+
- **Biodiversity value of PAs vs unprotected**: `iucn-richness-2025` (combined or per-taxon) × WDPA. Aggregated richness only — not the per-species coverage check the paper performs.
34+
- **Carbon stocks inside / outside PAs**: `irrecoverable-carbon` × WDPA. Closest analogue to one of the paper's 10 NCP layers (vulnerable ecosystem carbon).
35+
- **IPLC × PA overlap**: `landmark-iplc-poly` × `wdpa-december-2025`. Proxy for the ITT lens.
36+
37+
## Things we should *not* fabricate
38+
39+
If a user asks for HDI breakdowns, wild-harvesting estimates, farm-size or livestock-area overlaps, or scenario-specific results: say plainly we don't host those layers and point at the source datasets in [data-workflows#161](https://github.com/boettiger-lab/data-workflows/issues/161). Do not substitute unrelated layers (e.g. don't approximate HDI with SVI — SVI is US-only and a different construct).

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<head>
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<title>CA Protected Lands</title>
7+
<title>Global 30×30 Explorer</title>
88

99
<!--
1010
Geo-Chat core modules loaded from CDN.

k8s/configmap.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# LLM config template — NO SECRETS.
22
#
33
# The upstream LLM proxy key lives only in the nginx config (see
4-
# `padus-nginx` below), which injects the Authorization header
4+
# `global-30x30-nginx` below), which injects the Authorization header
55
# server-side via `proxy_set_header`. The browser only sees a relative
66
# `/api/llm` endpoint and never holds the key.
77
#
88
# See ../../geo-agent-ops/SECRETS_EXPOSURE.md for the migration plan.
99
apiVersion: v1
1010
kind: ConfigMap
1111
metadata:
12-
name: padus-config
12+
name: global-30x30-config
1313
namespace: biodiversity
1414
data:
1515
config.template.json: |
@@ -81,7 +81,7 @@ data:
8181
apiVersion: v1
8282
kind: ConfigMap
8383
metadata:
84-
name: padus-nginx
84+
name: global-30x30-nginx
8585
namespace: biodiversity
8686
data:
8787
nginx.conf.template: |

k8s/deployment.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
apiVersion: apps/v1
22
kind: Deployment
33
metadata:
4-
name: padus
4+
name: global-30x30
55
namespace: biodiversity
66
labels:
7-
app: padus
7+
app: global-30x30
88
spec:
99
replicas: 1
1010
strategy:
@@ -14,11 +14,11 @@ spec:
1414
maxSurge: 1
1515
selector:
1616
matchLabels:
17-
app: padus
17+
app: global-30x30
1818
template:
1919
metadata:
2020
labels:
21-
app: padus
21+
app: global-30x30
2222
spec:
2323
initContainers:
2424
- name: git-clone
@@ -30,7 +30,7 @@ spec:
3030
# Clone YOUR app repo (the GitHub repo you created from the template).
3131
# Update this URL to point to your own GitHub repo:
3232
# Update this URL to point to your own GitHub repo:
33-
git clone --depth 1 https://github.com/boettiger-lab/geo-agent-template.git /tmp/repo
33+
git clone --depth 1 https://github.com/boettiger-lab/global-30x30.git /tmp/repo
3434
cp /tmp/repo/index.html /usr/share/nginx/html/
3535
cp /tmp/repo/layers-input.json /usr/share/nginx/html/
3636
cp /tmp/repo/system-prompt.md /usr/share/nginx/html/
@@ -103,9 +103,9 @@ spec:
103103
emptyDir: {}
104104
- name: config-template
105105
configMap:
106-
name: padus-config
106+
name: global-30x30-config
107107
- name: nginx-template
108108
configMap:
109-
name: padus-nginx
109+
name: global-30x30-nginx
110110
- name: nginx-conf-d
111111
emptyDir: {}

k8s/ingress.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: networking.k8s.io/v1
22
kind: Ingress
33
metadata:
4-
name: padus-ingress
4+
name: global-30x30-ingress
55
namespace: biodiversity
66
annotations:
77
haproxy-ingress.github.io/cors-enable: "true"
@@ -16,15 +16,15 @@ spec:
1616
ingressClassName: haproxy
1717
tls:
1818
- hosts:
19-
- padus.nrp-nautilus.io
19+
- global-30x30.nrp-nautilus.io
2020
rules:
21-
- host: padus.nrp-nautilus.io
21+
- host: global-30x30.nrp-nautilus.io
2222
http:
2323
paths:
2424
- path: /
2525
pathType: Prefix
2626
backend:
2727
service:
28-
name: padus
28+
name: global-30x30
2929
port:
3030
number: 80

k8s/service.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
apiVersion: v1
22
kind: Service
33
metadata:
4-
name: padus
4+
name: global-30x30
55
namespace: biodiversity
66
labels:
7-
app: padus
7+
app: global-30x30
88
spec:
99
type: ClusterIP
1010
selector:
11-
app: padus
11+
app: global-30x30
1212
ports:
1313
- protocol: TCP
1414
port: 80

0 commit comments

Comments
 (0)