Flat file storage
Each course is a single .json file. Drop them in a folder, a CDN, or commit them straight to a GitHub repo. Zero database required to get started.
OpenSourceGolf Initiative
A free, open, community-maintained standard for structured golf course data — designed so any developer, researcher, or app builder can read it, write it, and build on top of it without permission or proprietary lock-in.
What is Open Course?
Golf is full of proprietary course databases locked inside paid subscriptions and closed APIs. Open Course is our answer to that — a lightweight, human-readable JSON data model that describes a golf course completely enough to power real, game-day applications.
T'doff uses Open Course as its native data layer. Every course powered by T'doff is represented as an Open Course document. That means the data that improves your game is transparent, auditable, and exportable — not trapped.
You can use Open Course data to build GPS apps, handicap trackers, practice simulators, course-review platforms, or anything else a golf developer can imagine. No license fees. No API keys. No middlemen.
The Specification
An Open Course document is a single JSON object. Here is the full structure, annotated with field purposes and types.
{
"id": "string — UUID v4, globally unique course identifier",
"name": "string — Official course name",
"slug": "string — URL-safe identifier e.g. pebble-beach-golf-links",
"location": { ... }, // see Location object
"timezone": "string — IANA timezone e.g. America/Los_Angeles",
"par": "number — Total course par",
"rating": "number — Course rating (decimal)",
"slope": "number — Slope rating (integer)",
"holes": [ ... ], // array of 18 Hole objects
"metadata": { ... } // see Metadata object
}
{
"address": "string — Street address (optional)",
"city": "string — City name",
"state": "string — State / province code e.g. CA",
"country": "string — ISO 3166-1 alpha-2 e.g. US",
"lat": "number — Latitude decimal degrees",
"lng": "number — Longitude decimal degrees"
}
{
"number": "number — 1–18",
"par": "number — 3 | 4 | 5",
"handicap": "number — Stroke index 1–18",
"tees": [ ... ], // array of Tee objects
"pin_positions":[ ... ], // array of PinPosition objects
"hazards": [ ... ], // array of Hazard objects (optional)
"layup_targets":[ ... ] // array of LayupTarget objects (optional)
}
{
"name": "string — Tee identifier e.g. Black | Gold | Blue | White | Red",
"distance_yards": "number — Measured tee-to-pin carry in yards",
"distance_metres": "number — Metres equivalent (optional)"
}
{
"id": "string — e.g. front | middle | back | custom label",
"distance_from_front_yards":"number — Yards from front edge of green to pin"
}
{
"type": "string — bunker | water | ob | trees | waste | lateral",
"side": "string — left | right | centre | carries (optional)",
"distance_from_tee_yards":"number — Carry distance to clear/avoid hazard (optional)",
"notes": "string — Free-text description (optional)"
}
{
"label": "string — e.g. Layup | Short-side safe | Bail right",
"distance_from_tee_yards":"number — Carry distance to target area"
}
{
"contributed_by": "string — GitHub handle or org name",
"last_updated": "string — ISO 8601 date e.g. 2026-02-22",
"version": "string — Semver of this document e.g. 1.0.0",
"license": "string — Always CC BY 4.0"
}
Full Example
This is what a real Open Course record looks like for a single hole. Scale it to 18 and you have a full course.
{
"id": "a3f1c920-8e44-4b2d-bf63-1d7e9a0c5521",
"name": "Harbour Pines Golf Club",
"slug": "harbour-pines-golf-club",
"location": {
"city": "Gosford",
"state": "NSW",
"country": "AU",
"lat": -33.4172,
"lng": 151.3526
},
"timezone": "Australia/Sydney",
"par": 72,
"rating": 73.2,
"slope": 137,
"holes": [
{
"number": 1,
"par": 4,
"handicap": 11,
"tees": [
{ "name": "Black", "distance_yards": 412 },
{ "name": "Blue", "distance_yards": 391 },
{ "name": "White", "distance_yards": 368 },
{ "name": "Red", "distance_yards": 312 }
],
"pin_positions": [
{ "id": "front", "distance_from_front_yards": 6 },
{ "id": "middle", "distance_from_front_yards": 17 },
{ "id": "back", "distance_from_front_yards": 29 }
],
"hazards": [
{
"type": "bunker",
"side": "left",
"distance_from_tee_yards": 230,
"notes": "Fairway bunker, steep face"
},
{
"type": "water",
"side": "right",
"distance_from_tee_yards": 195,
"notes": "Lateral hazard runs entire right side"
}
],
"layup_targets": [
{
"label": "Layup short of bunker",
"distance_from_tee_yards": 210
}
]
}
],
"metadata": {
"contributed_by": "opensourcegolf",
"last_updated": "2026-02-22",
"version": "1.0.0",
"license": "CC BY 4.0"
}
}
Build With It
The model is intentionally simple — a JSON file you can store, query, or serve any way you like.
Each course is a single .json file. Drop them in a folder, a CDN, or commit them straight to a GitHub repo. Zero database required to get started.
Wrap the files in any HTTP server and you have a course data API instantly. The flat structure maps directly to REST routes — /courses/:id/holes/:number.
Bundle course documents in your app binary for offline play. Parse with any JSON library on iOS, Android, or React Native — no proprietary SDK required.
Combine lat / lng from the location object with hole distances and hazard positions to render tee-to-green overlays on any mapping platform.
Par, stroke-index, and tee distances are all first-class fields. Your handicap calculator or scorecard app can consume Open Course documents directly.
Structured hazard, layup, and pin-position data feeds naturally into ML models for shot recommendation, course strategy, and performance analysis pipelines.
Join the effort
Open Course grows through community contributions. If you play a course and it isn't in the dataset yet, adding it takes less than an hour — and your contribution helps every golfer who plays there after you.
Start from the open-course-data repo on GitHub. Each course lives in its own .json file under /courses/.
Copy _template.json and fill in the fields. Tee distances, par, and hazard positions can usually be sourced from the course scorecard and walking the holes.
Run npm run validate in the repo root to check your document against the JSON Schema before raising a PR. The validator catches missing required fields and type mismatches.
Submit your PR with a short description of the course. A maintainer will review within a few days, and once merged your course is live in the dataset.
Contribution guidelines
notes if unsureLicensing
All Open Course data is released under Creative Commons Attribution 4.0. You are free to share and adapt the data for any purpose — commercial or otherwise — as long as you credit OpenSourceGolf.
Open Course by OpenSourceGolf
The spec is live, the schema is stable, and the community is growing. Grab the template and ship your first course today.