Skip to content

Commit 0b27a08

Browse files
committed
Initial public release
0 parents  commit 0b27a08

File tree

244 files changed

+860004
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

244 files changed

+860004
-0
lines changed

.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# External environment settings for geoluck.
2+
# Copy to `.env` and point everything at paths outside the repo.
3+
4+
PROJECT_VENV_ROOT=$HOME/venvs/<project-name>
5+
UV_PROJECT_ENVIRONMENT=$PROJECT_VENV_ROOT
6+
PYTHONDONTWRITEBYTECODE=1
7+
PYTHONPYCACHEPREFIX=$PROJECT_VENV_ROOT/.cache/pycache
8+
PYTEST_ADDOPTS="-p no:cacheprovider"
9+
UV_CACHE_DIR=$PROJECT_VENV_ROOT/.cache/uv
10+
RUFF_CACHE_DIR=$PROJECT_VENV_ROOT/.cache/ruff
11+
NPM_CONFIG_CACHE=$PROJECT_VENV_ROOT/.cache/npm
12+
PLAYWRIGHT_BROWSERS_PATH=$PROJECT_VENV_ROOT/.cache/playwright
13+
WINEPREFIX=$PROJECT_VENV_ROOT/.cache/wine

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: "3.12"
17+
18+
- uses: astral-sh/setup-uv@v5
19+
with:
20+
version: "0.6.6"
21+
22+
- name: Sync Python environment
23+
run: uv sync --all-extras
24+
25+
- name: Run tests
26+
run: uv run python -B -m pytest
27+
28+
- uses: actions/setup-node@v4
29+
with:
30+
node-version: "20"
31+
cache: "npm"
32+
cache-dependency-path: web/package-lock.json
33+
34+
- name: Install web dependencies
35+
working-directory: web
36+
run: npm ci
37+
38+
- name: Build web app
39+
working-directory: web
40+
run: npm run build
41+

.github/workflows/pages.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Deploy Pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: true
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- uses: actions/setup-node@v4
24+
with:
25+
node-version: "20"
26+
cache: "npm"
27+
cache-dependency-path: web/package-lock.json
28+
29+
- name: Install web dependencies
30+
working-directory: web
31+
run: npm ci
32+
33+
- name: Build web app
34+
working-directory: web
35+
run: npm run build
36+
37+
- uses: actions/configure-pages@v5
38+
39+
- uses: actions/upload-pages-artifact@v3
40+
with:
41+
path: web/dist
42+
43+
deploy:
44+
environment:
45+
name: github-pages
46+
url: ${{ steps.deployment.outputs.page_url }}
47+
runs-on: ubuntu-latest
48+
needs: build
49+
steps:
50+
- id: deployment
51+
uses: actions/deploy-pages@v4
52+

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.DS_Store
2+
.env
3+
.env.local
4+
.python-version
5+
.coverage
6+
.mypy_cache/
7+
.pytest_cache/
8+
.ruff_cache/
9+
.cache/
10+
.venv/
11+
venv/
12+
env/
13+
__pycache__/
14+
*.py[cod]
15+
*.log
16+
17+
# Private local agent/project planning files
18+
AGENTS.md
19+
geoluck_codex_plan.md
20+
21+
# Private agent workflow state
22+
do/
23+
24+
# Local/generated data artifacts
25+
data_raw/**
26+
data_intermediate/**
27+
data_final/**
28+
!data_raw/.gitkeep
29+
!data_intermediate/.gitkeep
30+
!data_final/.gitkeep
31+
32+
# Generated frontend payloads/build products
33+
web/node_modules/
34+
web/dist/

DATA_SOURCES.md

Lines changed: 52 additions & 0 deletions
Large diffs are not rendered by default.

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2026
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

Makefile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
SHELL := /bin/bash
2+
.ONESHELL:
3+
4+
.PHONY: sync test lint fmt web-install web-build check
5+
6+
define load_env
7+
if [ -f .env ]; then
8+
set -a
9+
source ./.env
10+
set +a
11+
fi
12+
endef
13+
14+
sync:
15+
$(load_env)
16+
uv sync
17+
18+
test:
19+
$(load_env)
20+
uv run python -B -m pytest
21+
22+
lint:
23+
$(load_env)
24+
uv run ruff check .
25+
26+
fmt:
27+
$(load_env)
28+
uv run ruff format .
29+
30+
web-install:
31+
$(load_env)
32+
cd web
33+
npm install
34+
35+
web-build:
36+
$(load_env)
37+
cd web
38+
npm run build
39+
40+
check: test web-build
41+

README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# geoluck &nbsp; <img src="logo/geoduck.png" alt="" width="36" />
2+
3+
**How much of relative country prosperity can be predicted from geography, natural endowments, resource development, and social structure — and who beats their geography?**
4+
5+
Geoluck is an open-source research project that builds a country-decade panel (1900–2020) and trains machine learning models to predict four prosperity outcomes from tiered feature sets. The results are published as an interactive static site.
6+
7+
This is explicitly about **predictive association**, not causal effect.
8+
9+
**[View the live site →](https://smkwray.github.io/geoluck/)**
10+
11+
---
12+
13+
## What the site shows
14+
15+
The static site models four outcome metrics, each converted to within-decade percentile ranks:
16+
17+
| Outcome | Definition | Source |
18+
|---|---|---|
19+
| **Income** | Log GDP per capita rank | Maddison Project Database 2023 |
20+
| **Wealth** | Produced capital per capita rank | World Bank Changing Wealth of Nations |
21+
| **Life expectancy** | Life expectancy at birth rank | World Bank WDI / UN Population Division |
22+
| **Inequality** | Disposable-income Gini rank (higher = more equal) | SWIID |
23+
24+
Predictor features are organized into three independently toggleable tiers:
25+
26+
- **Nature** — Pure geography: latitude, climate normals, terrain, soil, malaria ecology, seismic activity, wind/solar potential, ocean productivity, cyclone exposure.
27+
- **Infrastructure** — Resource development: dams, irrigation, oil/gas/coal/mineral extraction, agricultural land use, energy assets.
28+
- **Society** — Social and institutional structure: governance, democracy, trade openness, colonial history, ethnic/religious fractionalization, gender inequality, demographics.
29+
30+
All seven non-empty tier combinations are modeled independently for each outcome (28 model bundles). The site supports interactive choropleth maps, model comparison, country-level SHAP feature contributions, country-vs-country comparison, feature exploration by data source, full sortable rankings with CSV export, and shareable deep links.
31+
32+
---
33+
34+
## Repository structure
35+
36+
```
37+
src/ Python pipeline — ETL, feature building, modeling, export
38+
web/ Static frontend — TypeScript, Vite, Leaflet, Chart.js
39+
docs/ Methodology and payload documentation
40+
web/public/data/ Precomputed JSON payloads consumed by the frontend
41+
```
42+
43+
---
44+
45+
## Data policy
46+
47+
Raw and intermediate research data are **not** stored in the public repository. Only compact, precomputed JSON payloads required by the static site are committed under `web/public/data/`. These are generated by the Python pipeline's export commands.
48+
49+
---
50+
51+
## Modeling notes
52+
53+
- Models are evaluated **out of sample** using cross-validated R², RMSE, MAE, and Spearman rank correlation.
54+
- User-facing predictions and residuals use **cross-validated exports**, not in-sample fits.
55+
- Feature contributions use SHAP values from fold-trained estimators.
56+
- Results should be interpreted as **predictive structure**, not causal effects. A high R² for Nature-only features means geography is a strong statistical predictor — likely because it correlates with deeper causal channels — not that geography *causes* prosperity.
57+
58+
---
59+
60+
## GitHub Pages deployment
61+
62+
The site is deployed through **GitHub Actions**, not "Deploy from a branch."
63+
64+
In repository Settings → Pages, set the source to **GitHub Actions**. The workflow builds the frontend from `web/` and publishes the contents of `web/dist/`.
65+
66+
---
67+
68+
## Local development
69+
70+
```bash
71+
# Python pipeline
72+
make sync # Install/sync Python dependencies
73+
make test # Run tests
74+
75+
# Frontend
76+
make web-build # Build the static site (output: web/dist/)
77+
```
78+
79+
The frontend expects JSON data under `web/public/data/`. These payloads are committed to the repository and are generated by:
80+
81+
```bash
82+
uv run geoluck export-web-data
83+
```
84+
85+
For frontend development with hot reload:
86+
87+
```bash
88+
cd web && npm run dev
89+
```
90+
91+
---
92+
93+
## Documentation
94+
95+
- [`DATA_SOURCES.md`](DATA_SOURCES.md) — Source registry and licensing notes
96+
- [`docs/MODEL_SPECS.md`](docs/MODEL_SPECS.md) — Model families, feature-set variants, evaluation design
97+
- [`docs/UI_DATA_PAYLOADS.md`](docs/UI_DATA_PAYLOADS.md) — Frontend JSON payload schemas
98+
99+
---
100+
101+
## License
102+
103+
MIT

data_final/.gitkeep

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

data_intermediate/.gitkeep

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)