Skip to content

Commit ac7b7b4

Browse files
authored
Merge pull request #3 from boettiger-lab/docs/readme-deployment
docs: document both deployment options in README
2 parents 46850d0 + eb4d1b9 commit ac7b7b4

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

README.md

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
A reusable JavaScript library for interactive map applications with LLM-powered data analysis. MapLibre GL JS on the front end, agentic tool-use with MCP (Model Context Protocol) for SQL analytics via DuckDB.
44

5-
**This repo is the core library.** Individual apps (different datasets, URLs, branding) import these modules from the CDN and provide their own configuration. See [`example/`](example/) for a complete client app template.
5+
**This repo is the core library.** Individual apps (different datasets, URLs, branding) import these modules from the CDN and provide their own configuration.
6+
7+
**Live demo (GitHub Pages):** <https://boettiger-lab.github.io/geo-agent/>
68

79
## Quick start: create a new app
810

9-
1. Copy [`example/`](example/) into a new repo
10-
2. Edit `layers-input.json` — choose your STAC collections and assets
11+
1. Copy one of the example templates into a new repo
12+
2. Edit `layers-input.json` — choose your STAC collections, assets, and LLM config
1113
3. Edit `index.html` — set page title, pin CDN version
12-
4. Deploy with `kubectl apply -f k8s/`
14+
4. Deploy (see options below)
15+
16+
| Template | Deployment | API key handling |
17+
|---|---|---|
18+
| [`example/`](example/) | Kubernetes / managed host | Injected server-side via `config.json` |
19+
| [`example-ghpages/`](example-ghpages/) | GitHub Pages / any static host | Entered by the user in-browser |
1320

1421
See the [example README](example/README.md) for full details.
1522

@@ -55,11 +62,11 @@ Client apps load the core modules directly from jsdelivr:
5562
└────────────┘ └────────────┘ └──────────────┘
5663
```
5764

58-
Each client app is a tiny repo (~5 files) that provides:
65+
Each client app is a tiny repo (~4–5 files) that provides:
5966
- `index.html` — loads core JS/CSS from CDN, sets page title
60-
- `layers-input.json`which STAC collections + assets to show
67+
- `layers-input.json` — STAC collections, assets, and (optionally) LLM config
6168
- `system-prompt.md` — LLM personality and guidelines
62-
- `k8s/` — deployment manifests (hostname, replicas, secrets)
69+
- `k8s/`Kubernetes deployment manifests (hostname, replicas, secrets) — optional
6370

6471
### Core modules (`app/`)
6572

@@ -82,14 +89,24 @@ Each client app is a tiny repo (~5 files) that provides:
8289

8390
## Configuration
8491

85-
Client apps provide `layers-input.json`:
92+
Client apps provide `layers-input.json`. All fields except `collections` are optional.
8693

8794
```json
8895
{
8996
"catalog": "https://s3-west.nrp-nautilus.io/public-data/stac/catalog.json",
9097
"titiler_url": "https://titiler.nrp-nautilus.io",
9198
"mcp_url": "https://duckdb-mcp.nrp-nautilus.io/mcp",
9299
"view": { "center": [-119.4, 36.8], "zoom": 6 },
100+
101+
"llm": {
102+
"user_provided": true,
103+
"default_endpoint": "https://openrouter.ai/api/v1",
104+
"models": [
105+
{ "value": "anthropic/claude-sonnet-4", "label": "Claude Sonnet" },
106+
{ "value": "google/gemini-2.5-flash", "label": "Gemini Flash" }
107+
]
108+
},
109+
93110
"collections": [
94111
{
95112
"collection_id": "cpad-2025b",
@@ -110,6 +127,14 @@ Client apps provide `layers-input.json`:
110127
- **Object** entries with `assets` cherry-pick specific STAC asset IDs for map layers
111128
- Asset filtering only affects map toggles — all parquet/H3 data remains available for SQL
112129

130+
### LLM configuration
131+
132+
There are two ways to supply model credentials:
133+
134+
**Server-provided** (Kubernetes / managed deployments): omit the `llm` section from `layers-input.json` and provide a `config.json` on the same server with `llm_models` + API keys. The `k8s/` manifests in `example/` inject secrets this way at deploy time.
135+
136+
**User-provided** (static sites — GitHub Pages, Netlify, etc.): set `"user_provided": true` in the `llm` section. A ⚙ button appears in the chat footer; visitors enter their own API key (stored in `localStorage`, never sent to the hosting server). The `default_endpoint` is pre-filled — [OpenRouter](https://openrouter.ai) is a good default giving access to many models via a single key.
137+
113138
## Development
114139

115140
### Working on the core library
@@ -129,5 +154,11 @@ The `app/` directory includes its own `index.html`, `layers-input.json`, and `sy
129154

130155
## Deployment
131156

132-
The `k8s/` directory in this repo deploys the core library's own demo instance. See [`example/k8s/`](example/k8s/) for the client app deployment template.
157+
| Option | Template | How secrets are handled |
158+
|---|---|---|
159+
| **GitHub Pages** (or any static host) | [`example-ghpages/`](example-ghpages/) | User enters their own API key in-browser |
160+
| **Hugging Face Spaces** | Start from either example | Mount a `config.json` as a Space secret-file |
161+
| **Kubernetes** | [`example/`](example/) with [`k8s/`](example/k8s/) | Secrets injected into `config.json` via ConfigMap + init container |
162+
163+
The `k8s/` directory in this repo deploys the core library's own demo instance on the [NRP](https://nrp-nautilus.io) cluster. See [`example/k8s/`](example/k8s/) for the client app deployment template, and [`example/README.md`](example/README.md) for a full walkthrough of all three options.
133164

0 commit comments

Comments
 (0)