Geospatial Web Lab

Five geospatial applications covering service requests, data validation, simulated fleets, parcel scenarios, and 3D inspections, each built with a Rails and PostGIS backend and as a standalone browser edition.

My contribution

I built the five applications and their standalone browser editions as an AI-assisted personal learning project. All records are synthetic, the suite has no public deployment, and it has not been load-tested, security-certified, or used operationally.

Result: The September 29, 2026 verification records report 109 Rails tests with 690 assertions, 44 frontend tests, 13 browser scenarios, and five builds for the full-stack edition, and 51 domain, storage, and packaging tests, seven interface tests, and five static builds for the standalone edition, which also passed in a clean Ubuntu CI checkout.

Tools

  • Ruby on Rails
  • React
  • PostgreSQL/PostGIS
  • ArcGIS Maps SDK
  • CesiumJS
  • Redis and Sidekiq
  • IndexedDB
  • JSTS

The data is synthetic and the suite has no verified public deployment. The checks establish specific implemented behaviors; they are not load tests, security certification, or evidence of operational adoption. Docker image builds and runtime execution remain unverified.

Five workflows, each built twice

Geospatial Web Lab connects spatial data with the web workflows around it: reporting an issue, reviewing an import, tracking a simulated vehicle, comparing a planning scenario, and documenting an infrastructure observation. Each application has a full-stack edition and a separate standalone browser edition, so the same workflow can be compared with server-managed records and background jobs or with browser-managed state and local calculations.

  • Civic Works: geolocated service requests with linked maps and registers; text, category, status, and distance filters; staff assignment through permitted lifecycle states; GeoJSON imports that report rejected and duplicate records; and CSV exports.
  • Data Quality Portal: GeoJSON checks of required attributes, coordinate structure, geometry types, and topology. Invalid records are excluded only after an explicit acknowledgment, and approval stores a versioned export snapshot with a SHA-256 digest of its exact bytes.
  • Fleet Monitor: ten synthetic vehicles on replayable routes, with playback controls, trails, speed charts, staff-managed geofences, and sequence checks that reject older telemetry.
  • Parcel Scenario Explorer: 24 synthetic parcels with adjustable floors, coverage, and unit-area assumptions, and up to four saved scenarios comparing floor area, unit capacity, open space, and floor-area ratio.
  • Infrastructure Inspections: a CesiumJS corridor of eight synthetic assets, observations that staff resolve or reopen with history, and a 71-sample elevation profile exported as GeoJSON with source metadata.

Two architectures, distinct responsibilities

The two editions solve the same workflows with different engines. Standalone records never synchronize with the full-stack databases, browser processing stops when the page closes, and ArcGIS basemaps and SDK resources still need internet access.

How the full-stack and standalone editions divide the work
ResponsibilityFull-stack editionStandalone browser edition
Application dataSeparate PostgreSQL/PostGIS database per appSeparate IndexedDB database per app and browser origin
Identity and permissionsAuthenticated Rails APIs with ownership and staff checksLocally selected demo identities with simulated workflow rules
ProcessingRedis and Sidekiq workersJavaScript actions and a coordinated fleet timer
UpdatesAuthenticated Action Cable notifications, refresh, and pollingLocal subscriptions and compatible cross-tab notifications
Spatial operationsPostGIS validation, distance, area, and geodesic processingJSTS validity checks and documented JavaScript spatial formulas
DeliveryFrontend assets plus hosted backend servicesStatic files served over HTTP or HTTPS

Engineering decisions

  • Separate committed results from notification delivery: in the full-stack apps, a failed notification does not undo a successful write or calculation, and clients recover authoritative state through refresh and polling.
  • Treat concurrent work as normal: record versions reject stale edits, job revisions guard against obsolete results, and standalone storage transactions stop one tab from overwriting a newer state.
  • Preserve the inputs behind an output: approved exports, parcel calculations, and elevation profiles keep what is needed to explain their results.
  • Keep the originals: the standalone conversion added separate folders and dependencies, and all 371 previously tracked files were unchanged.

Verification by edition

Full-stack edition: 109 Rails tests with 690 assertions, 44 frontend tests, 13 browser scenarios against real local APIs, databases, Redis, and workers, and five frontend builds.

Standalone edition: 51 domain, storage, and packaging tests, seven interface tests, five static builds, and browser checks of persistence, calculations, simulation, approvals, and downloads. Its test and build pipeline also passed in a clean Ubuntu CI checkout.

Technical details

Independent learning project · AI-assisted · Synthetic data · September 2026

A useful geospatial application needs more than a map. It needs clear record ownership, validated inputs, understandable processing states, reproducible outputs, and reliable behavior when users edit concurrently or connections fail.

  • Build each workflow as a full-stack app: Rails APIs with ownership and staff checks, PostGIS spatial operations, and Redis and Sidekiq workers.
  • Build a separate standalone browser edition of each app with IndexedDB storage, simulated roles, and local spatial calculations.
  • Reject stale edits with record versions and guard asynchronous jobs against obsolete results.
  • Keep the inputs behind every export, parcel calculation, and profile, and store a SHA-256 digest with each approved dataset.
  • Leave the original full-stack implementations unchanged when adding the standalone editions.

Image viewer

100%