Files
geointel/frontend
Codex 301ecaccbd
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Bound responsive map explorer height
2026-07-19 02:51:06 +02:00
..
2026-07-18 06:37:54 +02:00
2026-07-19 02:51:06 +02:00
2026-06-16 23:36:32 +02:00
2026-06-16 23:36:32 +02:00
2026-06-16 23:36:32 +02:00
2026-06-16 23:36:32 +02:00
2026-07-18 06:07:44 +02:00

GeoIntel Frontend (Sprint 4)

React + TypeScript + MapLibre workbench for regional geographic analysis.

The persisted Kempen Regional Workbench is the automatic operational data context. Its datasets are loaded once for the complete official 28-municipality Vlaamse vervoerregio; the operator chooses Mol, another municipality or the complete region as a spatial work-area filter. The primary map no longer asks the user to choose a technical project or region before data becomes usable. Regional population and modern forest snapshots use the same current/evolution flow as Mol, while explicit project selection stays available under advanced management.

The Status workspace includes one compact Actualiteit en versiecontrole surface. It separates sources that are current, due for a catalogue review, require local integrity review or are local artifacts. Only attention items are expanded by default; all source detail remains available through disclosure. The refresh button reruns the local read-only audit and never downloads or replaces source data. A separate Officiële edities controleren action is the only trigger for bounded GRB/orthophoto catalog reads, the official Statbel population DCAT check and the official ALZ publication-page check. It presents official and local editions, layer/publication evidence and honest non-comparable version markers without starting an import or background poll. ALZ v1/v2 snapshots are labelled provisional; only the latest definitive v3 edition is compared with local history. Statbel reports the current population reference year separately from the sector-geometry edition and treats the old 2025 REDEGEO layout only as transition evidence. After that explicit check, the same surface shows a compact GRB refresh plan for buildings, roads, water and parcels. It states whether each local regional snapshot is current, updateable or needs review and shows the current object count. The UI cannot start the million-feature import: staging and checksum- confirmed application remain an operator action so a browser request cannot silently replace regional reference data. Existing snapshots remain visible as historical observations.

The user-facing shell is task based: Kaart, Bronnen, Kwaliteit, Beeldanalyse, Downloads, Status and Beheer. Internal benchmark projects, raw dataset metadata, provider capabilities, model registry details and QA evidence remain accessible through labelled advanced disclosures instead of competing with the normal workflow.

Detection defaults to the configured local YOLO asset and automatically selects an available raster and active model asset where possible. The model registry and preflight remain honest when PyTorch, Ultralytics, a local model file or a tile manifest is unavailable. The active building profile is operational but remains review-required: its current coverage-aligned benchmark is approximately precision 0.614, recall 0.606 and F1 0.607 over seven positive AOIs, with zero detections in all three pure-empty controls. A reviewed challenger remains inactive because it produced two detections in empty Postel forest.

Map-driven building analysis uses the documented footprint-IoU 0.25 and distinguishes model candidates from verified buildings. It shows persisted matches, precision, recall, F1, false positives and false negatives. The Quality workspace includes a paginated review queue for persisted detection-QA evidence. Reviews do not rewrite detections, GRB geometry or QA metrics.

The map-first explorer has two deliberate modes. Latest state selects the latest explicitly dated source snapshot without claiming an old edition is current, while Evolution lets the operator compare an earlier and later snapshot from the same series over a drawn rectangle. Results show units, absolute/percentage change, estimate status and source limitations. Added/removed/modified overlays only appear for stable source identities. When Evolution is opened from a current-only theme, the explorer automatically switches to the first available persisted series. Theme cards then show either the number and range of historical observations or Alleen huidige toestand, so a single GRB snapshot can no longer strand the workflow in an empty state. When a theme has multiple valid methodologies, a compact series selector keeps them explicit. Forest therefore defaults to the official modern 2013-2025 10 m series, while the separate 1778-1969 historical map series remains selectable and is never merged into the same trend. Regional building, water and road evolution uses the same selector after the partition-audited 1778/1873/1969 snapshots are provisioned. Historical built surfaces never replace current GRB building footprints in Latest state. The persistent top context bar follows the selected historical series while Evolution is active, so its source label cannot disagree with the result panel. Because these historical WFS classes are polygonal map surfaces, their metrics are hectares plus a supporting object count; generic live road/water line metrics are deliberately not shown.

Selection results use dataset-specific PostGIS summaries with end-user units. Building footprints, forest, water surfaces and parcels show intersected hectares; roads and linear watercourses show kilometres; population shows inhabitants with partial-sector estimates clearly marked. Intersecting object counts remain visible as supporting source evidence instead of being the only result. Water explicitly explains that volume cannot be derived without a reliable depth or bathymetry source. The advanced workbench remains available but is not required for the primary choose-theme, draw-area, read-result flow.

The primary workflow is deliberately short: choose a municipality or the complete region, choose a data theme, drag a rectangle on the MapLibre map and read the resulting PostGIS evidence. Releasing the drag runs the active theme query and every other available theme query for the same EPSG:4326 bbox. The active area_id constrains every drawn/manual selection to bbox ∩ Area; Volledig werkgebied uses a bbox enclosing the Area and therefore resolves to the exact persisted geometry. The result panel shows selection area, exact intersection totals, active-theme density, source identity and bounded feature properties. Map rendering remains capped at 1,000 features while total_feature_count reports the exact database count.

In the Flanders workbench, ruimtebeslag, open ruimte, population density, node value and service level may appear as Op aanvraag. Drawing a rectangle or choosing a municipality uses the existing backend Job/Dataset flow to acquire and persist those five official rasters for the exact selection, then shows all available semantic metrics together. Identical requests reuse the persisted artifact. The complete Flanders Area is deliberately unavailable for these rasters because it exceeds the backend safety ceiling; this does not limit vector or partitioned bathymetry analysis of the complete region.

Detection Lab only lists ready imagery rasters. Governed height, flood-hazard and thematic policy rasters remain available in the map explorer but are excluded from the Luchtbeeld selector.

Every cross-theme result now names the measured quantity next to the value, so a station water level, mapped area and line length cannot appear as an unexplained bare number. Current vector selections download as GeoJSON, current raster analyses download as JSON and historical comparisons download as JSON with their complete timeline and provenance. After a successful analysis, compact next actions carry the same spatial context directly into AI-vragen or Downloads. Bewaar in downloads first asks the backend to recompute and persist the active vector, governed raster or historical result; Downloads opens only when that traceable artifact exists.

For a rectangle in Laatste toestand, Herken gebouwen runs the complete operational image path without opening the technical AI screen: bounded official orthophoto acquisition, raster persistence, safe tiling, the active local YOLO model, Detection persistence and automatic QA against ready GRB buildings. The panel shows all stages and errors; successful detections open as an explicit AI-result overlay. Rectangles must be 128-1,024 m per side.

The theme catalog recognizes the governed vector, raster and partitioned sources through canonical source metadata. A theme is enabled only when a ready persisted Dataset exists, except for the five allowlisted Flanders policy rasters that explicitly show Op aanvraag. Other missing themes state Bron nog niet ingeladen; they never appear as zero-valued observations. The technical Map workspace remains available through Geavanceerde werkbank for derived datasets, QA/QC evidence and export operations.

The workbench uses a task-based shell instead of a single long panel stack. App.tsx still owns shared orchestration state, but Map is the default product entry and Overview, Data, QA/QC, AI Labs, Exports and System remain secondary workspaces with a persistent top context bar and an optional selection-detail drawer.

The premium V1 presentation layer lives in src/styles/premium.css. It groups navigation by Workspace, Analyze and Deliver, removes the permanent inspector column, gives desktop/ultrawide workspaces stable readable widths and switches narrow screens to full-width content with a horizontally scrollable navigation rail. API calls and workflow state remain owned by the existing hooks.

Current component boundaries

App.tsx remains the shared workspace orchestrator, while focused surfaces and pure map helpers are kept outside it:

  • components/overview/OverviewWorkspace.tsx owns status, source freshness, workflow progress and overview actions.
  • components/detection/DetectionLab.tsx owns the end-user detection flow; components/detection/DetectionModelManagement.tsx contains the collapsed operator-only model registry, profiles, assets and runtime diagnostics.
  • components/map/MapWorkspace.tsx owns the map workflow; components/map/mapWorkspaceUtils.ts owns pure bbox, metric, download and display helpers.
  • components/project/ProjectPanel.tsx owns explicit workspace management, including reversible archiving for non-canonical workspaces.

Normal screens use Dutch task language and friendly labels. UUIDs, file paths, checksums, raw model states and job terminology stay behind labelled technical disclosures. Archiving a workspace does not remove its data and the two canonical regional workspaces cannot be archived through the UI.

Data and Map are organized around the core daily workflow. Data shows Project, AOI and Dataset columns together on normal desktop widths, bounds populated lists inside their own panels and keeps create/upload forms in explicit disclosures. Map keeps the layer/AOI command surface and MapLibre frame first, then exposes provenance, BBox controls and raw feature inspection only when requested. Existing selection, export and QA actions are unchanged.

Regional workspaces are not truncated to the first API page. The frontend exhaustively loads paged Area and Dataset inventories, then keeps the Data workspace responsive with searchable 12-Area and 10-Dataset display pages. Collapsed Area catalogs and historical-detail content are mounted only when opened. This makes the 285-municipality Flanders workspace navigable without hiding or discarding any persisted source partition.

Wide and ultrawide screens keep a readable sidebar and centered work area, expand the MapLibre review frame and use extra horizontal space for Data, Analysis, AI and Export grids. The detail drawer overlays the work area only while open, so it does not permanently consume ultrawide canvas space.

The Map workspace defaults to an OpenStreetMap road basemap with visible attribution so uploaded vectors, AOIs and QA overlays appear on a real street context. Set VITE_MAP_STYLE_URL to a managed MapLibre style URL to override this for production or high-volume deployments.

Municipality-scale GeoJSON bounds are scanned incrementally and memoized instead of materializing coordinate arrays. This supports the complete Mol boundary and roughly 37k persisted GRB buildings without JavaScript argument-spread failures. The official boundary uses a dark teal map treatment, while active source layers and their legends use consistent theme colors and existing detection/change-result colors remain distinct.

When the public OpenStreetMap fallback is active, the Map workspace shows a basemap usage notice. This keeps the local/demo default honest and reminds operators to configure a managed style URL before production or heavier tile traffic.

Operational GIS testing is now available directly in the Map workspace. Users can choose a persisted vector database layer, load it on the map, reuse the selected AOI or active layer extent, run the existing persisted vector_features bbox query, save the result as a derived dataset, export the selection GeoJSON, choose a reference dataset and launch QA/QC without creating fake data or a parallel backend path. The guided workflow also includes a one-click full run action that executes query, derived dataset save, GeoJSON export and optional QA/QC in sequence with visible status. For repeated review, switch the run mode from Create new dataset/export to Reuse latest saved dataset for QA; this reruns QA/QC against the latest saved derived dataset without creating another dataset/export pair.

Large vector layers use viewport delivery instead of downloading one unbounded GeoJSON file. Datasets above 5,000 features load their persisted PostGIS geometries from the existing bbox-selection endpoint at zoom level 14 or closer, with a 1,000-feature cap per view. The Map workspace shows visible versus total feature counts and asks the operator to zoom further when the response is truncated. Small layers, AI result overlays, selections and QA evidence keep their existing complete-FeatureCollection behavior.

The Map workspace keeps database layers and analysis-result overlays explicit. Map content: Database is the default and is selected automatically whenever an operator chooses a persisted database layer. Analysis result is enabled only when a detection, segmentation or change-result GeoJSON is available. Switching modes changes only the rendered source; it does not delete persisted analysis results or dataset state.

QA/QC and Exports follow the same calmer density model. QA/QC keeps metric evidence, feature ids and raw findings available but compresses provenance and history surfaces so review starts from the selected check and map evidence actions. Exports uses denser handoff cards, latest-artifact cards and history filters so artifact creation and download paths are easier to scan.

When project data loads and no dataset is selected yet, the workbench auto-opens the first ready vector dataset. This gives Data, Map and Exports an immediately usable default context while preserving explicit user selection once the user picks another dataset.

Data and Map workspaces include mobile-density CSS for file inputs, dataset action buttons, map toolbar controls, range sliders and empty-map quick actions so narrow screens avoid accidental viewport overflow.

Map workspace now surfaces the selected AOI, active layer and rendered feature state before controls, then separates layer controls, provenance, the MapLibre frame and the feature inspector into focused surfaces. The underlying overlay, opacity and feature-selection behavior is unchanged.

Map workspace selection now also includes a Selection & extract panel. Clicking a rendered vector, detection, segmentation or change feature highlights it on the map, summarizes geometry type, coordinate count and EPSG:4326 bbox, shows properties as a table, and offers client-side selected-feature GeoJSON download plus property copy actions. This extracts only the currently loaded/clicked feature; rectangle or polygon spatial extraction against PostGIS remains a later backend query workflow.

QA/QC Results now separates persisted check summary, candidate/reference evidence, refresh/filter controls and result history into focused surfaces. Existing filters, refresh behavior, metric cards and stored result rendering are unchanged, with denser mobile grids for the same controls.

Change Detection now follows the same analysis workspace hierarchy: vector input controls, error/empty states, result metrics and warnings are separated into focused surfaces while the existing compare action and map overlay result flow remain unchanged.

AI Labs uses the same mobile-density baseline for Detection and Segmentation model cards, run forms, QA/result summaries and scroll-safe result tables. This keeps long model ids, tile paths and artifact paths from widening the workbench on phones.

Exports and System provider capabilities now use compact, mobile-safe cards for handoff actions, artifact filters and provider metadata. Long provider limitations, export ids and artifact paths wrap inside their cards instead of widening the workbench.

Export Center now separates export summary, handoff readiness, artifact actions, current export states and export history into focused surfaces. Provider Capabilities uses the same system-workspace rhythm with loading/error/empty cards, provider capability cards and dedicated attribution/license provenance cards.

The right-side inspector also uses mobile-safe metadata and tool panels. Dataset filenames, checksums, bounds, job JSON, raster/vector operation inputs and inspector action groups wrap or scroll within the inspector instead of widening the workbench.

Export Preview shows a compact JSON summary before the payload and keeps large JSON/GeoJSON handoff artifacts inside a scroll-contained preview shell. HTML report artifacts remain download-only.

Primary workbench navigation, overview shortcuts, inspector tabs and dataset action buttons now share visible keyboard focus styling. Inspector tabs are also bound to tab panels with ARIA metadata.

Raster and vector operation panels use structured group headings, compact helper text, field grids, action rows and inline error blocks so dense GIS controls remain scannable in the inspector.

Raster controls now start with a pipeline readiness surface for metadata profile, CRS readiness, preview artifact, tile manifest handoff and clip AOI state. Processing guardrails call out missing metadata, CRS, preview, invalid tile settings or unavailable raster processing before users run downstream GIS/AI operations.

QA/QC, exports and AI lab result panels use shared loading, error, empty and ready state cards. This keeps model registry failures, empty histories and result counts visually consistent across the workbench.

Detection Lab and Segmentation Lab now share the same AI workspace hierarchy: model capabilities, run controls, persisted results and QA controls are separated into focused surfaces. Existing run, filter, result loading and QA callbacks remain unchanged, but the screens are denser and easier to scan on desktop and mobile.

AI Lab run controls explicitly explain when no raster dataset is available, instead of only showing disabled detection/segmentation run buttons.

Detection Lab now provides one guided operational path for configured building detection:

  1. choose an existing raster or explicitly upload a georeferenced GeoTIFF;
  2. create canonical 512 px tiles with 64 px overlap through the existing raster API;
  3. run the read-only YOLO preflight for the selected local model asset;
  4. execute the existing persisted detection endpoint;
  5. load the persisted Detection rows and GeoJSON and open them on the existing MapLibre map.

The browser never manufactures manifest content, detections or QA metrics. Manual manifest paths and direct-manifest execution remain available only under technical tile settings. Detection QA remains the existing persisted reference comparison and is shown as a primary review step.

Before creating tiles, the guided action inspects raster dimensions and estimates the number of 512/64 tiles against the backend-reported YOLO_MAX_TILES. Oversized imagery is stopped before tile files are written and must first be clipped to the intended work area. Repeated runs reuse the currently linked manifest.

Scope implemented

  • API client layer (src/services/api)
  • Project and area list/create flows
  • Vector and raster dataset upload + metadata display
  • MapLibre map with uploaded feature preview

Sprint 2 additions

  • Dataset manager details now shows:
    • dataset type
    • processing status
    • file size
    • vector feature count
    • vector bounds
    • file metadata (original/stored filename, MIME type, SHA256)
    • raster metadata preview when available
  • Vector inspection and raster metadata endpoint support in API client
  • Readiness indicator for uploaded datasets

Sprint 3 additions

  • Dataset detail panel now includes:
    • available operations
    • operation run actions (clip, buffer, intersect)
    • linked job list and status details
    • derived dataset navigation from job output
  • Raster operation callouts for unavailable processing states
  • Vector operation summaries integrated in selected dataset view

Sprint 4 additions

  • Dataset detail panel now includes raster-specific runtime metadata:
    • driver, dimensions, band count, bounds, CRS
    • storage details (size_bytes, checksum_sha256)
  • Added action buttons for raster operations:
    • regenerate/inspect metadata
    • generate preview
    • generate tiles
    • clip by selected area
  • Added clear unavailable states for raster ops when backend returns RASTER_PROCESSING_UNAVAILABLE
  • Added operation/job result visibility for raster runs with derived dataset navigation

Sprint 5 additions

  • Added raster band statistics display in the dataset detail panel (min/max/mean/std/nodata ratio/valid pixel count).
  • Added raster reproject workflow in UI (target CRS + resampling) with visible errors for invalid CRS/dependency gaps.
  • Added stronger raster tile/clip result context with consistent job status display and derived output links where produced.
  • Added tile manifest-aware controls for raster tile generation parameters.

Sprint 6 additions

  • Added spectral index controls in dataset detail panel:
    • NDVI with NIR/Red band inputs
    • NDWI with NIR/Green band inputs
    • NDBI with SWIR/NIR band inputs
  • Added job-driven execution for local spectral index operations and result dataset linking.
  • Added clear error surfacing for dependency-unavailable index execution (RASTER_PROCESSING_UNAVAILABLE).
  • Added CRS/bounds/resolution context visibility for raster index source inspection.

Sprint 7B additions

  • Added a lightweight Provider Capabilities panel.
  • The panel lists GRB, OSM, manual and fixture provider status, configured state, authority level, supported layers, supported geometry types, query modes and limitation messages.
  • Provider Capabilities now labels GRB/OSM/manual/fixture as reference data source capabilities, not AI model choices.
  • GRB and OSM are shown as not_configured; the UI does not expose a live import/download action for them.
  • Existing dataset, reference and QA/QC UI remains unchanged.

Sprint 8 additions

  • Added a minimal Detection Lab panel.
  • The panel lists detection model capabilities and clearly shows configured/not_configured status.
  • Users can select a raster dataset, choose a confidence threshold and request a detection run.
  • Unavailable model responses are shown honestly with the backend error code/message.
  • The UI does not claim real YOLO/PyTorch inference is enabled.

Sprint 8B additions

  • Detection Lab now exposes the yolo-configured capability reported by the backend.
  • When yolo-configured is selected, users can provide an existing raster tile manifest path.
  • Detection Lab lists local model assets from GET /api/v1/detection/model-assets so operators can choose an existing mounted model file instead of editing only one hidden YOLO_MODEL_PATH slot.
  • Detection Lab exposes explicit operator profiles for mounted local building detectors. The focused small-building model is the recommended recall-balanced 0.15 profile; the previous expanded-AOI 0.15 model remains available for higher precision, and the background-aware 0.35 model remains the conservative review choice. Applying a profile never downloads weights, changes runtime environment or starts inference automatically.
  • The recommended profile metrics are coverage-aligned with the current QA pipeline: mean precision 0.6141, recall 0.6062 and F1 0.6069 over seven independent Mol/Kempen zones, with zero detections in all three pure-empty controls. A higher-positive-F1 challenger remains hidden from approved profiles because it failed the Postel-bos empty-control gate.
  • Applying a profile deliberately selects the local model asset and threshold for the browser-run request; runtime default activation remains a separate guarded .env operation through scripts/activate_promoted_yolo_candidate.py.
  • Detection Lab includes a read-only YOLO runtime preflight panel with backend status, dependency visibility, local model configuration, torch/ultralytics versions, CUDA state and YOLO_CONFIG_DIR.
  • The UI still does not download models or create fake detections; backend status and error codes remain the source of truth.

Sprint 8C additions

  • Detection Lab now lists detection analysis runs and persisted detections.
  • Users can filter detections by class and minimum confidence.
  • Selected detection GeoJSON is rendered on the existing MapLibre workbench map.
  • Detection QA compares a selected detection run against a reference dataset and displays persisted QA metrics.
  • Detection QA also shows whether persisted inference-tile coverage was applied, how many reference features were raw/evaluated/excluded, and a clearly labeled diagnostic-only box-to-footprint envelope comparison. The main precision, recall and F1 display remains canonical footprint-IoU output.
  • No segmentation UI is introduced in Sprint 8C.

Sprint 9 additions

  • Added a minimal Segmentation Lab panel.
  • The panel lists segmentation model capabilities and clearly distinguishes placeholders, fixture/demo mode, SAM placeholder and YOLO-seg placeholder states.
  • Users can select a raster dataset, select a configured segmentation model, list segmentation runs and load persisted segmentation results.
  • Segmentation results display class, confidence, area, model, tile and mask path fields.
  • Selected segmentation GeoJSON is rendered through the existing MapLibre workbench map.
  • Segmentation QA compares a selected segmentation run against a reference dataset and displays persisted QA metrics.
  • Real SAM/YOLO-seg inference, model downloads and new AI dependencies are not introduced in Sprint 9.

Sprint 10 maintainability updates

  • Split large workbench sections out of src/App.tsx without changing UI behavior:
    • src/components/project/ProjectPanel.tsx
    • src/components/project/AreaPanel.tsx
    • src/components/providers/ProviderPanel.tsx
    • src/components/detection/DetectionLab.tsx
    • src/components/segmentation/SegmentationLab.tsx
  • App.tsx still owns shared state orchestration and API calls; extracted components receive the same state and callbacks as props.
  • Existing MapLibre overlay behavior, dataset/reference flows, Detection Lab flows and Segmentation Lab flows are unchanged.

Detection result scale and review

  • Detection Lab keeps the complete persisted detection collection available to the existing MapLibre overlay and QA/QC flows.
  • The results table renders 50 rows by default and provides 25/50/100 row sizes plus previous/next controls. This bounds DOM work for dense AOIs without discarding or resampling detections.
  • Selecting another run, changing a class/confidence filter or loading a new result collection resets the visible table to page one.
  • Source tiles display their filename for compact scanning while retaining the complete persisted path in a hover tooltip.
  • Pagination is intentionally client-side over the canonical persisted response; detection API contracts and GeoJSON output are unchanged.

Sprint 15 additions

  • Added a Projects panel action to load the explicit offline demo workflow.
  • The action calls POST /api/v1/demo/workflow and refreshes projects, areas, datasets and run lists.
  • Demo data is labelled fixture/demo data and does not represent live GRB/OSM data or AI inference.

Sprint 16 additions

  • Added a QA/QC Results panel that lists persisted project quality checks and metric rows.
  • The panel calls GET /api/v1/projects/{project_id}/quality-checks.
  • Demo workflow loading and QA actions refresh the persisted QA/QC result list.

Sprint 17 additions

  • Added an Export Center panel.
  • The panel can create persisted exports for:
    • project metadata JSON
    • project report HTML
    • selected vector dataset GeoJSON
    • selected detection run GeoJSON
    • selected segmentation run GeoJSON
  • Export records are listed from GET /api/v1/exports/projects/{project_id}/exports.
  • JSON artifact preview uses GET /api/v1/exports/{export_id}/content.
  • Artifact downloads use GET /api/v1/exports/{export_id}/download.
  • The UI does not introduce live provider downloads, a report designer or new AI behavior.
  • The HTML report is a lightweight artifact built from persisted project, dataset, QA/QC summary and export history state; it is not a PDF/report designer.

Sprint 18 additions

  • Added a Change Detection panel for comparing two vector datasets in the same project.
  • Change Detection uses the backend job envelope and renders added/removed/unchanged GeoJSON on the existing MapLibre workbench map.
  • The UI exposes IoU threshold and unchanged-feature inclusion controls.
  • The frontend does not infer fake object lifecycle states; it displays only the backend-provided added/removed/unchanged result.

Sprint 19 additions

  • Added V1 Map Workbench controls for the active GeoJSON layer:
    • visibility toggle
    • opacity slider
    • active layer label
    • loaded feature count
  • Added click-to-inspect feature properties from the active MapLibre layer.
  • Updated the app header to the V1 workbench identity instead of an old sprint label.

Sprint 20 additions

  • Area API responses now include persisted AOI GeoJSON for map display.
  • The Map Workbench renders the selected project area as a dedicated MapLibre GeoJSON layer.
  • Added area visibility and opacity controls alongside the existing active vector/result layer controls.
  • Area list items can select which AOI is shown on the map.

Sprint 21 additions

  • Loading the explicit demo workflow now opens the candidate vector fixture dataset directly, so the Map Workbench shows the demo vector layer without an extra manual dataset click.
  • The demo/export verification script now checks connected V1 state: area GeoJSON, fixture datasets, vector FeatureCollection content, vector feature summary, persisted QA/QC metrics and export downloads through the frontend proxy.

Sprint 22 additions

  • Added a compact V1 Workbench status strip above the main panels.
  • The strip summarizes existing connected state for project, AOI, datasets, active map layer, persisted QA/QC results and exports.
  • It suggests the next operator action based on missing V1 loop state without calling new APIs or adding backend behavior.
  • The status strip is implemented in src/components/WorkbenchStatusStrip.tsx and remains driven by App.tsx orchestration state.
  • MapLibre source/layer updates now wait for style readiness to avoid runtime blank-screen failures during first render.

Sprint 23 additions

  • Project report HTML exports now include a V1 readiness summary.
  • The report summary covers project, AOI, datasets, QA/QC, exports and known limitations.
  • Export Center behavior is unchanged; the richer handoff content is produced by the existing project report export action.

Sprint 26 maintainability updates

  • Detection workflow orchestration moved from src/App.tsx into src/hooks/useDetectionWorkflow.ts.
  • Segmentation workflow orchestration moved from src/App.tsx into src/hooks/useSegmentationWorkflow.ts.
  • Shared frontend API error formatting now lives in src/lib/formatError.ts.
  • Detection Lab and Segmentation Lab UI behavior is unchanged; App.tsx still wires the same panel props and shared project/map state.

Sprint 27 maintainability updates

  • Export Center orchestration moved from src/App.tsx into src/hooks/useExportWorkflow.ts.
  • QA/QC comparison and persisted quality-check listing moved from src/App.tsx into src/hooks/useQualityWorkflow.ts.
  • Detection and segmentation QA continue to share the same persisted QA/QC refresh path through loadQualityChecks.
  • Export Center and QA/QC UI behavior is unchanged; App.tsx still coordinates selected project, dataset and analysis-run state.

Sprint 28 maintainability updates

  • Dataset selection, upload form state, detail loading, dataset jobs and raster/vector operation orchestration moved from src/App.tsx into src/hooks/useDatasetWorkflow.ts.
  • Project-scoped dataset listing remains in App.tsx because it is still part of the shared project/area load boundary.
  • Dataset details, raster controls, vector controls and job list behavior are unchanged; the UI still receives the same callbacks and state.

Sprint 29 maintainability updates

  • Dataset upload/list rendering moved into src/components/datasets/DatasetPanel.tsx.
  • Dataset details and job-list rendering moved into src/components/datasets/DatasetDetailPanel.tsx.
  • Raster controls and vector controls now live in src/components/datasets/RasterControls.tsx and src/components/datasets/VectorControls.tsx.
  • App.tsx still owns cross-module orchestration and passes the same useDatasetWorkflow state/actions into these presentational components.

Sprint 30 maintainability updates

  • Persisted QA/QC result rendering moved into src/components/quality/QualityResultsPanel.tsx.
  • Map layer controls, MapLibre rendering and the feature inspector are now composed by src/components/map/MapWorkspace.tsx.
  • App.tsx still owns selected project, selected area, active layer and inspector state; the extracted components receive the same state and callbacks as props.
  • No map behavior, QA/QC API behavior, backend behavior, migrations or product features changed.

Release hardening updates

  • Production builds split application code, React vendor code and MapLibre vendor code into separate chunks.
  • The MapLibre chunk is intentionally larger than generic app chunks because it contains the GIS map runtime; the Vite warning threshold is set to keep this known vendor dependency visible without warning on every release build.
  • Export preview rendering lives in src/components/exports/ExportPreview.tsx.
  • The Export Center only offers JSON preview for JSON/GeoJSON artifacts; HTML project reports are shown as download-only artifacts.
  • Provider capability loading lives in src/hooks/useProviderCapabilities.ts.
  • Change detection orchestration lives in src/hooks/useChangeDetectionWorkflow.ts.
  • Derived MapLibre workbench state lives in src/hooks/useMapWorkspaceState.ts.
  • Project, area and dataset-list loading lives in src/hooks/useProjectWorkspace.ts.
  • Area fallback selection now lives with the owning workflow hooks: clip-area selection in useDatasetWorkflow.ts and map-area selection in useMapWorkspaceState.ts.
  • Offline demo workflow orchestration lives in src/hooks/useDemoWorkflow.ts, because it coordinates project, dataset, map, QA/QC, detection, segmentation and export state after the backend fixture seed.
  • Workbench bootstrap and reload effects live in src/hooks/useWorkbenchBootstrap.ts, keeping App.tsx focused on composing hooks into panels.
  • The workbench shell includes a compact command bar, consistent raised/sunken surfaces, structured empty states and scroll-safe AI result tables to keep the V1 workflow usable across desktop and mobile widths.
  • The shell includes a keyboard skip link, an explicit primary workspace navigation label and compact horizontal context/navigation rails on narrow screens so active workspace content is reachable without a tall preamble.
  • The Overview workspace separates readiness, status tiles and recommended next actions into distinct visual hierarchy regions, keeping the first screen scannable without changing workflow behavior.
  • The Overview workspace now also shows a compact workflow guidance rail for the V1 path from project and AOI setup through data, map review, QA/AI validation and export handoff.
  • When the V1 workflow is populated end to end, the Overview rail switches to a Ready for handoff state and keeps map guidance explicit about layer features versus AOI context.
  • Overview rail Map and Export clicks reuse the first ready vector/GeoJSON dataset when no layer or dataset is active, keeping the happy path connected without adding new API calls.
  • The Data workspace surfaces selected project, AOI and dataset context first, keeps creation/upload forms in closed-by-default disclosures and constrains large populated catalogs to independently scrollable panels.
  • The Export Center includes a handoff readiness summary, grouped artifact actions and provenance-rich export cards so report/GeoJSON handoff stays understandable in long-running demo projects.
  • The Export Center highlights the latest project report, project metadata, dataset GeoJSON, detection GeoJSON and segmentation GeoJSON artifacts with direct preview/download actions.
  • The offline demo workflow now selects the seeded raster fixture for Detection and Segmentation Lab prerequisites while keeping the candidate vector dataset open for Data/Map/Export review.

Workbench shell refactor

  • The primary UI is organized around workspaceNavItems in src/App.tsx.
  • The shell regions are:
    • workbench-topbar: active project, AOI, dataset and layer context.
    • workbench-sidebar: primary navigation between workflow workspaces.
    • workbench-main: one active workflow at a time.
    • workbench-inspector: optional selected dataset details and raster/vector operation controls, opened from the active workspace heading.
  • Existing API calls, hooks, MapLibre rendering and QA/AI/export flows are unchanged.
  • Stable navigation test anchors use data-testid="workspace-nav-{workspace}".
  • Mobile workbench navigation uses a full-width horizontal primary rail, avoiding the former fixed 152 px sidebar that compressed the active workspace.
  • Detection and Segmentation Labs present run controls first; model registry and YOLO preflight diagnostics remain available as collapsed detail surfaces below the operational workflow.
  • The Map workspace shows active layer source/provenance/draw-state context and selected-feature property chips before the raw JSON inspector.
  • When the Map workspace has no active result layer, it lists ready vector/GeoJSON datasets as direct quick actions so populated demo projects can jump straight from the empty state to map inspection.
  • The Map workspace can extract persisted vector features by area: open a ready vector dataset, use Start map bbox and click two map corners or enter EPSG:4326 bbox values, then run Run area extract to query backend vector_features. Results are highlighted on the map and can be downloaded as GeoJSON.
  • After an area extract, Save area export persists the selected FeatureCollection as a normal Export Center artifact (vector_selection_geojson) so the handoff remains in project export history.
  • Save as dataset persists the same selected FeatureCollection as a derived vector dataset, selects it in the workbench and keeps it queryable through backend vector_features for later QA/QC or analysis.
  • Once a map selection has been saved as a derived dataset, the Map workspace can run QA/QC against a selected reference dataset without switching workspaces. The action reuses the existing QA comparison endpoint and shows precision, recall, F1 and persisted quality-check status inline.
  • Map selection QA results also show persisted quality-check id, matches, false positives, false negatives, mean IoU and QA warnings. Open QA/QC evidence hands operators to the existing QA/QC evidence drilldown for the full parameters/findings record.
  • The Data catalog shows a compact selected/reference/candidate/source summary and scan-friendly badges. Persisted reference datasets are shown as Reference, non-reference vector/GeoJSON layers are shown as QA Candidates for workbench scanning, and raster/other uploads remain Source.
  • Dataset cards explain the recommended next action and use compact two-line action buttons for inspect, map, export/QA and metadata refresh. Disabled actions keep a visible reason, such as Vector/GeoJSON only.
  • Raster controls show the latest generated tile manifest path from persisted raster.tile jobs and can hand that path directly to Detection Lab or Segmentation Lab with the selected raster dataset.
  • The QA/QC workspace shows candidate/reference handoff cards and resolves persisted quality-check dataset IDs back to dataset names when the datasets are loaded in the current project context.
  • The QA/QC workspace includes a selected-check evidence drilldown with candidate/reference provenance, false-positive/negative metric evidence, map handoff context and parameters/findings JSON.
  • QA/QC findings now persist feature-level evidence in findings_json: matched candidate/reference feature ids with IoU, false-positive candidate feature ids and false-negative reference feature ids. The QA/QC drilldown renders these as compact evidence lists before the raw JSON.
  • Persisted QA/QC checks can be rendered as a Map workspace evidence overlay. The QA/QC panel calls GET /api/v1/projects/{project_id}/quality-checks/{quality_check_id}/evidence/geojson, then MapLibre draws matched candidate/reference geometries, false positives and false negatives with distinct styling and a compact legend.
  • Detection QA checks expose a filtered, paginated operator review queue through GET/POST /api/v1/projects/{project_id}/quality-checks/{quality_check_id}/reviews. The UI keeps confirmed model errors separate from reference gaps and box-to-footprint alignment mismatches.

Raster dependency visibility

Raster metadata and raster ops may remain unavailable when backend raster stack is missing. In that case:

  • raster uploads are still stored and listed
  • status becomes failed
  • backend returns explicit RASTER_PROCESSING_UNAVAILABLE responses for metadata/preview/clip/tile

Source inventory, evolution and local questions

The Sources workspace starts with a compact inventory of loaded themes and their real observation ranges. A collapsed follow-up catalogue distinguishes official sources that exist from datasets that are already persisted in the active project.

The Map result panel also loads a governed orthophoto product list. The most recent product retains the configured-YOLO plus current-GRB QA action. Official historical years/periods use the same bounded rectangle, persist as raster Datasets and render as MapLibre image overlays, but expose no misleading current-state AI/QA action. The Sources inventory moves Waterinfo and historical orthophotos from follow-up to loaded evidence only after such datasets exist.

Evolution mode compares the exact selected persisted Area when the full municipality/region action is used. It shows the selected before/after values, all compatible supporting metrics and a chart/table for every observation in the same source series. It never merges GRB current geometry with a differently measured historical land-use series.

AI-vragen is a separate local Ollama workspace. Users select one of the models actually installed on the server, ask about the active Area or drawn rectangle and can inspect how many metrics, time series and source datasets were supplied. Chat history remains in the browser session; source measurements are recomputed by the backend from PostGIS for every question.

Run locally

Prerequisites

  • Node.js 20.19+ or 22.12+

Install dependencies

cd frontend
npm install

Run locally

npm run start

Type check and build

npm run typecheck
npm run build
npm audit

The frontend uses Vite 7 and React plugin 5. Production remains a static nginx build; Vite is only the local/build toolchain. npm audit should report zero known vulnerabilities before a release build is accepted.

Dockerized frontend

docker compose up --build frontend

When using the repository Docker Compose stack, the frontend is published on host port 1202: http://localhost:1202.

The frontend API client uses same-origin requests by default. In Docker Compose, nginx serves the built frontend and reverse proxies /api and /health to the backend service, so browser clients on LAN hosts do not call their own localhost:8000.

The QA/QC workspace promotes core metrics into evidence cards before the raw metric list, keeping precision, recall, F1, mean IoU and false positive/negative counts scan-friendly while preserving the persisted raw metrics.

The workbench shell clamps page-level horizontal overflow on mobile while keeping the sidebar and workspace shortcut rows intentionally scrollable. Long QA identifiers and inspector values wrap inside their cards instead of widening the viewport.

The QA/QC result list includes client-side search, status and check-type filters plus a latest-results cap so long-lived demo projects remain scan-friendly without changing the API response shape.

The current-state Map explorer includes Natuurwaarde when the governed INBO BWK/Natura 2000 state-2025 Dataset is loaded. It shows exact mapped BWK area, separate official value classes, PHAB-derived Natura 2000 and regional-biotope hectares, uncertain habitat knowledge gaps and source provenance. This single edition is not exposed as a fabricated annual series in Evolution.

When definitive ALZ datasets are loaded, the Map explorer adds Landbouw as a separate theme rather than mixing it with cadastral parcels. Current mode shows declared-use hectares and official main-crop group hectares. Evolution mode compares any two persisted annual editions and charts the complete series. Object additions/removals stay hidden because annual parcel identity is not stable. The Sources inventory only labels the series available after real Datasets exist.

When the governed Buildings and Addresses Register snapshot is loaded for Mol, the Bebouwing theme automatically prefers that richer Dataset only while the exact Mol Area is active. It shows register lifecycle, unit/address aggregate metrics and GRB reconciliation without exposing address labels. Selecting another municipality or the complete Kempen scope falls back to the complete regional GRB building layer. This avoids presenting a Mol-only snapshot as regional coverage.

When a governed DHMV Dataset is loaded, the Map explorer adds Hoogte & reliëf. The active 5 m analysis raster is rendered as a colour-relief MapLibre image over the ordinary OpenStreetMap context. A drawn rectangle or the exact selected Area returns measured DTM/DSM height, relief and slope with TAW and the 2013-2015 source period visible. Raster cells are not presented as objects. GeoJSON export is disabled for this raster-only result, and the UI explicitly states that water depth and volume cannot be derived from DHMV.

When governed VMM scenarios are present, the Map explorer adds a separate Overstroming theme. It is deliberately not merged into Water: the latter describes persisted water surfaces and watercourse lengths, while the former is modeled flood hazard. A scenario selector keeps pluvial/fluvial, T10/T100/T1000 and current/2050 conditions visible before analysis. The persisted depth raster is shown through the existing MapLibre image-overlay pattern and a rectangle returns scenario-bound hectare/depth metrics. Raster GeoJSON export stays disabled. The UI never labels the maximum-depth area integral as current, permanent or concurrent water volume.

In the Flanders workspace, DHMV and VMM products do not need to be pre-provisioned before they become usable. The explorer reads the governed backend registries, exposes DTM/DSM and all twelve VMM scenarios, and acquires only the municipality or rectangle the user explicitly analyses. The acquisition still runs through the backend Job and Dataset boundaries; the browser never contacts WCS directly. An exact repeat reuses the persisted request. A complete-Flanders raster request remains disabled by the regional size guard, while a complete municipality remains a valid bounded analysis.

The same explicit-selection workflow exposes GRB buildings, roads, water and parcels. These are vector products rather than rasters: selecting a municipality or drawing a rectangle starts a bounded backend OGC API request, persists the complete clipped result and analyzes the persisted vector_features. Cards show Op aanvraag before first use and measured hectares or kilometres afterwards. Full-Flanders acquisition remains disabled by the 20 km side limit; users select a municipality or smaller rectangle. The map never calls Digitaal Vlaanderen directly and never displays a silently truncated reference layer.

Selecting Hoogte & reliëf shows the source distinction before analysis: DTM represents terrain after removal of buildings and other objects; DSM represents the visible surface including buildings and vegetation. Selecting Overstroming shows mechanism, climate context and return period. The result therefore cannot be mistaken for an observed current water level.

Regional VMM provisioning creates one scenario raster per municipality Area. For a municipality the explorer still uses only that exact Area-linked file. For the complete Kempen Area it presents the 28 VMM and DHMV partitions as one logical map layer, deduplicates VMM into twelve scenario choices and renders every matching MapLibre image partition. A drawn rectangle is sent to the partition endpoint, which opens only intersecting files and calculates exact combined cell statistics. A monolithic full-region 5 m calculation remains disabled because it exceeds the governed raster-cell limit; users draw a bounded rectangle without first choosing a municipality.

Every selection entry path forwards the active Area id. This includes dragged and coordinate rectangles, manual bbox input, temporal comparison, saving a derived selection Dataset and the advanced GIS workflow. Backend geometry intersection therefore remains the authority for the municipality or regional boundary even when a rectangle extends beyond it.

Useful repository scripts

  • bash scripts/frontend_install.sh
  • bash scripts/frontend_typecheck.sh
  • bash scripts/frontend_build.sh
  • bash scripts/frontend_dev.sh

Key docs

  • docs/40-build-launch/SPRINT_1_SCOPE_FREEZE.md
  • docs/API_CONTRACTS.md
  • docs/REPOSITORY_CONVENTIONS.md

Area-aware map layer selection

Map themes can have both a complete regional Dataset and a smaller exact-Area snapshot from the same official source. The workbench prefers the Dataset whose area_id exactly matches the selected Area; when no exact snapshot exists, the regional Dataset remains available and the backend clips metrics and map output to the selected municipality or drawn rectangle. The Sources workspace reports overlapping BWK area snapshots as separate coverages and does not sum their feature counts as if they were disjoint observations.

Platform-wide source portfolio

The Sources inventory is organized around six end-user questions rather than provider technology: space/buildings, nature/agriculture, soil/relief, mobility/accessibility, population/services and climate/living environment. The central definitions live in src/lib/sourcePortfolio.ts.

The current Map explorer also recognizes the governed Ruimtebeslag, Open ruimte, Bevolking, Bereikbaarheid, Voorzieningen and Bodem Datasets. The first five render persisted raster PNGs with product-specific legends and return cell-based semantic metrics; Bodem renders the persisted DOV polygons and exposes soil attributes on feature selection. A single official snapshot never activates Evolution by itself. Evolution is enabled only when at least two comparable observations exist.

The domain cards count only matching ready Datasets as operational. Audited official sources that have not passed acquisition, persistence and metric validation remain inside the collapsed follow-up list with an explicit priority and examples of the measurements they should eventually support. Theme/time-series detail and active-source limitations are also collapsed by default so the Data workspace stays readable.

Bathymetry profile map theme

Ready vmm_vha_bathymetry_profiles Datasets activate the Waterbodem map theme. The layer renders persisted profile points through the existing MapLibre/GeoJSON path. Clicking a point shows the watercourse, profile number, measurement date, nullable registered depth and an allowlisted official VHA profile-document link.

The UI always labels the points as historical cross-sections. It does not present them as a continuous bed raster and does not calculate water volume. Municipality partitions remain hidden for a regional Area until their backend manifest reports complete coverage. The Sources workspace lists MDK North Sea as read-only probe-only and SPW Walloon bathymetry as planned until bounded raster/download acquisition is operational.

For a complete regional manifest, the theme card totals all data-bearing municipality partitions instead of displaying one representative partition. A regional rectangle or full-Area analysis calls the partitioned backend selection and draws only its bounded GeoJSON result. Switching to a municipality automatically returns to the exact single-Area Dataset. Regional downloads are recomputed server-side through the same manifest-aware path.

On-demand forest, agriculture, nature and soil

In the Flanders workspace, Bos, Landbouw, Natuurwaarde and Bodem are discoverable before local provisioning. They remain Op aanvraag until the user selects a municipality or draws a bounded rectangle. Forest and agriculture use thematic raster analysis; nature value and soil use the persisted-vector GeoJSON pattern. The browser calls only the GeoIntel API and never contacts WCS, WFS or OGC providers directly.

Belgium and Belgian North Sea coverage

When Belgium and North Sea Workbench exists with ready reference data, it is preferred over the legacy Mol/Kempen workspaces at startup. Mol and Kempen remain regression workspaces and can still be selected normally.

Drawing a rectangle on the Map invokes the GeoIntel coverage resolver after a short debounce. The map displays every intersected land or legal sea zone and the active theme as Beschikbaar, Gedeeltelijk, Niet gekoppeld or Niet ondersteund. The same resolved zones determine which on-demand source is eligible: GRB for Flanders, SPW/PICC for Wallonia and UrbIS for Brussels. Products are filtered by both theme and coverage_zones; a coastal or cross-region selection remains visibly split and separately persisted. The browser never calls NGI, SPW, UrbIS, RBINS or MDK directly and never promotes an audited catalog entry to operational data without a matching ready Dataset.

Frontend release tests

Run the deterministic component/hook regression suite locally:

npm run test:unit

Install the browser runtime once and execute the live Belgium/North Sea journeys from the repository root:

npx playwright install chromium
bash scripts/run_rc8_release_journeys.sh \
  http://192.168.10.150:1202 \
  artifacts/rc8-release-journeys \
  artifacts/rc8-golden-areas.json

The live runner expects a healthy GeoIntel deployment with PostGIS, the configured local Ollama integration and the configured local YOLO model. It uses only the explicit technical demo-fixture flow for AI validation. Runtime screenshots and the machine-readable manifest are ignored build evidence and must not be committed.

Run the loading, accessibility, responsive-layout and performance-feedback audit at the release viewports:

bash scripts/run_rc9_ux_audit.sh \
  http://192.168.10.150:1202 \
  artifacts/rc9-ux-audit

The audit covers 390x844, 1366x768 and 2560x1080, every top-level workspace, keyboard operation of the analysis period, skip-link focus, delayed bootstrap truthfulness and visible coverage timing. The enforced limits are documented in docs/UX_PERFORMANCE_BUDGETS.md.