Case study | InCuencaEcuador.com
Turning messy public transit data into a map people can actually trust.
A data-driven transit and local-guide platform for Cuenca, Ecuador. It transforms inconsistent public sources — PDFs, municipal datasets, shapefiles, GTFS exports, and map data — into a public bus map, a place-based city Atlas, and a private review workspace for resolving uncertainty before publication.
The problem
The sources disagree with each other — and most maps pretend they don't.
Cuenca's transit information lives in mixed-quality sources: route PDFs, municipal datasets, shapefiles, GTFS exports, public map data, and manual corrections. Those sources disagree on route names, directions, stop names, coordinates, and geometry. A naive approach would pick one source, draw the lines, and present the result as settled fact.
I designed the project around the opposite premise: normalize the data while preserving where each piece came from, make ambiguity visible to reviewers, give the public a clear browsing experience that never implies live arrivals or trip-planning accuracy the data can't support, and keep internal QA tooling strictly separate from public-facing content.
The system
One pipeline, three product surfaces.
Cuenca Atlas
A map-led city guide for parishes, neighborhoods, places, landmarks, trails, stories, nearby context, and relevant transit access.
Bus Map
A route-and-stop explorer with route search, directional display, stop context, route-density modes, and issue-reporting affordances.
Line Review
A private workspace for checking route geometry, stop order, distance anomalies, source evidence, and unresolved data-quality issues.
Data pipeline & quality model
The hard part wasn't drawing routes. It was building a path from uncertainty to publishable data.
Parse source files into structured data
Route PDFs and source files become structured lines, directions, stops, sequences, schedules — and parse warnings, kept rather than discarded.
Build canonical stops and aliases
Spelling and naming variations resolve to canonical stop records with tracked aliases, so inconsistent names don't silently fragment the data.
Match against geographic candidates
Stops match to coordinates with Cuenca-area prioritization, and questionable matches retain warnings instead of being promoted as fact.
Generate a review queue
Uncertain route and stop relationships surface in an explicit queue for human review — ambiguity is a first-class state, not an error to hide.
Promote validated, tracked payloads
Reviewed data becomes deterministic, checked-in payloads that the public map and internal review surface build from on a clean checkout.
Key design decisions
Decisions I'd defend in a design review.
Line Review is deliberately unindexed and unlinked from public navigation. Public users get useful route context; reviewers get diagnostic detail. Combining them creates both usability and publishing-risk problems.
Route geometry, stop coordinates, and directional mappings carry provenance and fallback behavior rather than being treated as equally authoritative.
The frontend builds from a clean checkout with no dependence on ignored local analysis output. Deterministic generation is part of the product contract, not a convenience script.
A canonical route parser covers guide pages, the Atlas, Bus Map, Line Review, directories, and explicit not-found behavior — every state is addressable and predictable.
Shared MapLibre/PMTiles initialization, interactions, sources, popups, route layers, Atlas layers, and diagnostics live in focused modules extracted from what began as large UI components.
Keyboard focus states, Escape precedence, live-region feedback, mobile-sheet rules, and preview-first map interactions reduce accidental context switches — engineered, not bolted on.
What I learned
Lessons that transfer to any data-heavy product.
The hard problem wasn't rendering geo-data. It was knowing which source supplied a route or coordinate, what fallback was used, and when a result still needed human review.
The project deliberately avoids presenting route proximity as an arrival prediction, transfer guarantee, or live-service claim the underlying data can't support. Knowing what your product shouldn't say is a design skill.
Public users need simple exploration; reviewers need warnings, raw evidence, and diagnostic layers. One interface serving both does both badly.
Early versions concentrated map lifecycle, URL state, overlays, Atlas content, and review logic in a few large files. Refactoring established boundaries around routing, browser access, MapLibre initialization, data adapters, and layer modules.
Clean builds, deterministic output, validation thresholds, source precedence, and clear ownership are what make a data pipeline maintainable after the first month.
Sidebars, sheets, legends, controls, previews, and interaction modes collide fast on mobile. Screenshot matrices and accessibility checks are engineering practice, not cosmetic polish.
Current status
Core surfaces built. The next phase is quality, not features.
The three product surfaces, the data pipeline, a route/runtime refactor, and generated-payload contracts are in place. The deliberate choice for the next phase is to invest in quality engineering rather than greenfield feature creation — the kind of unglamorous work that determines whether a project survives contact with real users.