Skip to content

ianp-1/nadir

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

207 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nadir

NADIR

Decentralized Disaster Verification Platform
AI-powered satellite imagery analysis · Human consensus voting · On-chain proof via Solana

Next.js Solana Mapbox Prisma TITiler


What is Nadir?

Nadir is a platform that combines satellite imagery, crowd-sourced human verification, and blockchain consensus to produce immutable, trustworthy disaster damage assessments.

The pipeline works like this:

Satellite Imagery (Maxar Open Data)
        ↓
  AI Uncertainty Scoring
        ↓
  Human Volunteer Voting (Damage / No Damage / Unsure)
        ↓
  Consensus Engine (N-of-M threshold)
        ↓
  On-Chain Anchoring (Solana via Anchor/Seahorse)
        ↓
  Reputation SBTs (Metaplex Core Soulbound Tokens)
        ↓
  First Responder Dispatch (Command Center)

Table of Contents


Architecture

┌──────────────────────────────────────────────────────────────┐
│                     FRONTEND (Next.js 16)                    │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌─────────────┐  │
│  │Dashboard │  │Satellite │  │Missions  │  │ Responder   │  │
│  │(Mapbox)  │  │Map View  │  │& Scanner │  │ Cmd Center  │  │
│  └──────────┘  └──────────┘  └──────────┘  └─────────────┘  │
├──────────────────────────────────────────────────────────────┤
│                      API LAYER (Next.js Routes)              │
│  /api/tiles · /api/vote · /api/mosaic · /api/satellite       │
│  /api/nonce · /api/user · /api/admin · /api/actions          │
├──────────────────────────────────────────────────────────────┤
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌─────────────┐  │
│  │PostgreSQL│  │TITiler   │  │Solana    │  │ Metaplex    │  │
│  │(Prisma)  │  │(COG Svr) │  │(Anchor)  │  │ Core (SBT)  │  │
│  └──────────┘  └──────────┘  └──────────┘  └─────────────┘  │
└──────────────────────────────────────────────────────────────┘
Layer Technology Purpose
Frontend React 19, Mapbox GL JS, Tailwind CSS 4 Interactive satellite map, voting UI, dashboards
Auth Privy + better-auth Email/social login with embedded Solana wallet
Database PostgreSQL + Prisma ORM Users, tiles, votes, sessions
Tile Server TITiler (self-hosted) Dynamic rendering of Cloud-Optimized GeoTIFFs
Blockchain Solana (Anchor / Seahorse) Consensus anchoring, damage verification proofs
NFTs Metaplex Core Soulbound reputation tokens for volunteers
Infrastructure Docker, DigitalOcean Containerized deployment

Prerequisites

Tool Version Install
Node.js ≥ 20 nodejs.org
pnpm ≥ 9 npm install -g pnpm
PostgreSQL ≥ 15 postgresql.org or Docker
Docker Latest docker.com (optional, for TITiler + production)
Solana CLI ≥ 1.18 sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
Anchor CLI ≥ 0.32 cargo install --git https://github.com/coral-xyz/anchor avm --locked

Optional (for on-chain programs):

  • Rustcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • Seahorsecargo install seahorse-lang

Quick Start

# 1. Clone the repo
git clone https://github.com/YOUR_ORG/nadir.git
cd nadir

# 2. Install dependencies
pnpm install

# 3. Set up environment variables
cp .env.example .env
# Edit .env and fill in the required values (see table below)

# 4. Set up the database
# Option A: Local PostgreSQL
createdb nadir
pnpm prisma migrate dev

# Option B: Docker PostgreSQL (included in docker-compose)
docker compose up postgres-db -d
pnpm prisma migrate dev

# 5. Generate the Prisma client
pnpm prisma generate

# 6. Start the dev server
pnpm dev

Open http://localhost:3000 to see the dashboard.


Environment Variables

Create a .env file from the example:

cp .env.example .env
Variable Required Description
DATABASE_URL PostgreSQL connection string (pooled)
DIRECT_URL PostgreSQL direct connection (for migrations)
NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN Mapbox GL JS token — get one here
NEXT_PUBLIC_PRIVY_APP_ID Privy authentication app ID — privy.io
SOLANA_RPC_URL Solana RPC endpoint (defaults to http://127.0.0.1:8899)
ADMIN_KEYPAIR_SECRET JSON array of 64 bytes for the admin Solana keypair
HELIUS_API_KEY Helius RPC/webhook API key
AUTHORITY_PRIVATE_KEY Base58 private key for on-chain authority
NEXT_PUBLIC_NADIR_MINT_ADDRESS SPL token mint address
WEBHOOK_SECRET Secret for satellite webhook verification
NEXT_PUBLIC_TITILER_URL TITiler endpoint (defaults to http://localhost:8080)
COG_CDN_URL CDN URL for mirrored Cloud-Optimized GeoTIFFs
CONSENSUS_THRESHOLD Votes to reach consensus (default: 5)
CONSENSUS_QUORUM Total votes required before evaluation (default: 7)

✅ = Required for the app to run · ⬡ = Optional / has default


Running with Docker

The docker-compose.yml includes all services:

# Start everything (app + TITiler + PostgreSQL)
docker compose up -d --build

# Start only TITiler (for local dev with satellite imagery)
docker compose up titiler -d

# Start only PostgreSQL
docker compose up postgres-db -d

# View logs
docker compose logs -f web

# Shut down
docker compose down
Service Port Description
web 3000 Next.js production server
titiler 8080 TITiler COG tile server
postgres-db 5433 PostgreSQL 15

Database Setup

The schema is managed by Prisma. Key models:

Model Purpose
User Volunteers, rescuers, admins (with solanaWallet, reputationScore, role)
Tile Satellite tiles with beforeUrl, afterUrl, aiUncertaintyScore, status
Vote User votes on tiles (DAMAGE_FOUND / NO_DAMAGE / UNSURE)
Session Auth sessions via better-auth
# Run migrations
pnpm prisma migrate dev

# Open Prisma Studio (visual DB browser)
pnpm prisma studio

# Reset database
pnpm prisma migrate reset

Solana / On-Chain Setup

Local Validator (Development)

# Start a local Solana validator
solana-test-validator

# In a new terminal, configure CLI for local
solana config set --url http://127.0.0.1:8899

# Airdrop SOL for testing
solana airdrop 5

Deploy the Seahorse Consensus Program

cd nadir-consensus

# Build
seahorse build   # Compile Python → Rust
anchor build     # Compile Rust → BPF

# Deploy to local validator
anchor deploy

# Or deploy to Devnet
solana config set --url devnet
solana airdrop 2
anchor deploy

Soulbound Tokens (SBTs)

Nadir uses Metaplex Core to mint frozen (soulbound) reputation NFTs:

  • Minted after a user casts ≥ 5 evaluated votes
  • Score (0–100) reflects voting accuracy against consensus outcomes
  • Automatically updated as more votes are cast
  • Frozen via FreezeDelegate plugin — non-transferable

Project Structure

nadir/
├── src/
│   ├── app/                    # Next.js App Router pages
│   │   ├── page.tsx            # Landing → Dashboard
│   │   ├── dashboard/          # Dashboard view
│   │   ├── map/                # Satellite map explorer
│   │   ├── missions/           # Mission listing & details
│   │   ├── scan/               # Tile scanner (swipe voting)
│   │   ├── review/             # Tile review (detailed)
│   │   ├── responder/          # First responder command center
│   │   │   ├── page.tsx        # Tactical heatmap with dispatch
│   │   │   ├── analytics/      # Responder analytics
│   │   │   ├── missions/       # Responder mission view
│   │   │   └── settings/       # Responder settings
│   │   ├── login/              # Sign in page
│   │   ├── signup/             # Registration
│   │   ├── profile/            # User profile & wallet
│   │   └── api/                # API routes (see API Reference)
│   ├── components/
│   │   ├── DashboardClient.tsx  # Main dashboard (873 lines!)
│   │   ├── MapView.tsx          # Mapbox map with mosaic overlays
│   │   ├── HeatMap.tsx          # Canvas-based global heatmap
│   │   ├── Sidebar.tsx          # Tile listing & filtering
│   │   ├── TileDetailPanel.tsx  # Tile inspection + voting
│   │   ├── tile-scanner.tsx     # Swipe-style tile verification
│   │   ├── Header.tsx           # App header with stats & auth
│   │   └── ui/                  # shadcn/ui components
│   ├── lib/
│   │   ├── consensus.ts         # Core consensus engine + Solana anchoring
│   │   ├── reputation.ts        # Reputation scoring + SBT minting
│   │   ├── umi.ts               # Metaplex Core SBT operations
│   │   ├── solana.ts            # Solana connection + config
│   │   ├── nonce.ts             # Durable nonce accounts for offline tx
│   │   ├── satellite/           # Multi-provider satellite imagery
│   │   │   ├── types.ts         # Provider contracts
│   │   │   ├── maxar.ts         # Maxar Open Data
│   │   │   ├── sentinel2.ts     # Sentinel-2 (medium-res)
│   │   │   ├── planet.ts        # Planet Labs
│   │   │   └── umbra.ts         # Umbra SAR
│   │   ├── prisma.ts            # Prisma client singleton
│   │   └── auth.ts              # better-auth setup
│   └── data/                    # Mock/seed data
├── prisma/
│   └── schema.prisma            # Database schema
├── nadir-consensus/             # Anchor/Seahorse on-chain programs
├── disaster_relief/             # Seahorse disaster relief program
├── contracts/                   # Additional smart contracts
├── scripts/
│   ├── prerender-tiles.sh       # Pre-render tiles to CDN
│   └── mirror-cogs.sh           # Mirror COG files to DigitalOcean
├── docker-compose.yml           # All services
├── Dockerfile                   # Multi-stage Next.js build
├── titiler.Dockerfile           # TITiler tile server
└── public/                      # Static assets

Features & Pages

🛰️ Satellite Dashboard (/)

The main command center. Displays an interactive Mapbox satellite map with:

  • 50+ disaster events from the Maxar Open Data catalog (hurricanes, earthquakes, floods, wildfires, volcanoes, landslides)
  • Mosaic tile overlays rendered via TITiler from Cloud-Optimized GeoTIFFs
  • Tile sidebar with filtering by status (Pending / Verified Damage / Verified Safe)
  • AI uncertainty scoring for prioritizing tiles that need human review
  • Catalog switching between pre/post-disaster imagery passes
  • Map style switching between satellite, hybrid, and dark map layers

🗺️ Map Explorer (/map)

Dedicated satellite map view with event selection and catalog browsing.

📋 Missions (/missions)

Lists active verification missions with:

  • Certainty percentage, milestone progress, escrow balance
  • Region and status indicators
  • Drill-down to individual mission details

🔍 Tile Scanner (/scan/[missionId])

A swipe-style mobile-friendly tile verification interface:

  • Before/after satellite image comparison
  • Keyboard shortcuts for rapid voting (← / → / ↓)
  • Tag-based damage classification (structural, flooding, debris)
  • Progress tracking across tile sets

📊 Tile Detail (/review/[id])

Deep inspection panel for individual tiles:

  • Before/after image comparison with slider
  • Vote submission (Damage Found / No Damage / Unsure)
  • Metadata: coordinates, AI uncertainty score, consensus status
  • Solana transaction hash link after consensus anchoring
  • Catalog browsing per tile

🚨 Responder Command Center (/responder)

A tactical interface for first responders:

  • Live heatmap of verified damage zones
  • 3D tilted map with automated damage point overlays
  • Target popups with satellite preview and "Initiate Dispatch" action
  • GeoJSON export of all verified damage for GIS tools
  • Metric cards: Priority Zones, Active Volunteers
  • Hidden header for immersive full-screen experience

👤 Profile (/profile)

User profile with:

  • Wallet connection status
  • Reputation score and SBT details
  • Organization affiliation
  • Voting history

🔐 Authentication (/login, /signup)

  • Email/password via better-auth
  • Privy embedded wallet (automatic Solana wallet provisioning)
  • Solana Wallet Adapter integration (Phantom, Solflare, etc.)

API Reference

Tiles

Method Endpoint Description
GET /api/tiles List all tiles (supports ?status= filter)
GET /api/tiles/[id] Get tile by ID
GET /api/tiles/next-priority Get next highest-priority tile for review
GET /api/tiles/map-markers Get map marker data for all tiles
GET /api/tiles-for-bbox Get tiles within a bounding box

Voting & Consensus

Method Endpoint Description
POST /api/vote Submit a vote (tileId, decision)
GET /api/user/votes Get user's voting history

Satellite & Imagery

Method Endpoint Description
GET /api/mosaic/[slug] Get mosaic metadata for a disaster event
GET /api/mosaic-tiles/[slug]/[...path] Proxy mosaic tiles from TITiler
GET /api/satellite/search Search satellite imagery catalogs
GET /api/satellite/tile Get individual satellite tile
GET /api/satellite/providers List available satellite providers
POST /api/satellite/aoi Register area of interest for monitoring
POST /api/satellite/webhook Receive satellite imagery webhooks

User & Auth

Method Endpoint Description
GET/POST /api/auth/[...all] better-auth catch-all handler
GET /api/user/reputation Get user's reputation score
GET /api/user/wallet Get user's wallet info
POST /api/user/org Update user organization

Nonce & Offline Transactions

Method Endpoint Description
GET /api/nonce Get user's durable nonce
POST /api/nonce/create Create a durable nonce account
POST /api/nonce/submit Submit an offline-signed transaction

Solana Actions (Blinks)

Method Endpoint Description
GET/POST /api/actions/verify/[tileId] Solana Action for tile verification
GET/POST /api/actions/vote/[tileId] Solana Action for voting

Admin

Method Endpoint Description
POST /api/admin/mint Admin mint operations

Demo Walkthrough

Follow this sequence to showcase the full platform during a demo:

1. Start Services

# Terminal 1: Start TITiler for satellite imagery
docker compose up titiler -d

# Terminal 2: Start the Next.js dev server
pnpm dev

2. Create an Account

  1. Navigate to localhost:3000/signup
  2. Create an account with email/password
  3. You'll be redirected to the dashboard with an embedded Solana wallet

3. Explore the Dashboard

  1. Open localhost:3000 — the main satellite dashboard
  2. Use the event dropdown in the sidebar to select a disaster event (e.g., "Hurricane Ian", "Wildfires — Los Angeles")
  3. Watch as the Maxar Open Data mosaic loads over the satellite basemap
  4. Click individual tile footprints on the map to see before/after comparisons
  5. Use the filter chips (Pending / Damage / Safe) to focus on specific tile statuses
  6. Switch map styles between satellite, hybrid, and dark

4. Vote on Tiles

  1. Click a pending tile on the map or sidebar
  2. The Tile Detail Panel slides open on the right
  3. Inspect the satellite imagery — compare before/after
  4. Cast your vote: Damage Found, No Damage, or Unsure
  5. When enough votes accumulate (default: 5/7), consensus is reached
  6. The result is anchored to Solana — look for the transaction hash in the tile detail

5. Tile Scanner (Mobile-Friendly)

  1. Navigate to localhost:3000/missions
  2. Select an active mission
  3. Click Start Scanning to enter the swipe-style scanner
  4. Use keyboard shortcuts: (No Damage), (Damage), (Unsure)
  5. Tag damage types: structural damage, flooding, debris

6. Responder Command Center

  1. Navigate to localhost:3000/responder
  2. See the tactical heatmap showing verified damage clusters
  3. Click individual damage points for a popup with satellite preview
  4. Click "Initiate Dispatch" in the popup
  5. Use "Export .GeoJSON Data" to download all verified damage for GIS tools
  6. Note the immersive full-screen layout (no header)

7. Profile & Reputation

  1. Navigate to localhost:3000/profile
  2. Check your reputation score (accuracy % based on consensus alignment)
  3. After ≥ 5 votes on finalized tiles, a Soulbound Token is minted to your wallet
  4. Connect an external wallet via the Solana wallet button in the header

8. On-Chain Verification (Advanced)

# Check the Solana explorer for anchored consensus transactions
# The tx hash appears in the Tile Detail Panel after consensus is reached

# Check SBT minting
# Use `solana account <asset-id>` to inspect a minted reputation SBT

Satellite Data Sources

Nadir supports a multi-provider architecture:

Provider Resolution Pipeline Access
Maxar Open Data 30–50 cm Human verification Free (AWS S3 / GitHub)
Sentinel-2 10 m AI background scanning Free (Copernicus)
Planet Labs 3–5 m Both API key required
Umbra 25 cm SAR Human verification API key required

Maxar events are sourced from the opengeos/maxar-open-data repository. The catalog includes 50+ disaster events spanning wildfires, hurricanes, earthquakes, floods, cyclones, volcanic eruptions, and landslides from 2015–2025.


Deployment

DigitalOcean App Platform (Recommended)

  1. Push to your GitHub repo
  2. Create a new App on DigitalOcean App Platform
  3. Set environment variables in the App settings
  4. Add a managed PostgreSQL database
  5. Deploy TITiler as a separate service (or on a Droplet)

Docker (Self-Hosted)

# Build and run all services
docker compose up -d --build

# The app will be available at http://localhost:3000
# TITiler at http://localhost:8080

Production Checklist

  • Set NODE_ENV=production
  • Configure production DATABASE_URL with connection pooling
  • Set Solana RPC to Devnet/Mainnet (not localhost)
  • Configure COG_CDN_URL for faster tile serving
  • Add a real WEBHOOK_SECRET
  • Run pnpm prisma migrate deploy (not dev)
  • Pre-render tiles with scripts/prerender-tiles.sh for high-traffic events

License

MIT


Built with 🛰️ by the Nadir team

About

HackIllinois Best Deployed on DigitalOcean · AI-powered satellite imagery analysis · Human consensus voting · On-chain proof via Solana

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors