Live demo: https://oasis51.205-209-110-122.sslip.io · API docs: https://oasis51.205-209-110-122.sslip.io/api/v1/methodology
Demo slides (7): PDF · PowerPoint
New to the project? Start with docs/TEAMMATE-START-HERE.md and docs/BACKEND-INTEGRATION.md.
Oman-focused crop-rotation decision-support prototype for the NASA Space Apps Challenge 2026 (Field Shift: Adapting Farms with NASA Data). A farmer places the farm on a map and enters area, water, irrigation method, salinity tests, previous crop and priorities. OASIS 51 then uses NASA POWER daily data (a listed resource of the challenge) to compute FAO-56 crop water demand, crop suitability with reasons, and a reference rotation plus two alternatives across two seasons, with water balance, heat and salinity risks, what-if scenarios and a printable report — in Arabic and English, with every source and assumption shown.
- Frontend (this folder): Next.js, bilingual RTL/LTR interface, farms kept in the browser.
- Backend (
backend/): FastAPI, NASA POWER client, FAO-56/FAO-29 calculations, rotation engine. See backend/README.md and backend/API.md.
OASIS 51 is independent and not affiliated with or endorsed by NASA. It uses public NASA POWER data.
Licence: MIT (LICENSE). Sources and third-party licences: docs/DATA-SOURCES.md, backend/SOURCES.md. AI use: docs/AI-USAGE.md, backend/AI_DISCLOSURE.md.
Next.js 16.4 (App Router, Turbopack, Cache Components) · React 19.3 · TypeScript 5 ·
Tailwind CSS 4 · Recharts 3 · Leaflet 1.9 / react-leaflet 5 (OpenStreetMap tiles) · Vitest 5.
Package manager: npm (Node.js 20.9+; developed on Node 26).
Optional code map: Trail-code / graft map (npm i -g @trailhq/trail-code, then trail build); see docs/GRAPH-STATUS.md.
npm install
cp .env.example .env.local # optional; defaults work without it
npm run dev # http://localhost:3000Production:
npm run build
npm run start # http://localhost:3000 (use -- -p 3051 for another port)Checks:
npm run typecheck # next typegen + tsc --noEmit
npm run lint # eslint
npm run test # vitest (normalization, validation, adapter query, provider switching)
npm run check # all of the above + production build
npm run fixture:rebuild # regenerate data/nasa/demo-oman/normalized.json + metadata.json from the saved raw response (offline)| Variable | Values | Purpose |
|---|---|---|
NEXT_PUBLIC_OASIS51_DATA_PROVIDER |
adapter (default) · mock · backend |
Which provider the browser data client uses |
NEXT_PUBLIC_OASIS51_BACKEND_URL |
public URL, e.g. https://api.example.org |
Base URL for backend mode (no secrets) |
NASA POWER requires no API key. Never put secrets in NEXT_PUBLIC_* variables — they are
embedded in the browser bundle. NEXT_PUBLIC_* values are read at build time; rebuild after changing them.
- All agreed routes render with consistent headers, breadcrumbs, cards, badges, tables and EN/AR (LTR/RTL). Each was checked at desktop and mobile width.
/farm/new: five-step setup with validation, map or manual coordinates, and edit mode. Records live in this browser only.- Real climate:
/analysis/[id]/climateshows real NASA POWER daily data (T2M, T2M_MAX, T2M_MIN, PRECTOTCORR, RH2M, WS2M, ALLSKY_SFC_SW_DWN) with:- completeness and missing-data warnings;
- provenance (observed period vs retrieval time), source metadata, and live/cached/demo labels;
- retry, and an explicit saved-example option that shows the example's own location.
- Printable report:
/analysis/[id]/reportcontains no illustrative values. Charts print with fixed sizes, and print output was verified as PDF in EN and AR. - Analyses keep a snapshot of the farm inputs. Editing a farm never rewrites a past analysis.
- Corrupted or blocked storage is reported, never silently overwritten.
- Module pages: water, crops, rotations and scenarios have complete layouts and interactions (filter, sort, compare, editable scenarios with reset). They use illustrative fixtures, always labeled "Illustrative interface demo — not calculated from this farm."
- Soil shows the real inputs, with soil EC and irrigation-water EC kept separate.
Direct demo URLs (after npm run dev):
- http://localhost:3000/analysis/demo/climate
- http://localhost:3000/analysis/demo/report
- http://localhost:3000/analysis/demo/water
- http://localhost:3000/analysis/demo/crops
- http://localhost:3000/analysis/demo/rotations
- http://localhost:3000/analysis/demo/scenarios
The scientific backend is in backend/ (FastAPI, Python 3.12). In backend provider mode every
analysis page reads calculated results from it: the browser sends each analysis's farm snapshot once
(PUT /api/v1/analyses/{id}), then reads climate, planning summary, soil, water, crops, rotations and
scenarios. Run both locally:
cd backend && python -m venv .venv && .venv/Scripts/activate && pip install -r requirements-dev.txt
uvicorn app.main:app --port 8000
# in the repo root:
NEXT_PUBLIC_OASIS51_DATA_PROVIDER=backend NEXT_PUBLIC_OASIS51_BACKEND_URL=http://localhost:8000 npm run devDetails, decisions and verification: docs/BACKEND-INTEGRATION.md.
Farms and analyses are saved in localStorage (oasis51.v1.farms, oasis51.v1.analyses) with
IDs like local-farm-xxxxxxxx. This is not a backend account or server persistence: it lives
only in the current browser profile. Do not commit personal farm records (the .gitignore
excludes /data/local/, /data/private/, *.farm.json, /exports/).
- Temporary adapter:
GET /api/climate/nasa-power/daily?latitude=&longitude=&start=YYYY-MM-DD&end=YYYY-MM-DD[&analysis_id=](src/app/api/climate/nasa-power/daily/route.ts). Fixed host/parameters, validation, 366-day limit, 20 s timeout, 2 bounded retries for timeouts/429/502/503/504, 24 h in-memory server cache (hits labeledcached),Cache-Control: no-store, typed error codes. - Components only use
dataClientfromsrc/lib/api/client.tsand the types insrc/types/. - The backend in
backend/implements this contract (including/climate). To use it, setNEXT_PUBLIC_OASIS51_DATA_PROVIDER=backendandNEXT_PUBLIC_OASIS51_BACKEND_URL=<url>; the climate page then callsGET {url}/api/v1/analyses/{analysis_id}/climate?start=&end=. The adapter stays foradaptermode.
src/app/ routes (pages + temporary API route)
src/components/ layout, ui, farm, climate, analysis views
src/lib/api/ data-access boundary (dataClient, useClimate)
src/lib/providers/ NASA POWER config, normalizer, query validation, server fetcher
src/lib/i18n/ en/ar dictionaries and provider
src/lib/storage/ browser-local prototype persistence (store.ts core, snapshots)
src/lib/modules/ pure UI helpers (crop filter/sort, scenario inputs)
src/components/modules/ soil, water, crops, rotations, scenarios views
src/lib/validation/ farm form validation → canonical Farm
src/types/ shared contract types (api, climate, farm)
src/mocks/ demo records (real saved fixture) + illustrative.ts (NOT calculations)
data/nasa/demo-oman real NASA POWER response, normalized fixture, metadata
docs/ handoff documentation
tests/ vitest suites
claude-tasks/ task instructions
docs/PAGE-INVENTORY.md— routes, readiness, data dependenciesdocs/API-CONTRACT.md— canonical fields, types, endpoints, handoffdocs/DATA-SOURCES.md— NASA POWER verification and fixture provenancedocs/BACKEND-HANDOFF.md— page data needs, exact/proposed contracts, storage replacement, acceptance checklistdocs/AI-USAGE.md— AI assistance disclosuredocs/IMAGE-ASSET-MANIFEST.md— AI-generated image inventory, sizes and crop decisionsdocs/GRAPH-STATUS.md— Graft (Trail-code graft map) statusdocs/FRONTEND-PHASE-01-REPORT.md,docs/FRONTEND-PHASE-02-REPORT.md— phase reportsAGENTS.md— persistent workflow instructions for coding agents
- Project-scoped skills are in
.claude/skills/, vendored and pinned, with provenance in.claude/skills/VENDORED.md. The inventory and how each skill was applied are indocs/FRONTEND-SKILLS-INVENTORY.md.- The bilingual rules live in
.claude/skills/oasis51-rtl-i18n/and are enforced bytests/i18n.test.ts.
- The bilingual rules live in
- Interface:
- The home page opens with a real NASA POWER range chart, labeled as saved real data.
- Starting a farm and exploring the demo are clearly separate actions.
- The analysis overview groups modules as Real data, Your inputs and Illustrative previews.
- The wizard has an error summary that focuses the first invalid field, explicit optional labels, and an unsaved-changes guard.
- The climate page shows a skeleton while loading and a provenance strip, and its source metadata is collapsible.
- Crop filters are kept in the URL.
- Icons are an authored SVG set.
- Motion respects
prefers-reduced-motion. - Arabic visitors no longer see an English flash on first load.
- Performance:
- Recharts loads only where a chart renders, and the saved fixture loads only on demand.
- Measured encoded JS on
/went from 315 KB to 196 KB (see the phase report for the method and all routes).
- Security:
- The adapter limits new upstream NASA requests to 20 per minute per client (
TOO_MANY_REQUESTS, HTTP 429). - Baseline security headers are set, and
X-Powered-Byis removed.
- The adapter limits new upstream NASA requests to 20 per minute per client (
The app follows the three approved concept boards in design-references/; these are AI-generated and illustrative only (see docs/REFERENCE-DESIGN-MAPPING.md).
Shared components:
- light header, analysis sidebar and quiet bordered cards;
- metric tiles, accordions and an illustrative pill.
Data, contract and functionality are unchanged.
Asset gap (Phase 04): there were no licensed photographs, so authored SVG illustrations were used. Phase 05 resolves this with AI-generated images (see below). Report: docs/FRONTEND-PHASE-04-REPORT.md.
- Source: the owner supplied AI-generated images:
- the home hero;
- 13 crop photos;
- a soil and root illustration;
- 5 irrigation illustrations;
- the logo.
- Pipeline:
- Originals stay locally in
design-assets/(git-ignored). node scripts/build-image-assets.mts(sharp) writes the optimized WebP/PNG files topublic/assets/and writesdocs/image-assets.json.- The typed manifest is
src/lib/assets.ts. - Inventory and crop decisions:
docs/IMAGE-ASSET-MANIFEST.md.
- Originals stay locally in
- Disclosure: every generated image shows a visible "AI-generated" marker or caption. The hero says it is a fictional scene, and the soil picture says it is not a measured profile.
- Unchanged: maps, charts, NASA data, IDs, validation and routes.
- Report:
docs/FRONTEND-PHASE-05-REPORT.md.
Superseded: the Dock was removed in Phase 08 and the text navigation restored. Kept here as history.
- What it is: the owner-supplied Dock (
src/components/ui/dock.tsx, built on framer-motion and lucide-react) is the site's page navigation, fixed at the bottom centre. - How it works:
- It is icon-only; page names appear as translated tooltips on hover or keyboard focus.
- Inside an analysis it links to that analysis's own module pages.
- What it replaced: the header text links, the mobile menu and the analysis sidebar.
- Print: the Dock is hidden.
- Report:
docs/FRONTEND-PHASE-06-REPORT.md.
- Three stages at
/farm/new, then one results page at/analysis/{id}that answers four questions:- What could I grow?
- What is the plan?
- Is there enough water?
- What should I watch?
- Real farms: real NASA POWER climate data, the user's own water input, and honest "not available yet / not assessed" states.
- The example (
/analysis/demo) shows labeled illustrative results. - Water amounts can be entered per day, per week, per month or as a total.
- Report: a 2-page summary.
- Backend: the needed contract is the proposed
GET /api/v1/analyses/{id}/planning-summary. - Docs:
docs/SIMPLE-USER-JOURNEY.mdanddocs/FRONTEND-PHASE-07-REPORT.md.
- Navigation:
- the bottom Dock is gone;
- the header has text links and a mobile menu again;
- analysis pages have a sidebar (pills on smaller screens) that keeps the current analysis ID.
- Visual refinement follows the owner's selected skills:
emil-design-eng,ui-ux-pro-max,impeccable(guidance only) andtaste-skill(vendoredSKILL.mdonly). The fifth skill was never specified. - Unchanged: data, behaviour, the three-stage journey, content, images and routes.
- Report:
docs/FRONTEND-PHASE-08-REPORT.md.
- Location: chosen on the map only. Coordinates stay as internal, validated data.
- Positive findings: shown in subtle light green.
- Arabic mode: illustrative example text, parameter names and labels are translated.
- Buttons: clearer shapes, with hover, focus, press, disabled and loading states.
- Report:
docs/FRONTEND-PHASE-09-REPORT.md.