Case study | TrailKit — Trail Running Ecuador

Building a trustworthy geospatial publishing system for trail running.

TrailKit is a local-first content production and publishing platform that transforms GPX tracks, route metadata, race records, activity history, and field media into reviewed, privacy-safe public experiences for Trail Running Ecuador. The central challenge was never rendering a map — it was building a publishing workflow you can trust around uncertain, sensitive, and constantly changing geographic information.

Role: Designer, architect, and sole developer Stack: Python, Pydantic, FastAPI, PostgreSQL/PostGIS, Astro, React, MapLibre, PMTiles Status: Active, production-oriented development

The problem

A CMS makes publishing pages easy — and the important questions impossible.

Trail-running information exists in fragments: GPX files from different people and devices, hand-written route notes, race spreadsheets, social-media observations, photos with embedded GPS metadata, personal activity history, and partial or outdated access and safety information. Multiple recordings often describe what is effectively the same trail.

A traditional CMS would happily publish all of it. What it can't answer:

Which route representation is canonical when three GPX files disagree? Is this exact geometry safe to publish, and has access been verified? Are the photos licensed, credited, and stripped of sensitive GPS metadata? Which information is a source observation versus an editorial decision? Can the public site be rebuilt reliably from the underlying data?

TrailKit answers these through explicit data contracts, review states, generated artifacts, admin tools, and publication gates.

The system

From raw GPX to public site, with review gates in between.

Core

Route & geospatial processing

The Python trailkit_core pipeline turns GPX and metadata into canonical route packages: GeoJSON, elevation profiles, climb and segment detection, phases and critical sections, map and elevation SVGs, social graphics, content drafts, offline exports, media manifests, QA reports, and checksummed artifact manifests. Generated files are never the durable source of truth — source material persists, dist/ rebuilds.

Data model

Canonical trail networks

Individual GPX packages proved too narrow: multiple recordings describe options and variations within one real trail area. The public model evolved into an atlas of trail clusters, canonical network identities, route options per network, and source tracks retained as evidence. Public identities describe the trail experience — never internal filenames or importer history.

Public

Trail Running Ecuador site

A static Astro site: trail atlas, network and route-option pages, race calendar and detail pages, organizer and province views, media galleries, resources, and vocabulary — with public maps, elevation profiles, source-confidence indicators, and safety notices. It consumes only generated public-safe artifacts.

Internal

Authoring & review suite

Six standalone admin services — Media, Routes, Races, Publication, Training, and Transit — built on FastAPI with React/Vite map-first workbenches. They handle trace reconciliation, network geometry editing, media review and association, publication readiness, and rollback state, deliberately separated from the public site.

Data & privacy model

"Generated" does not mean "public."

As data accumulated, the project introduced a strict four-tier boundary. It's what lets the system retain rich internal information without ever leaking filesystem paths, raw GPX filenames, review notes, exact GPS metadata, object-storage keys, private activity history, or unpublished geometry.

Tier 1 Source data

GPX files, notes, spreadsheets, original media — durable evidence, preserved as-is.

Tier 2 Internal review artifacts

Diagnostics, warnings, review packets, contact sheets, source observations.

Tier 3 Public-safe projections

Validated, redacted artifacts containing only what the public needs.

Tier 4 Static site output

Rebuilt deterministically from projections — never edited by hand.

Media is the sharpest example: a photo can be technically available yet unpublishable. Publication depends on separate checks — identifiable people, GPS metadata revealing sensitive locations, credit and license state, availability of a safe public derivative, and whether the associated route is itself public. Review-first, not publish-first.
119Python modules in trailkit_core
68test files across the system
6standalone admin services
74races catalogued, with 179 courses
1,859media files scanned, 1,763 review records
20maintained Cuenca route directories

Documented snapshots from the architecture records, not permanent KPIs — the underlying data is actively refreshed.

How it evolved

Five phases, each earned by hitting the limits of the last.

Local-first route generation

Raw GPX became consistent route packages, graphics, drafts, and QA reports. Key insight: a trail website needs a production pipeline before it needs a CMS.

Public editorial experience

Generated artifacts became a public Astro site — bringing responsive layouts, i18n, map and elevation displays, and public-safe empty and error states.

Publication boundaries

More data made it clear that "generated" isn't "public." Explicit tiers separated source data, internal review artifacts, public-safe projections, and site output.

Database-backed authoring

File-based generation stayed for deterministic builds; PostgreSQL/PostGIS arrived where data needed relationships, history, multiple editors, geometry operations, rollback, and audit. A hybrid, not a rewrite.

Operational hardening

Artifact manifests, deterministic rebuilds, atomic SQLite generation, backup and recovery checks, OpenAPI contracts, static public-boundary scans, and CI isolation per admin app. Operating the system safely became the product.

Key design decisions

Decisions I'd defend in a design review.

Publication is a workflow, not a boolean

No simple published flag. Access, safety, attribution, editorial completeness, technical validity, media permissions, and geometry visibility are separate decisions with explicit review gates. Normal builds serve internal work; strict QA mode is the release gate.

Heuristics stay visibly heuristic

Climb detection, phases, and diagnostics are editorial aids, not automatic safety decisions. The system preserves manual overrides, review notes, source confidence, explicit uncertainty, and correction history. A useful guess is not a verified fact.

Public identity represents the real-world concept

Source files and recordings are evidence, not identity. The network/option model lets multiple recordings converge on a stable public concept instead of exposing importer history.

Domain workbenches over generic CRUD

Route and media editing are spatial and contextual. Editors get map-first workbenches with inspectors, route traces, elevation profiles, media associations, and command contracts — not generic forms.

Generated artifacts have strong boundaries

Editable source material, generated internal artifacts, public projections, and static output are distinct. Nothing gets silently overwritten; every rebuild is reproducible from a clean checkout.

Evidence is part of the product

For safety-relevant, location-sensitive publishing, "the code works" isn't enough. Exact commands, manifests, test results, boundary scans, screenshots, and human acceptance are first-class deliverables, maintained in a repo-owned ticket and evidence system.

What I learned

The map was never the hard part.

A geospatial content product is a data-governance product.

The UI is the final expression of a larger system. The difficult work was modeling identities, relationships, provenance, review state, publication policy, and uncertainty. Once those contracts were clear, both the public experience and internal tools became far easier to evolve.

Local-first was the right start — and PostGIS wasn't a reversal.

A local-first pipeline was fast to iterate, reproducible, testable with fixtures, and transparent. Moving mutable review workflows into PostGIS recognized that authoring state needs relational and audit capabilities — while files remain durable source evidence.

Media requires governance, not just rendering.

Public photo projections contain only what the public needs: public IDs, safe URLs, captions, credits, licenses, approved associations. Everything else — EXIF, GPS, processing details — stays behind the boundary.

Verification has layers.

Unit and contract tests, public-boundary scans, build verification, database integration, visual smoke testing, and human review each catch different failures. Treating them as one "test suite" hides which guarantee you actually have.

Systems must survive missing sources.

Public projections sometimes need rebuilding when original photos are unavailable. The answer: reuse only existing safe derivatives and fail explicitly when required durable assets are missing — never guess.

Current status

Substantially implemented, deliberately described as evolving.

The core pipeline, public Astro site, public projections, admin services, route/network tooling, media workflows, race catalog, and CI contracts are all substantially implemented. The system is designed to keep improving as more field data and editorial decisions arrive — calling it "finished" would misrepresent what it is.

Same honesty policy as everything on this site: the scale figures above are documented engineering snapshots. No claims about traffic, adoption, or accuracy percentages appear here because I haven't independently measured them.

Work in progress

Field-level access and safety decisions
Further database-backed authoring
Richer route and map editing
Media review history and reconciliation
Component and design-system parity
Complete visual proof for all public surfaces
Backup, recovery, and atomic publishing refinement

This is the system-design judgment I bring to a team — data contracts first, UI second.