A browser-based self-assessment wizard that generates personalised biodiversity monitoring plans for agricultural and semi-natural landscapes.
LAHMP is a functional prototype of a four-step land health self-assessment tool developed for the IUCN Nature-Based Solutions Hub. It operationalises the IUCN Land Health Monitoring Framework (LHMF), connecting sustainable agricultural practices to measurable biodiversity indicators through a structured, evidence-based workflow.
A practitioner — land manager, field ecologist, NGO programme officer, or monitoring coordinator — works through four sequential steps:
- Landscape Profile — characterise the site by location, land use, pressures, degradation challenges, and priority ecosystem services
- Practice Recommendation — receive a scored and ranked shortlist of sustainable land management practices matched to the site's pressure profile
- Capacity Assessment — declare team composition, field time, equipment, budget, and seasonal site access
- Monitoring Plan — receive an auto-generated, capacity-fitted monitoring programme: biological indicator protocols, abiotic baselines, a 12-month survey calendar, and a plain-language narrative
The output is a complete monitoring plan rendered in the browser and printable via window.print(). No server, no accounts, no API calls.
- Logic validation — verify that the LHMF scoring and filtering algorithms produce scientifically coherent outputs for known test landscapes
- Stakeholder demonstration — share a working prototype with project partners and funders via a static URL
- Development testbed — confirm JSON knowledge-base structure against algorithm output before production implementation in Laravel/Vue.js
LAHMP is a single-page application with zero build tooling. All logic runs in the browser against static JSON knowledge bases. There is no backend, no API, and no authentication layer.
┌─────────────────────────────────────────────────────────────────┐
│ Browser │
│ │
│ index.html ──── presentation shell (113 lines) │
│ wizard.js ──── all state management + algorithm logic │
│ styles.css ──── IUCN brand styling │
│ │
│ data/ │
│ ├── reference.json ← pressures (28), challenges (35), │
│ │ services (37), EFG options, │
│ │ pre-population mapping tables │
│ ├── practices.json ← 43 sustainable land management │
│ │ practices with scoring metadata │
│ ├── indicators.json ← 41 biological indicator profiles │
│ │ (32 validated, 6 draft, 3 pending) │
│ └── abiotic.json ← 16 abiotic baseline indicators │
│ │
│ localStorage ─────────── session persistence (resume on │
│ reload; not a data store) │
└─────────────────────────────────────────────────────────────────┘
flowchart TD
S1[Step 1 — Landscape Profile]
S2[Step 2 — Practice Recommendation]
S3[Step 3 — Capacity Assessment]
S4[Step 4 — Monitoring Plan]
S1 -->|pressures → challenges\nchallenges → services| S1
S1 -->|step1 object| S2
S2 -->|scored + filtered\nselected_practices| S3
S3 -->|computeCapacityProfile| S4
S4 --> O1[Op 1: Practice chains\ngrouped by theme]
S4 --> O2[Op 2: Indicator group\nselection]
S4 --> O3[Op 3: Protocol\nassignment]
S4 --> O4[Op 4: Capacity\nfitting]
S4 --> O5[Op 5: Monitoring\ncalendar]
| Concern | Choice | Rationale |
|---|---|---|
| Language | Vanilla ES2020 JavaScript | No build tooling; directly shareable via GitHub Pages |
| Markup | HTML5 | Single file, no templating engine |
| Styling | CSS custom properties | IUCN brand tokens; zero runtime overhead |
| Fonts | IBM Plex Sans / Serif / Mono | IUCN-aligned; loaded via Google Fonts CDN |
| Data | Static JSON | Exported from canonical Excel knowledge bases |
| Persistence | localStorage |
Wizard resume across page reloads |
| Hosting | GitHub Pages | Zero-infrastructure; no server required |
| PDF output | window.print() + print CSS |
No Puppeteer or server-side rendering |
- A modern browser (Chrome ≥ 105, Firefox ≥ 104, Safari ≥ 16, Edge ≥ 105)
- A static file server for local development (the wizard loads JSON via
fetch, which requires HTTP — openingindex.htmldirectly from disk will fail due to CORS restrictions)
Python 3, Node.js, or any other static server will work:
# Python 3
python3 -m http.server 8080
# Node.js (npx)
npx serve .
# Node.js (http-server)
npx http-server . -p 8080git clone https://github.com/daimpad/LAHMP.git
cd LAHMP
python3 -m http.server 8080
# Open http://localhost:8080No npm install, no build step, no environment variables.
https://daimpad.github.io/LAHMP
| Parameter | Values | Effect |
|---|---|---|
?fixture= |
TEST-01, TEST-02, TEST-03 |
Pre-loads a complete test assessment |
&step= |
1, 2, 3, 4 |
Jumps directly to the specified step |
Examples:
# Load the Skoura M'Daz Morocco test case, jump to Step 4 output
https://daimpad.github.io/LAHMP?fixture=TEST-01&step=4
# Load the Vietnam VSA test case at Step 1
https://daimpad.github.io/LAHMP?fixture=TEST-03
Three pre-configured fixtures cover distinct land system types and climate zones:
| ID | Name | Location | Primary EFG | Key pressures |
|---|---|---|---|---|
TEST-01 |
Skoura M'Daz | Drâa-Tafilalet, Morocco | T7.2 — Sown pastures | Overgrazing, soil erosion, drought |
TEST-02 |
PK-17 | Trarza, Mauritania | T7.5 — Semi-natural pastures | Desertification, overgrazing, invasive species |
TEST-03 |
Vietnam VSA | Mekong Delta, An Giang | T7.1 + F3.3 — Annual cropland / Rice paddies | Pesticide use, water pollution, agrobiodiversity loss |
- Open the wizard and enter landscape location details (Step 1, Block 1)
- Select IPCC land use categories, EFG codes, and soil types (Block 1.2)
- Mark active pressures for each of 28 pressure types (Block 4); Block 5 challenges auto-populate
- Confirm relevant land health challenges and rank priority ecosystem services (Blocks 5–6)
- Complete the pre-screen and review scored practice recommendations; select your programme's practices (Step 2)
- Declare team composition, field days, equipment, budget, and seasonal access calendar (Step 3)
- Step 4 generates automatically: review the narrative, indicator tables, and 12-month calendar; print via the browser print dialog
The wizard saves state to localStorage after every input — closing and reopening the tab resumes from the last position.
Defined as CSS custom properties in styles.css:
:root {
--iucn-navy: #003478;
--iucn-yellow: #FDC82F; /* action/accent only — never decorative */
--iucn-green: #1A7A52;
}All content is loaded at runtime from data/. These files are the canonical source of truth for the browser application. Do not edit them directly — they are generated by the export scripts in export/.
| File | Records | Description |
|---|---|---|
data/reference.json |
28 pressures, 35 challenges, 37 services, 15 IPCC land use categories, 10 soil types, ~120 EFG options | Block 4/5/6 lists and pre-population mapping tables |
data/practices.json |
43 practices across 11 themes | Practice Matrix: scoring metadata, eligibility rules, pre-screen linkages |
data/indicators.json |
41 profiles (32 validated, 6 draft, 3 pending) | Indicator Linkage Matrix: 3-level protocol assignments, seasonal windows, EFG/IPCC linkages. Draft profiles (14, 19, 22, 23, 37, 38) appear in Step 4 output with "Protocol proposed" badge; pending profiles (39–41) are excluded pending expert authoring. See docs/profiles_pending.md. |
data/abiotic.json |
16 indicators | Abiotic Reference Table: baseline measurement protocols and universal baseline flags |
All wizard state is held in window.assessment. Its structure is intentionally identical to the production assessment record JSON so prototype data can directly test the production algorithm:
window.assessment = {
assessment_id: String, // UUID — generated on first load
landscape_name: String,
created_at: ISO8601,
last_updated: ISO8601,
step1: { /* landscape profile */ },
step2: { /* selected practices */ },
step3: { /* capacity inputs */ },
step4_outputs: { /* algorithm outputs */ },
};See CLAUDE.md for the complete field-level schema. See FORM_DOCUMENTATION.md for structured guidance on every user-facing input form.
lahmp/
├── index.html ← Presentation shell — structural HTML only
├── wizard.js ← All state management and algorithm logic (~2 500 lines)
├── styles.css ← IUCN brand styling (~1 300 lines)
├── data/
│ ├── reference.json ← Pressures, challenges, services, mapping tables
│ ├── practices.json ← 43 practice profiles
│ ├── indicators.json ← 41 biological indicator profiles
│ ├── abiotic.json ← 16 abiotic baseline indicators
│ └── test_fixtures/
│ ├── TEST-01.json ← Skoura M'Daz, Morocco (T7.2)
│ ├── TEST-02.json ← PK-17, Mauritania (T7.5)
│ └── TEST-03.json ← Vietnam VSA (T7.1 + F3.3)
├── indicators/ ← DOCX source files for all 41 indicator profiles
│ ├── LAHMP_Indicator_Profile_Template.docx
│ └── LAHMP_Profile_01_Soil_Bacteria.docx … (41 files)
├── raw/ ← Canonical Excel and CSV source data
│ ├── LAHMP_Practice_Matrix.xlsx
│ ├── LAHMP_Indicator_Linkage_Matrix_Populated.xlsx
│ ├── LAHMP_Abiotic_Reference_Table.xlsx
│ └── IUCN - LHMT - *.csv … (7 files)
├── export/
│ ├── convert.py ← raw/*.xlsx → data/*.json
│ └── extract_indicators.py ← indicators/*.docx → data/indicators.json
├── CLAUDE.md ← Canonical developer specification and open items
├── FORM_DOCUMENTATION.md ← Complete reference for all user-facing input forms (Steps 1–3)
└── LICENSE
The file is organised into clearly labelled sections that map to the step and operation numbers in the specification documents:
Constants and lookup tables
MONTHS, TEAM_PROTOCOL_LEVEL, BUDGET_OPTS, THEME_TO_CHAIN,
PRESSURE_LAND_USE_KEYWORDS, PRESCREEN_ANSWERS, SITE_COUNT_MIDPOINT
Assessment state initialisation
Step 1 algorithms
prepopulateChallenges(pressures, landUseComposition)
prepopulateServices(challenges)
scorePractice(practice, step1)
Step 3 algorithms
computeCapacityProfile(step3)
Step 4 algorithms
Operation 1 — practice chain grouping
Operation 2 — selectIndicatorGroups(indicators, step1, step2)
Operation 3 — assignProtocol(group, capacityProfile)
Operation 4 — capacityFit(groups, cap, step2, step1)
Operation 5 — buildMonitoringCalendar(groups, accessCalendar)
└── parseSeasonalWindow(text)
└── splitIntoWindows(indices)
└── stageSpeed(monitoringStage)
runStep4Algorithm()
Render functions
renderStep1(), renderStep2(), renderStep3(), renderStep4()
Event wiring, navigation, localStorage persistence
- All algorithm logic in
wizard.js— render functions in the same file for simplicity, but clearly separated - All content from
data/— no labels, option lists, or tooltips are hardcoded in JS or HTML - Function names match spec terminology —
prepopulateChallenges,scorePractice,assignProtocol,computeCapacityProfile,selectIndicatorGroups - No external dependencies — no npm, no bundler, no polyfills beyond what browsers provide natively
The files in raw/ are the canonical source of truth. Always edit the source file first, then re-export to JSON. Never edit the JSON files in data/ directly.
# Re-export practices.json, abiotic.json, reference.json from raw/*.xlsx
cd export/
pip install pandas openpyxl python-docx
python3 convert.py
# Re-extract all 41 indicator profiles from indicators/*.docx
python3 extract_indicators.py
# Reads from indicators/ (tracked), falls back to indicators_dl/ cache,
# downloads from GitHub only if neither exists. Writes data/indicators.jsonThe primary test mechanism is loading a pre-configured test fixture and inspecting Step 4 output:
# Full run
https://daimpad.github.io/LAHMP?fixture=TEST-01
# Jump directly to output
https://daimpad.github.io/LAHMP?fixture=TEST-01&step=4
https://daimpad.github.io/LAHMP?fixture=TEST-02&step=4
https://daimpad.github.io/LAHMP?fixture=TEST-03&step=4
| Check | Expected |
|---|---|
| Block 5 pre-population | Challenges appear when Block 4 pressures are marked ongoing; confidence degrades to medium for past/not_sure; disappears for not_relevant |
| Area weighting | Marking overgrazing ongoing in a landscape with < 10% grassland area produces medium (not high) confidence challenges |
| Practice scoring | Practices with higher Block 4/5/6 overlap score higher; score displayed on each card |
| Protocol assignment | TEST-03 (Types C + D, budget tier 3) should assign Level 2 protocols; TEST-02 (Types A + B, budget tier 1) should assign Level 1 |
| Calendar windows | TEST-02 constrained months (April–June) should not appear as suggested monitoring windows |
| Capacity trimming | Low-capacity profiles (few days, low budget) should produce a trimmed group list in "Enhancement recommendations" |
export/extract_indicators.py includes a Python simulation of the Step 4 selection algorithm that was used during development to validate indicator counts against the three test fixtures. Run it directly to re-validate:
cd export/
python3 extract_indicators.py --validate-only
# Validates indicator selection logic against all three test fixtures.
# Expected counts will vary as B2/B1 linkages in indicators.json are updated;
# re-run after any data change to confirm the algorithm still produces non-empty output.This prototype has no automated test runner. The testing approach is:
- Fixture-based end-to-end — the three test fixtures provide known inputs with expected output characteristics
- Algorithm simulation — Python equivalents of the JS algorithms in
extract_indicators.pywere used to verify selection logic during development - Manual inspection — the rendered Step 4 output is reviewed against the scientific specification by domain experts
Automated unit tests (Jest or similar) are planned for LAHMP v1 (the production Laravel application).
The prototype is deployed automatically to GitHub Pages from the main branch. No CI/CD pipeline is configured — any push to main that modifies index.html, wizard.js, styles.css, or data/ is immediately live.
Production URL: https://daimpad.github.io/LAHMP
Branch: main
Deploy trigger: push to main (GitHub Pages auto-deploy)
Build step: none
Before pushing changes that affect algorithm behaviour:
- Verify all three test fixtures render correctly at
?fixture=TEST-0N&step=4 - Confirm JSON files were exported from the canonical Excel source (not edited manually)
- Check browser console for JavaScript errors on initial load and on each step transition
- Verify
localStorageresume works: fill Step 1, reload, confirm state is preserved
| Environment | URL | Branch |
|---|---|---|
| Production | https://daimpad.github.io/LAHMP |
main |
| Local development | http://localhost:8080 |
any |
There is no staging environment. Breaking changes should be developed on a feature branch and reviewed before merging to main.
Before contributing, note what is deliberately out of scope for this prototype and belongs to LAHMP v1 (the production Laravel application):
| Feature | Reason deferred |
|---|---|
| GEO API (globalecosystems.org polygon query) | Requires server, API key, CORS handling |
| ABC Map / FAO API for IPCC land use | Same |
| Leaflet polygon drawing | Prototype uses manual text inputs |
| User accounts and saved assessments | No server |
| PDF generation | window.print() is the prototype approach |
| LLM/AI narrative generation | IUCN AI policy clearance pending |
| Darwin Core field alignment | v2 feature |
| Automated test suite | Planned for v1 |
- Author the profile content in
LAHMP_Indicator_Profile_Template.docx - Add the row to
raw/LAHMP_Indicator_Linkage_Matrix_Populated.xlsx(canonical source) - Run
python3 export/extract_indicators.pyto regeneratedata/indicators.json - Load
?fixture=TEST-01&step=4and verify the new profile appears when its P-code linkages match the test landscape's selected practices - Set
"populated": "draft"while the profile awaits expert validation; upgrade to"populated": trueonce validated
main ← production (GitHub Pages)
feature/* ← new features or data updates
fix/* ← bug fixes
data/* ← knowledge base updates only (JSON re-exports)
Pull requests to main require at least one review. Squash-merge preferred for feature branches to keep history readable.
Follow Conventional Commits loosely:
feat: add conditionality check for conditional indicator profiles
fix: correct THEME_TO_CHAIN keys to match actual practice themes
data: re-export indicators.json from populated DOCX source files
docs: update README deployment section
- No hardcoded content in
wizard.jsorindex.html— all labels/options loaded fromdata/ - No new external dependencies introduced
- Algorithm changes tested against all three test fixtures
- JSON schema changes are backward-compatible with existing fixture files
-
CLAUDE.mdupdated if the developer specification has changed
- IUCN Global Ecosystem Typology 2.0 — EFG classification system used for landscape characterisation and indicator linkage
- IPCC Guidelines for National Greenhouse Gas Inventories — Land Use Categories — IPCC land use category framework used in Step 1
- IUCN Nature-Based Solutions — Organisational context for the LHMF
- Ecdysis Foundation 1000 Farms Protocol — Field-level biological monitoring methodology referenced in indicator profiles
- ISO 23611-1 — Soil quality: Sampling of soil invertebrates — Protocol standard for earthworm sampling (Profile 06)
- SEBI (Streamlining European Biodiversity Indicators) — European biodiversity indicator framework
- UK Countryside Survey methodology — Reference for vegetation quadrat and invertebrate survey protocols
- BTO/JNCC/RSPB Breeding Bird Survey — Protocol reference for farmland bird point counts (Profiles 19–21)
- UK Bat Conservation Trust Good Practice Guidelines — Protocol reference for bat acoustic monitoring (Profile 22)
- FAO TAPE — Tool for Agroecology Performance Evaluation — Agroecological performance framework; practice matrix approach origins
- LandScale Framework — Landscape-level sustainability assessment; ecosystem service methodology
- Rainforest Alliance Sustainable Agriculture Standard — Practice eligibility reference
- MDN — localStorage — Session persistence mechanism
- MDN — Fetch API — Used for loading JSON data files at runtime
- ECMAScript 2020 specification — Language version used throughout
wizard.js - CSS Custom Properties specification — Token system used for IUCN brand colours
The authoritative algorithm and data specifications are maintained as Word documents in the IUCN project SharePoint. They are the single source of truth; when any conflict exists between this README, CLAUDE.md, or the code, the specification documents take precedence.
| Document | Contents |
|---|---|
LAHMP_Master_Developer_Document.docx |
Platform architecture, data flow, v1/v2 boundary |
LAHMP_Step1_Developer_Specification.docx |
Landscape profile, all input lists, pre-population logic |
LAHMP_Step2_Developer_Specification.docx |
Practice recommendation algorithm (4 operations) |
LAHMP_Step3_Developer_Specification.docx |
Capacity assessment, 6 questions, capacity profile |
LAHMP_Step4_Developer_Specification.docx |
Monitoring plan algorithm (5 operations), output structure |
MIT License — see LICENSE for the full text.
Copyright © 2026 Damian Paderta
LAHMP is a prototype. It is not a certified monitoring tool. All indicator protocols and practice recommendations should be validated by qualified ecologists before field deployment.