Skip to content

Pizanjavier/wildspotter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WildSpotter

A geographical exploration tool for the overland and vanlife community. WildSpotter acts as a "radar" that processes geographic, topographic, legal, and satellite data to probabilistically discover undiscovered overnight parking spots in the wild.

Unlike user-generated directories (Park4night, iOverlander) that lead to spot overcrowding, WildSpotter discovers new spots from raw geographic data — no community reviews needed.

Target region: Spain (initial).

Full specification: SPEC_V2.md

Architecture

WildSpotter uses a backend-centric architecture. All heavy processing (geographic filtering, terrain analysis, legal cross-referencing, AI inference) runs in a Dockerized backend stack. The React Native app is a lightweight client that consumes pre-processed data via a JSON API.

┌──────────────────────────────────────────────────────────────┐
│                     Docker Compose Stack                     │
│                                                              │
│  ┌──────────┐    ┌──────────────┐    ┌───────────────────┐   │
│  │   n8n    │───>│  AI/GIS      │───>│  PostgreSQL       │   │
│  │ (cron)   │    │  Worker      │    │  + PostGIS        │   │
│  │          │    │ (Python)     │    │                   │   │
│  └──────────┘    └──────────────┘    └─────────┬─────────┘   │
│       │                                        │             │
│       │  Geofabrik .osc diffs                  │             │
│       v                                        │             │
│  ┌──────────┐                          ┌───────┴─────────┐   │
│  │ osm2pgsql│─────────────────────────>│    Fastify       │   │
│  │ (import) │                          │  (JSON API)     │   │
│  └──────────┘                          └───────┬─────────┘   │
│                                                │             │
└────────────────────────────────────────────────┼─────────────┘
                                                 │ HTTP/JSON
                                        ┌────────┴────────┐
                                        │  React Native   │
                                        │  (Expo) Client  │
                                        └─────────────────┘
Component Technology Role
Mobile Client React Native / Expo (TypeScript) UI, map rendering, API consumption, offline caching
Backend API Fastify (TypeScript) Serves processed spot data as JSON
Database PostgreSQL + PostGIS Spain OSM data, terrain/legal/AI results, spatial indexing
Orchestration n8n Scheduled data ingestion and processing pipelines
Processing Worker Python Terrain-RGB analysis, WMS legal checks, AI model inference

How It Works

WildSpotter runs a 5-stage processing pipeline on OSM data, executed server-side:

Radar → Topographer → Legal Judge → Satellite Eye → Context & Amenities

1. Radar (Infrastructure Filtering)

Queries the local PostGIS database (imported from OpenStreetMap via Geofabrik) to find:

  • Dead-end dirt/gravel tracks (noexit=yes)
  • Informal unpaved parkings near points of interest
  • Clearings accessible by motor vehicle (excludes hiking/cycling paths)

2. Topographer (Elevation Analysis)

Python worker evaluates terrain slope using Terrain-RGB tiles (AWS Terrarium, z15). Slope and elevation are stored for every spot — no spots are rejected. Users filter by max slope at query time via preferences.

3. Legal Judge (Restriction Cross-Referencing)

Python worker cross-references candidates against Spanish government data using local PostGIS spatial queries (offline) and the Catastro REST API:

  • Red Natura 2000 — EU environmental protection zones (local PostGIS, MITECO shapefiles)
  • National Parks — strict protection boundaries (local PostGIS, MITECO shapefiles)
  • Coastal Law zones — maritime-terrestrial public domain: DPMT, Servidumbre de Protección, Terrenos Incluidos; minus Núcleos Excluidos (local PostGIS, MITECO shapefiles)
  • Cadastre — land classification via Catastro REST API (Consulta_RCCOOR)

Legal Zones Map Overlay: Users can toggle a red semi-transparent overlay on the map showing all restriction areas. This uses pre-generated Mapbox Vector Tiles (.pbf files at z4–z10, ~74 MB on disk) served as static files by the Fastify API — zero PostGIS cost at runtime. Tiles are generated by workers/generate_legal_tiles.py, which creates a materialized view with coastline-clipped geometries (marine zones excluded) and includes the DPMT boundary line as a 20m buffer polygon. Regenerate tiles when MITECO shapefiles are updated.

The original WMS-based approach was replaced because MITECO endpoints had wrong layer names, returned XML instead of JSON, and the Coastal Law endpoint was dead — causing all legal checks to silently pass every spot. Local PostGIS queries run in ~1ms/spot vs ~1s/spot with WMS.

Fuente: «© Ministerio para la Transición Ecológica y el Reto Demográfico»

4. Satellite Eye (AI Visual Validation)

Python worker downloads satellite imagery (IGN Spain PNOA orthophotos, 25cm/pixel) and sends tiles to Claude Haiku Vision for multi-factor analysis. It evaluates 5 sub-scores: surface quality, vehicle access, open space, van presence, and obstruction absence, generating a rich contextual score rather than a simple binary classification.

5. Context & Amenities Analyst

Evaluates spatial surroundings using local PostGIS queries to determine road noise, privacy, scenic value, and access to nearby amenities (drinking water and dog-friendly places). Adjusts the overall context score based on spatial proximity.

Scoring

Each spot receives a 0-100 composite score: Terrain (20%) + AI (25%) + Context (55%). Legal data is informational only — it does not gate scoring. All spots receive a score regardless of legal status. Users can toggle "hide restricted areas" at query time.

Tech Stack

Layer Technology
App React Native + Expo (TypeScript strict)
Maps MapLibre GL
AI Claude Haiku Vision API (server-side, Python worker)
State Zustand
Backend API Fastify (TypeScript)
Database PostgreSQL + PostGIS
Orchestration n8n (cron pipelines)
Workers Python (terrain, legal, AI, scoring)
Data Local OSM (Geofabrik), Terrain-RGB, Spanish WMS (MITECO, Catastro, IGN)

Getting Started

Prerequisites

  • Docker Desktop (includes Docker Compose)
  • Node.js 18+
  • Expo CLI (npm install -g expo-cli)
  • For iOS: Xcode + iOS Simulator runtime
  • For Android: Android Studio + Android SDK

1. Set up environment variables

cp .env.example .env
# Edit .env with your values (database password, optional API keys)

2. Start the backend stack

docker-compose up -d --build

This starts all 4 services:

  • PostgreSQL + PostGIS on port 5433 (external)
  • Fastify API on port 8000
  • Python worker on port 8001 (Flask API, runs terrain+legal+AI in parallel threads)
  • n8n on port 5678 (orchestrator, triggers pipeline every 20 min)

Verify the stack is running:

docker-compose ps
curl http://localhost:8000/health

3. Seed the database

Download the Spain OSM extract (~1.3 GB) and import it:

mkdir -p data
wget -O data/spain-latest.osm.pbf https://download.geofabrik.de/europe/spain-latest.osm.pbf

docker-compose exec worker osm2pgsql \
  -d wildspotter -H db -U wildspotter -s \
  /data/spain-latest.osm.pbf

4. Start the mobile app

npm install

# Web (recommended for development)
npx expo start --web

# iOS Simulator
npx expo start --ios

# Android Emulator
npx expo start --android

Run Tests

npm test

Project Structure

src/                         # React Native app (thin client)
├── app/                     # Expo Router screens (Map, Spots, Legal, Config)
├── components/              # UI components (map/, spots/, legal/, ui/)
├── services/api/            # Typed API client for Fastify backend
├── stores/                  # Zustand state management
├── constants/               # Theme tokens, config
└── types/                   # Shared TypeScript types
backend/                     # Fastify API (TypeScript)
├── src/routes/              # GET /spots, GET /spots/:id, GET /health, GET /legal/tiles/:z/:x/:y.pbf
├── src/services/            # PostGIS query builders, static tile serving
└── Dockerfile
workers/                     # Processing scripts (Python)
├── terrain.py               # Slope/elevation analysis
├── legal.py                 # PostGIS legal checks + Catastro REST API
├── ai_vision_labeler.py     # Claude Haiku multi-factor satellite analysis
├── scoring.py               # Composite score calculation
├── generate_legal_tiles.py  # Pre-generate MVT tiles for legal zone map overlay
└── Dockerfile
db/                          # Database schema
├── init.sql                 # PostGIS extension + tables + indexes
data/                        # OSM extracts, satellite tiles, legal tiles (gitignored)
models/                      # ML model files (.keras, .onnx)
design/                      # Design mockups (.pen + PNG exports)
docker-compose.yml           # Full stack orchestration

AI Vision (Claude Haiku)

Architecture

  • Model: Claude Haiku (claude-haiku-4-5-20251001) via Anthropic API
  • Task: Multi-factor scene understanding for vanlife suitability
  • Input: 256x256 RGB satellite tiles
  • Output: 5 sub-scores (0-10) generating a composite ai_score (0-100) and ai_details JSONB
  • Factors Analyzed:
    • surface_quality (30%): Mineral/dirt/gravel suitability
    • vehicle_access (20%): Visible tracks/roads
    • open_space (20%): Room for vehicles
    • van_presence (15%): Bonus for already parked vans
    • obstruction_absence (15%): Free from dense trees/buildings
  • Inference: Server-side python worker calling Anthropic API (workers/ai_vision_labeler.py)

Docker Commands

docker-compose up -d --build       # Start/rebuild all services
docker-compose logs -f api         # Follow API logs
docker-compose logs -f worker      # Follow worker logs
docker-compose exec db psql -U wildspotter  # Database shell
docker-compose down                # Stop all services
docker-compose down -v             # Stop and destroy volumes (reset DB)

# Generate legal zone map overlay tiles (~25s, ~64 MB)
docker-compose exec worker python generate_legal_tiles.py

Limitations

  • Spain only — Legal layers (MITECO shapefiles, Catastro REST API) are Spain-specific
  • Satellite imagery lag — Tiles may be months/years old
  • AI accuracy — Vision models can occasionally hallucinate tracks or misinterpret shadows
  • Slope estimation — Terrain-RGB resolution (~30m) misses micro-terrain
  • Legal data freshness — MITECO shapefiles are point-in-time snapshots; re-import periodically for updates

License

Private project — not open source.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors