<picture>
  <source media="(prefers-color-scheme: dark)" srcset="website/static/logo-dark.svg">
  <img alt="Logo of gpx.studio." src="website/static/logo.svg">
</picture>

[**gpx.studio**](https://gpx.studio)는 GPX 파일을 만들고 편집하는 온라인 도구입니다.

이 저장소는 [gpxstudio/gpx.studio](https://github.com/gpxstudio/gpx.studio)를 클론해서
**개인 NAS(Synology)에 자체 호스팅**하기 위해 커스터마이징한 포크입니다.

- 배포 주소: `https://gpx.dodo-lab.kr`
- 배포 방식: `website/`를 정적 빌드해서 Synology Web Station으로 서빙

## 원본 대비 변경 사항

### 기능 추가
- **자동차(Car) 라우팅 프로파일 추가** — BRouter(`car-fast`)를 이용, 기존 GraphHopper 기반 프로파일들과 별개로 동작
  ([routing.ts](website/src/lib/components/toolbar/tools/routing/routing.ts))
- **GPS 끊김 구간 자동 강조 기능** — 연속된 두 포인트 사이 거리가 최근 구간들의 중앙값 대비 3배 이상(그리고 15m 이상) 벌어지면
  트랙 색상의 보색으로 자동 강조 표시. View 메뉴에서 켜고 끌 수 있음(기본 켜짐)
  ([gpx-layer.ts](website/src/lib/components/map/gpx-layer/gpx-layer.ts))
- **한국어(ko) 완전 번역** — UI 문자열(`ko.json`)과 도움말 문서(`/help`) 전체 20개 페이지 번역,
  언어 선택 목록에 노출 ([languages.ts](website/src/lib/languages.ts))

### 버그 수정
- `[[language]]` 라우트 파라미터를 검증 없이 동적 import에 사용하던 문제 수정 — `/favicon.ico` 등 알 수 없는 경로 접근 시
  500 에러가 나던 것을 해결 ([hooks.server.js](website/src/hooks.server.js), [+layout.server.ts](website/src/routes/+layout.server.ts))
- `trailingSlash`를 `'always'`로 변경 — Synology Web Station 같은 일반 정적 서버에서 `/app`, `/help/*` 등의 경로가
  403/404 나던 문제 해결 ([+layout.ts](website/src/routes/+layout.ts))
- 앱 내부 메뉴의 "도움말" 링크가 상대경로(`./help`)라 위 변경과 충돌하던 것을 절대경로로 수정 ([Menu.svelte](website/src/lib/components/Menu.svelte))
- `getElevation()`이 CORS로 막힌 고도 타일 요청 실패 시 예외를 그대로 던져서 포인트 이동 작업 전체가 실패하던 문제 수정 —
  실패 시 조용히 고도값 0으로 폴백하도록 변경 ([utils.ts](website/src/lib/utils.ts))
- 내보내기(Export) 다이얼로그의 CSS 클래스 충돌(`relative`+`fixed`)로 다이얼로그가 화면 하단에 잘려서 뜨던 문제 수정 (현재는 다이얼로그 자체를 제거함, 아래 참고)

### 변경/제거
- **내보내기 후원 안내 다이얼로그 제거** — `Export...`/`Export all...`/`Ctrl+S`가 이제 팝업 없이 원본 파일명 그대로 바로 다운로드됨
  (`Export.svelte` 삭제, [Menu.svelte](website/src/lib/components/Menu.svelte)에서 직접 호출)
- 도메인 관련 하드코딩 문자열을 `gpx.dodo-lab.kr`로 변경 (OG/canonical 메타태그, `sitemap.xml`, PWA manifest, `robots.txt`)

## 자체 호스팅 시 알아둘 점 (CORS 제약)

`styles.gpx.studio` / `tiles.gpx.studio` / `overpass.gpx.studio`는 gpx.studio 팀이 직접 운영하는 서버로,
**`https://gpx.studio` 도메인에서 오는 요청만 허용**하도록 CORS가 설정되어 있습니다. 따라서 이 도메인 밖에서 자체 호스팅하면:

- 지도 스타일 4종(Liberty Topo, Liberty Satellite, OSM, OSM Topo)이 로드되지 않고, **자동으로 순정 OpenStreetMap 타일로 대체**됩니다(코드 수정 없이 정상 동작).
- 3D 지형(Mapterhorn), 고도 데이터 조회, 관심 지점(POI) 오버레이 레이어는 사용할 수 없습니다.
- 라우팅(GraphHopper `graphhopper.gpx.studio`, BRouter `brouter.de`)은 CORS가 열려 있어 정상 동작합니다.

## 개발 환경

원본과 동일하게 두 부분으로 나뉩니다:

- `gpx`: GPX 파일 파싱/조작용 TypeScript 라이브러리
- `website`: [SvelteKit](https://kit.svelte.dev/) 기반 웹앱

**Node.js 22 이상**이 필요합니다 (`website/.npmrc`에 `engine-strict=true`가 설정되어 있고,
일부 의존성이 Node 22+를 요구합니다).

### `gpx` 라이브러리 빌드

```bash
cd gpx
npm install
npm run build
```

### `website` 개발 서버 실행

지도를 표시하려면 [MapTiler 키](https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/)가 필요합니다.
`website/.env` 파일에 저장하세요.

```bash
cd website
echo PUBLIC_MAPTILER_KEY={YOUR_MAPTILER_KEY} >> .env
npm install
npm run dev
```

> 개발 서버(`npm run dev`)는 메모리를 많이 씁니다(테스트 시 약 800MB). 상시 배포에는 쓰지 마세요.

### 정적 배포용 빌드

```bash
cd website
npm run build
```

`website/build/`에 순수 정적 파일(HTML/CSS/JS)이 생성됩니다(테스트 시 약 34MB). Node.js 런타임 없이
nginx, Apache, Synology Web Station 등 아무 정적 파일 서버에 그대로 올리면 됩니다.

## 원본 프로젝트 정보

이 프로젝트는 다음 오픈소스 프로젝트들 덕분에 가능했습니다 (원본 [README](https://github.com/gpxstudio/gpx.studio/blob/main/README.md) 참고):

- 개발: [Svelte](https://github.com/sveltejs/svelte) / [SvelteKit](https://github.com/sveltejs/kit), [MDsveX](https://github.com/pngwn/MDsveX)
- 디자인: [shadcn-svelte](https://github.com/huntabyte/shadcn-svelte), [@lucide/svelte](https://github.com/lucide-icons/lucide/tree/main/packages/svelte), [tailwindcss](https://github.com/tailwindlabs/tailwindcss), [Chart.js](https://github.com/chartjs/Chart.js)
- 로직: [immer](https://github.com/immerjs/immer), [Dexie.js](https://github.com/dexie/Dexie.js), [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), [SortableJS](https://github.com/SortableJS/Sortable)
- 지도: [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js), [GraphHopper](https://github.com/graphhopper/graphhopper), [OpenStreetMap](https://www.openstreetmap.org), [Mapterhorn](https://github.com/mapterhorn/mapterhorn)
- 검색: [DocSearch](https://github.com/algolia/docsearch)

## 라이선스

원본과 동일하게 MIT 라이선스입니다 — [LICENSE](LICENSE) 참고.
