ArticleReadMain page

Nathan's Technology Wiki / Projects

OpenTrail

An open-source hiking platform and the most complete example of product, security, data, and release engineering in this journey.

Project identity

OpenTrail is an open-source community hiking platform built around free trail knowledge, minimal tracking, open data, offline access, and community contribution. The repository history begins July 18, 2026 with a monorepo, PostGIS schema, NestJS API, and Next.js/MapLibre web MVP.

Working version1.1.0 in package manifests
Recorded release tagsv0.1.0 through v1.0.1
LicenseAGPL-3.0

The project charter is the source of truth for principles, planned features, deliberate deviations, and feature status. A separate future roadmap records post-1.0.1 work.

Shipped capabilities

Explore and understand trails

  • Oregon-wide OpenStreetMap trail import with idempotent upserts and stitched hiking relations.
  • Map-driven viewport and radius search, state filters, trail-name matching, and server-side location geocoding.
  • PostGIS geometry, full-text/trigram search, real elevation gain from terrain data, and connecting-trail discovery.
  • Parking, lodging, cabins, camps, parks, difficulty indicators, and route geometry.

Context, community, and safety

  • Weather forecasts and active alerts through a server-side National Weather Service integration.
  • Live wildfire information and proximity warnings.
  • Guest and account-based saved trails.
  • Moderated reviews and photos, user administration, bans, and role-aware moderation.
  • Email directions composed in the user's mail client without server-side mailbox access.

Architecture and stack

OpenTrail is a modular npm workspace. Deployable applications live separately from shared packages and infrastructure code.

LayerTechnology and responsibilitySecurity/operational boundary
WebNext.js App Router, TypeScript, Tailwind CSS, MapLibre GLRenders the experience and calls defined API contracts.
APINestJS, Swagger, validation, throttling, HelmetOwns authentication, authorization, business logic, and safe responses.
DataPostgreSQL 16, PostGIS 3.4, Prisma, raw geospatial/FTS SQLPrivate service with separated migration and runtime roles.
StorageMinIO with S3-compatible clientPrivate original uploads; approved transformed media only.
Jobs/cacheRedis and BullMQ-ready designProvisioned for imports and background work as needed.
Shared codeTypeScript shared packageStable contracts without turning the API into a library.

Geospatial data and performance

OpenTrail uses spatial database features rather than treating maps as decoration. Bounding-box and radius queries run against PostGIS. Map views snap to a zoom-aware cache grid so nearby pans reuse results, while responses are trimmed to the exact requested viewport.

  • OSM imports preserve open-data attribution and can be rerun safely.
  • Elevation is backfilled from digital elevation model tiles.
  • Parking and lodging use distance-based spatial relationships.
  • Search combines exact/partial trail names, full text, trigram similarity, and location geocoding.
  • Administrative cache metrics show hit rate and frequently viewed areas without making cache behavior invisible.

Accounts, sessions, and privacy

The implementation deliberately chose revocable opaque sessions rather than JWT access tokens for the current phase. Passwords use Argon2id at the documented OWASP baseline. Session tokens are 256-bit random values in HttpOnly cookies; only their SHA-256 hashes are stored, allowing immediate revocation.

  • Browsing does not require an account.
  • Guest saved trails survive signup or merge into an existing account at login.
  • Authentication routes have stricter throttling than general API routes.
  • Unknown-email and wrong-password attempts return indistinguishable behavior, including a dummy-hash verification path.
  • Secure-cookie mode is enabled when the application operates behind HTTPS.
  • Server-side geocoding prevents the user's address-search request from going directly to the external provider.

Moderation, media, and user safety

Reviews and photos are private to the moderation workflow until approved. Uploaded images are decoded and re-encoded to WebP while EXIF and GPS metadata are removed. Only approved media becomes public or can serve as a trail cover.

Administrators and moderators manage queues. A user ban requires a reason, revokes sessions, prevents login, and removes the user's public contributions in one transaction. Unbanning restores account access without silently republishing removed content.

Docker, permissions, backup, and recovery

The Compose stack contains PostgreSQL, a one-shot migration job, MinIO, API, Redis, and web services. Multi-stage images and health checks make startup order and runtime state visible.

Least-privilege database roles

  • A schema owner performs migrations.
  • The API runtime account receives table CRUD without DDL.
  • A separate human administration role supports controlled maintenance.
  • Strong credentials are generated into ignored configuration.

Recovery design

  • Database dumps preserve PostGIS application data.
  • Object storage requires its own backup and restore process.
  • Migrations are applied before application health is trusted.
  • Restoration is verified through health checks and a real trail journey.

Versioning, releases, and verification

The root and deployable packages share the working version. Release tags, CHANGELOG, CODE_CHANGELOG, HOTFIXES, release documents, smoke scripts, version checks, and domain-specific validation scripts create layered evidence.

PlanCharter and roadmap define outcomes, sequence, privacy principles, and deliberate exclusions.
BuildFocused web, API, schema, importer, or infrastructure changes preserve module boundaries.
PreflightBuild, migrations, smoke tests, version alignment, import validation, and security checks run; the wiki draft records the intended capability and architecture change.
PostflightProduction health, map/search behavior, accounts, permissions, data counts, and release identity are verified; the wiki is updated with the shipped result and lessons.

Hurdles and deliberate decisions

  • Trail data import moved earlier because an empty map cannot validate the product.
  • The API remains a deployable application, while packages are reserved for shared libraries.
  • Kubernetes and Terraform were deferred until deployment complexity justified them.
  • Moderation is currently a module rather than a separate service.
  • Opaque sessions replaced an earlier JWT idea to make revocation immediate.
  • Google imagery was avoided because its licensing is incompatible with the platform's open-data goals.
  • Redis is provisioned ahead of full background-job use, so unused complexity must remain visible.

Roadmap and future planning

The roadmap sequences bike access and suitability, live GPS progress, offline trail packs, wildlife sightings, OAuth, trust/reputation, condition reports, GPX uploads, mobile work, contributor onboarding, and a public beta. Each phase is evaluated against privacy, data licensing, offline behavior, operational cost, and whether the web MVP is stable enough to support expansion.

Roadmap rule
Future features are documented as planned until implementation, verification, and release evidence prove they are shipped.