Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danizd/urbanviable/llms.txt

Use this file to discover all available pages before exploring further.

UrbanViable’s frontend is a single-page application built with React 18 and Vite 6. The map is rendered by MapLibre GL JS 4, which uses WebGL to evaluate scoring expressions directly on the GPU. When a user moves a slider, the new weighted score is computed across every census section simultaneously on the GPU — no fetch, no server round-trip, no re-render of the React tree beyond updating the paint property on the map layer.

Technology Stack

PackageVersionRole
react + react-dom18.3.xUI framework and DOM rendering
react-router-dom6.28.xClient-side SPA routing
maplibre-gl4.7.xWebGL map engine — GPU paint expressions
axios1.7.xHTTP client (used only for the /api/status call)
vite6.0.xDev server and production bundler

Pages

The router (App.jsx) defines three routes. Any unmatched path redirects to /.
Page componentRoutePurpose
<HomePage />/Landing page with CTA button linking to /scouting
<ScoutingPage />/scoutingMain scouting tool — header + sidebar + full-screen map
<HowToUsePage />/como-usarStatic how-to page with centred text content

ScoutingPage Layout

┌────────────────────────────────────────────────────────────────┐
│  HEADER (56px, --color-primary background)                     │
│  UrbanViable  │  Inicio   ¿Cómo usar?  │  ✅ Datos: 01/01/26  │
├────────────────┬───────────────────────────────────────────────┤
│                │                                               │
│  SIDEBAR       │   MAP CANVAS (full remaining height)         │
│  (320px fixed) │   MapLibre GL JS — CartoDB Dark Matter base  │
│                │                                               │
│  SCOUTING      │   Navigation controls (top-left)             │
│  SCORE         │                                               │
│  ──────────    │   Dynamic heat map:                          │
│                │   · Gray   → sections with zero score        │
│  VARIABLES     │   · Blue → Orange → Red: rising score        │
│  ──────────    │                                               │
│  [Sliders ×7]  │   Click any section → popup + sidebar panel  │
│                │                                               │
│  INFORMACIÓN   │                                               │
│  DE ZONA       │                                               │
│  ──────────    │                                               │
│  [Tooltip]     │                                               │
│                │                                               │
└────────────────┴───────────────────────────────────────────────┘

Components

ComponentFileResponsibility
MapViewercomponents/MapViewer.jsxInitialises MapLibre map, adds source and layers, fires click/hover events
ToolPanelcomponents/ToolPanel.jsx320 px sidebar — wraps all ScoreSlider instances and the Tooltip
ScoreSlidercomponents/ScoreSlider.jsxSingle <input type="range"> with label, percentage readout, and description
DataStatuscomponents/DataStatus.jsxHeader badge showing dataset freshness — ✅ or ⚠️
Tooltipcomponents/Tooltip.jsxCensus-section detail panel rendered inside the sidebar on feature click

useMapStyle Hook

hooks/useMapStyle.js — watches the weights object and calls map.setPaintProperty with a freshly built MapLibre GL JS interpolate expression every time any weight changes, translating the React state into a GPU-side color ramp with zero latency.

Key Constants

constants/variables.js exports two objects that drive every part of the scoring UI:
  • VARIABLES — array of 7 descriptor objects (one per indicator). Each entry carries the normalised property key used in paint expressions (key), the human-readable label, a short description shown beneath the slider, and the absolute-value metadata (absKey, absLabel, absFormat) used by Tooltip.
  • DEFAULT_WEIGHTS — plain object mapping each key to its initial slider position (0–1). Loaded into React state on mount; mutated by onWeightChange as the user drags sliders.

Development Server

cd frontend
npm run start
# → Vite dev server at http://localhost:5173
In development the frontend loads galicia_scouting.geojson directly from the public/ directory via a fetch() call — no TileServer GL instance is required. Set VITE_REACT_APP_TILE_URL to an empty string (the default) and place the file at frontend/public/galicia_scouting.geojson.

Next Steps

Scoring Engine

How useMapStyle builds MapLibre GL JS paint expressions and computes the weighted score on the GPU.

Component Reference

Prop tables and behaviour details for all five React components.

Configuration

Environment variables, build command, and Nginx deployment.

Deployment

Docker Compose setup for TileServer GL and Nginx in production.

Build docs developers (and LLMs) love