condottiero, based on gpx.studio, an online tool for creating and editing GPX files.
This repository contains the source code of the website.
Please create an issue if you find a bug or have a feature request.
Code contributions are also welcome, but except for obvious bug fixes, please open an issue first to discuss the changes you would like to make.
The website is translated by volunteers on a collaborative translation platform. You can help complete and improve the translations by joining the Crowdin project. If you would like to start the translation in a new language, please contact me or create an issue.
Any help is greatly appreciated!
The code is split into two parts:
gpx: a Typescript library for parsing and manipulating GPX files,website: the website itself, which is a SvelteKit application.
You will need Node.js to build and run these two parts.
cd gpx
npm install
npm run buildTo be able to load the map, you will need to create your own MapTiler key and store it in a .env file in the website directory.
cd website
echo PUBLIC_MAPTILER_KEY={YOUR_MAPTILER_KEY} >> .env
npm install
npm run devThe project can be deployed to Vercel as a monorepo. The gpx library must be built before the website.
-
Import the repository in the Vercel dashboard and set the Root Directory to the repository root (leave blank).
-
Add the following environment variable under environment variables:
PUBLIC_MAPTILER_KEY=your_maptiler_key
The website exposes a REST endpoint for generating GPX files programmatically from a list of points of interest.
Returns a .gpx file built from the provided POIs.
Request body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
pois |
array | ✅ | List of points of interest (max 500) |
pois[].lat |
number | ✅ | Latitude in decimal degrees [-90, 90] |
pois[].lon |
number | ✅ | Longitude in decimal degrees [-180, 180] |
pois[].name |
string | — | Waypoint name |
pois[].desc |
string | — | Waypoint description |
pois[].ele |
number | — | Elevation in meters |
pois[].sym |
string | — | GPX symbol name (e.g. "Flag, Blue") |
name |
string | — | GPX file and track name (default: "Generated route") |
description |
string | — | Metadata description |
create_track |
boolean | — | Connect POIs as a <trk> in order (default: true) |
color |
string | — | Hex color for the track line (e.g. "0055ff") |
example request:
curl -X POST https://your-site.vercel.app/api/gpx \
-H "Content-Type: application/json" \
-d '{
"name": "Giro del centro storico",
"description": "Tour a piedi dei principali monumenti",
"create_track": true,
"color": "0055ff",
"pois": [
{ "lat": 43.1122, "lon": 12.3888, "name": "something", "ele": 493 },
{ "lat": 43.1105, "lon": 12.3910, "name": "something", "ele": 490 },
{ "lat": 43.1135, "lon": 12.3875, "name": "something", "ele": 500 }
]
}' \
--output route.gpxResponse: application/gpx+xml, aka the generated GPX file as a download.
Each POI is added as a <wpt> (visible waypoint on the map). When create_track is true, a <trk> connecting all POIs in order is also included, with optional gpx_style:line color styling compatible with gpx.studio.
Returns a JSON description of the endpoint and a usage example.
The endpoint is implemented in:
website/src/routes/api/gpx/+server.ts
This project has been made possible thanks to the following open source projects:
- Development:
- Design:
- shadcn-svelte — beautiful components
- @lucide/svelte — beautiful icons
- tailwindcss — easy styling
- Chart.js — beautiful and fast charts
- Logic:
- immer — complex state management
- Dexie.js — IndexedDB wrapper
- fast-xml-parser — fast GPX file parsing
- SortableJS — creating a sortable file tree
- Mapping:
- MapLibre GL JS — beautiful and fast interactive map rendering
- GraphHopper — powerful routing engine
- OpenStreetMap — open map data used by most of the map layers, and by the routing engine
- Mapterhorn — high-quality open terrain data used by some map layers (including for 3D), and by the routing engine
- Search:
- DocSearch — search engine for the documentation
This project is licensed under the MIT License - see the LICENSE file for details.
