Skip to content

Repository files navigation

Marker: Golf

A "Letterboxd for golf courses." Explore and map every course in the US, log where you’ve played, build bucket lists, and plan golf trips with a grounded AI planner.

Marker is built as a domain-agnostic engine + skin: the engine owns reusable product behavior, including maps, discovery, lists, profiles, planning, and data interfaces, while the skin (in this case, golf) supplies the domain-specific vocabulary, attributes, theme, and data.

Highlights

12,640 US courses Built with my own ETL (OpenStreetMap + Overture, enriched with Wikidata, elevation, wind, season and USGS aerials). It matched a hand-labelled ground-truth set 50/50.
AI trip planner Type a brief like "long weekend near Monterey, links-style, one bucket-list course" and get a day-by-day itinerary you can refine. Out-of-season dates get a reason and a playable window. An end-to-end eval against the deployed function passes 48/48.
Flat infrastructure cost No metered map or places APIs. The basemap is a single PMTiles file on Cloudflare R2, pins are clustered on the device, and descriptions and embeddings are batch-precomputed once. The only per-user AI call is gated behind the subscription.
Security by construction Every user table uses Postgres row-level security, backed by SQL isolation tests. Entitlements are written only by the server-side RevenueCat webhook. There is also a community e2e suite that passes 23/23 against production with two accounts.
Engine / skin separation The engine code is forbidden from using golf vocabulary, and a purity lint in pnpm verify enforces the rule. Adding a new niche (ski resorts, surf breaks, national parks) means writing a new skin package and an ETL adapter.

How the planner can't hallucinate

free-text brief ──► parse (LLM, strict JSON schema)
                ──► retrieve 15–40 candidates (PostGIS + pgvector, our code, not the LLM)
                ──► compose itinerary from candidate IDs only (LLM)
                ──► validate: unknown IDs dropped, untraceable numbers rejected,
                    region checked against an independent geographic fixture
                ──► render from database IDs, never from model prose

When a request is impossible (for example, dates that fall outside the region's playing season), the planner declines honestly. It tells the user the reason and suggests a playable window instead of returning a plan that would be wrong. For the full reasoning, see docs/architecture.md and the eval harness in tooling/eval/plan-trip-eval.mjs.

Stack

App: Expo (React Native) · TypeScript · expo-router · MapLibre Backend: Supabase (Postgres, PostGIS, pgvector, Auth, Edge Functions) · Cloudflare Workers + R2 AI: Claude (Haiku for the planner, Batch API for grounded descriptions) · local embeddings Monetization: RevenueCat · Tooling: pnpm workspaces · EAS Build

Repository layout

apps/mobile          the engine app (Expo), niche-agnostic and lint-enforced
packages/core        skin contract + domain types
packages/skins/golf  vocabulary, theme, attribute schema, curated lists
tooling/etl          course data pipeline: extract → transform → enrich → load
tooling/eval         end-to-end grounding + community evals
supabase/            17 migrations, RLS isolation tests, edge functions
infra/tile-worker    edge-cached tile/photo/privacy worker
docs/                architecture, decision records, data-quality + eval reports

How it was built

I wrote the architecture plan and the decision records, then directed a small team of Claude sub-agents (mobile, backend, data, AI, release-ops and a reviewer; see .claude/agents) against them, using security reviews and evals as the gates between milestones. The commit history is written to be read. Messages explain why a change was made, including cases where an earlier fix didn't work.

Running it

See docs/DEVELOPMENT.md.

Data attribution

Course data © OpenStreetMap contributors (ODbL) and the Overture Maps Foundation. Aerial imagery comes from USGS NAIP (public domain). Additional facts come from Wikidata (CC0).

About

iOS golf platform for exploring 12,640 U.S. courses, tracking play, and planning trips with an AI-powered trip planner.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages