Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
인터랙티브 히치하이킹 지도에서 Hitchwiki·Hitchmap·커뮤니티 장소를 찾고, 평점·히트맵·경로 계획·전 세계 차량 공유 가능
Interactive hitchhiking map: find spots from Hitchwiki, Hitchmap, and the community. Ratings, heatmaps, route planning, share rides worldwide.
라이프스타일Python · JavaScriptGitHub @Hitchwiki온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기The map to hitchhiking the world
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
This project is deployed on the Hitchwiki server at the following locations:
• the Map maps.hitchwiki.org at/var/www/maps.hitchwiki.org
• the Nostr relay used as a the central data store wss://relay.maps.hitchwiki.org at /var/www/relay.maps.hitchwiki.org
Hitchhiking Map
maps.hitchwiki.org
The map to hitchhiking the world.
Report Bug
·
Request Feature
About The Project
This project is the continuation of a similar map on Hitchwiki that was present until 2022. Read this paper to learn more about the history.README 전문 보기 ↗This project is deployed on the Hitchwiki server at the following locations:
maps.hitchwiki.org at/var/www/maps.hitchwiki.orgwss://relay.maps.hitchwiki.org at /var/www/relay.maps.hitchwiki.orgThis project is the continuation of a similar map on Hitchwiki that was present until 2022. Read this paper to learn more about the history.
This project embraces Nostr - hitchhiking rides that are submitted are published as Nostr event following the data standard in the first place. So events on Nostr relays become the single source of truth (database) for hitchhiking rides that also other apps (not only this one) can contribute to.
Join the conversation about a map for hitchhiking in our Signal Chat.
This repository, Hitchwiki/maps.hitchwiki.org, is a fork of hitchmap/hitchmap.
Every ride submitted through maps.hitchwiki.org is published to the Nostr network following the hitchhiking data standard, so the data is open for anyone to use. There are two supported ways to consume it:
A snapshot of all rides is published on Hugging Face:
Hitchwiki/hitchhiking-rides-dataset
deploy/cron.sh.hitch/scripts/sync_hitchhiking_rides_dataset.py,
which reads dist/allPosts.json (the Nostr ride events fetched by
hitch/scripts/fetch_hitchhiking_events/).submission_time descending (newest first; nulls last).This is the simplest option when you just want a single, ready-to-analyze file.
If you run another hitchhiking platform and want to stay up to date, fetch rides
straight from the Nostr relays rather than downloading static snapshots. The
fetch_hitchhiking_events script does this and can filter by date and source,
so you can pull only recent rides or only those from a given app:
See that script's README for setup and usage examples.
Set up Python virtual environment, install requirements and download the latest database dump:
Works with Python 3.12.6
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp example.env .env
cp tests/hitchwiki_articles.json dist/hitchwiki_articles.json
And set the missing env variables and wiki bot passwords. If you do not have a Nostr key pair you can use the below snipped to create one:
from pynostr.key import PrivateKey
private_key = PrivateKey()
print(f"Private Key (nsec): {private_key.bech32()}")
print(f"Public Key (npub): {private_key.public_key.bech32()}")
Put file from https://simplemaps.com/static/data/world-cities/basic/simplemaps_worldcities_basicv1.901.zip into dist/ as worldcities.zip but any worldcities.csv file with city, country, population column works.
# recommended for local testing
sudo docker compose up --build
# or to deploy for production
sudo docker compose up --build -d --remove-orphans
# connect to the container
sudo docker exec -it hitchhiking-map /bin/bash
# if down just:
sudo docker restart hitchhiking-map
sudo docker stop hitchhiking-map
sudo docker rm hitchhiking-map
Pick the lightest option that covers the files you changed. The host's ./hitch/static, ./hitch/templates, ./dist, ./db, and ./logs are bind-mounted into the container (see docker-compose.yml), so changes to those files are visible inside the container immediately — only Flask's in-process caches need busting. Anything else lives in the image and requires a rebuild.
| Changed files | What to run | Why |
|---|---|---|
hitch/static/** (CSS, JS, images), dist/** (generated JSON) | nothing — just hard-refresh the browser (or bump the asset URL to bypass the browser cache) | Flask reads static files from disk per request; the bind mount means the new bytes are already served. |
hitch/templates/** (Jinja .html) | sudo docker restart hitchhiking-map | Files are bind-mounted, but Jinja caches compiled templates in memory — a process restart drops the cache. No image rebuild needed. |
Python source: hitch/**/*.py, settings.py, hitch/scripts/**, hitch/scripts/fetch_hitchhiking_events/** (TS), requirements.txt, Dockerfile, deploy/run.sh, deploy/cron.sh | sudo docker compose up --build -d | These are baked into the image at build time (not bind-mounted), so the running container keeps the old copy until the image is rebuilt and the container recreated. |
docker-compose.yml, .env | sudo docker compose up -d (add --build if image contents also changed) | Compose recreates the container so new env vars / volume / port settings take effect. A plain docker restart keeps the old container config. |
db/*.sqlite schema (new column added to a model) | run the manual ALTER TABLE against the prod DB before rebuilding — see CLAUDE.md → "Database migrations" | There is no migration framework; flask init won't add columns to existing tables. |
In order to run the project continuously, use deploy/cron.sh to set up corresponding cronjobs to update the views and deploy/apache.conf as a basic NGINX configuration.
sudo cp deploy/apache.conf /etc/apache2/sites-available/25-hwmaptest.conf
# install the following
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
# to start the deployment
sudo apachectl configtest
sudo systemctl reload apache2
To enable it put the verification file like googlexxx.html into dist/.
If you find the data collected and provided by maps.hitchwiki.org helpful, feel free to cite it using:
@misc{hitchhiking,
author = {Till Wenke},
title = {Dataset of Hitchhiking Trips},
year = {2025},
url = {https://maps.hitchwiki.org},
}
A copy of the SQLite database is uploaded weekly (Sundays, 1 AM) to the Google Drive of [email protected], into the hitchwiki_maps-backups folder. The last 4 weeks are kept.
User emails are replaced with placeholders (user<id>@example.invalid) before upload, along with 2FA secrets, phone numbers and login IPs. Password hashes are kept so the backup can restore working logins. Everything else is a complete copy.
See hitch/scripts/backup_to_drive.py and deploy/rclone.conf.example (setup runbook).
We are aware of the following applications making downstream usage of data collected under this or its predecessor project, we expect them to use correct attribution and licensing:
The software provided in this repository is licensed under AGPL 3.0. The Hitchwiki Maps database is licensed under the ODbL, the license used by OpenStreetMap.
The ODbL covers the database (the collection of spots and rides), but not the individual contents inside it (see ODbL §2.4). The individual reviews users contribute — their free-text comments and the username they publish under — are separately licensed under CC BY-SA 4.0. Re-use the database as a whole under the ODbL; re-use individual reviews under CC BY-SA 4.0 with attribution.
How we want to work on Hirchwiki Maps is defined in GOVERNANCE.md and refined in CONTRIBUTING.md.
Run the complete, deterministic test suite (Python API tests with coverage and browser-independent JavaScript unit tests):
make test
To run one side while developing:
make test-python
make test-javascript
Tests marked network contact live Nostr relays, so they are excluded from
normal local and pull-request runs. Run them explicitly when checking relay
health:
python -m pytest tests/ -v -m network
Pull requests receive an updated coverage overview comment with Python and JavaScript coverage percentages. The same report is available in the GitHub Actions run summary.
We use the highway=hitchhiking OSM tag to bridge the gap between official, everyday hitchhiking spots and unofficial ones submitted by users. Rides submitted near an OSM-tagged spot are automatically linked to it, connecting community-reported experiences with officially mapped infrastructure.
Spots that fall inside the same gas station / motorway service area or the same "road island" (the patch of land enclosed by the slip-roads of a junction) are the same physical hitchhiking spot even when the pins are tens of metres apart. show.py merges them into a single marker using two polygon tables built from OpenStreetMap:
service_area — built by sync_service_areasroad_island — built by sync_road_islandsThese are one-off jobs, not cron jobs. They make thousands of Overpass calls and the data barely changes, so run them manually only when you want to (re)build the polygons — e.g. on first setup or occasionally as new spots accumulate:
# inside the container (or any env with the app + DB)
flask --app hitch generate sync_service_areas # build/refresh service_area
flask --app hitch generate sync_road_islands # build/refresh road_island (run after service areas)
Both are slow but resumable: they snapshot their work to db/.<script>.snapshot.json / .progress.json, commit incrementally, and a re-run picks up where an interrupted one left off. On successful completion those checkpoint files are deleted (their absence is how you know a run finished). Re-running never deletes existing rows, so it's safe to re-run anytime.
They query the standard public Overpass endpoint (https://overpass-api.de/api/interpreter) with polite throttling and HTTP 429 back-off; override OVERPASS_BULK_URL to point at a different/bulk instance if needed. After a sync, the next show.py run automatically uses the updated polygons.
The map's route planner is powered by a graph built from real rides. For every ride with a destination, build_ride_routes.py fetches an OSRM driving route and records which other known start spots lie along it; corridors shared by multiple rides become the "repeatable" trees the frontend searches. It runs daily at 2 AM via cron, but you can rebuild it manually — inside the container (the host venv lacks shapely, so spot grouping would be skipped and routes would reference phantom spots):
# inside the container — full rebuild (never use --limit, it writes partial data)
sudo docker exec hitchhiking-map python3 /app/hitch/scripts/build_ride_routes.py --skip-detailed
This writes dist/repeatable_routes.json (+ oneoff_routes.json, test_routes.json). OSRM responses are cached in dist/route_cache.jsonl, so a rerun only fetches routes for rides added since last time.
Many hitchwiki.org / hitchmap.com rides reach us with only a start point — no destination — which leaves them out of the routing graph. Two occasional, manual batch jobs (not cron) infer destinations for these and store them in the derived_ride_location table (keyed by the Nostr d tag, distinguished by a kind column). show.py and build_ride_routes.py then merge a derived destination onto any ride whose stops lack one. Both are standalone python3 scripts; the prod DB is root-owned, so pass --db and run under sudo.
1. Mine the destination from the ride's comment (LLM). Some comments name the city the ride actually reached ("got a lift to Kayseri"). extract_destinations.py runs in three stages — a cheap regex prefilter, an LLM pass that decides which city (if any) each ride reached, and a geocode+store step (kind=derived-comment-city, is_exact=0 — the coordinate is a city centre inferred from prose). The OpenAI key is read from OPENAI_API_KEY only, never written to disk:
# stage 1 — find no-destination rides whose comment mentions arriving somewhere
python3 hitch/scripts/extract_destinations.py prefilter
# stage 2 — LLM extracts the reached city per comment (needs the key)
OPENAI_API_KEY=sk-... python3 hitch/scripts/extract_destinations.py extract
# stage 3 — geocode the cities against dist/worldcities.csv and upsert
sudo python3 hitch/scripts/extract_destinations.py geocode-store --db db/hitchhiking-prod.sqlite
2. Reconstruct chains of consecutively-logged rides. When a named user logged a whole trip in one sitting — a run of their no-destination rides entered minutes apart whose starts march in one direction — the start of each ride is, in practice, the destination of the one before it. derive_consecutive_destinations.py finds those chains and stores each ride's destination as the next ride's logged start (kind=derived-consecutive-ride, is_exact=1 — it's a real logged spot). It never overwrites a comment-derived row.
# preview the chains it would write (change nothing)
python3 hitch/scripts/derive_consecutive_destinations.py --db db/hitchhiking-prod.sqlite --dry-run
# write them
sudo python3 hitch/scripts/derive_consecutive_destinations.py --db db/hitchhiking-prod.sqlite
After running either enrichment job, regenerate the map data and routing graph so the new destinations take effect (both in the container):
sudo docker exec hitchhiking-map /usr/local/bin/flask --app hitch generate show --force
sudo docker exec hitchhiking-map python3 /app/hitch/scripts/build_ride_routes.py --skip-detailed
Not every ride on the map was logged here. Each ride carries a source naming the platform it was recorded on, and that decides whether our users can change it. The list lives in hitch/blueprints/utils/ride_sources.py.
| Source | Editable / claimable here? | Why |
|---|---|---|
maps.hitchwiki.org (THIS_NOSTR_SOURCE) | yes | logged on this site |
hitchmap.com | yes | legacy dataset imported by this project |
hitchwiki.org | yes | same |
liftershalte.info | yes | same |
triphopping.com | no | another platform's ride |
| anything else | no | unknown source, treated as foreign |
A ride is only writable when both hold:
our_ride_pubkeys(), derived from our_nsecs() — a list that today holds exactly NSEC). Holding the secret key is the point: editing republishes the ride as a kind-36820 event with its original d tag, and kind 36820 is addressable per (pubkey, kind, d), so the rewrite only replaces the original when it is signed by the same key. Sign with a different key and the rewrite lands beside the original — the fetch scripts' (pubkey, d) upsert then stores both and the ride is on the map twice, with no way to withdraw the first (NIP-09 honours only a deletion signed by its author).The second condition is the binding one in practice: the bulk imports went out under a key whose nsec we no longer hold, so those rides carry one of our source names but stay read-only. Only rides published under the current NSEC can be edited or claimed.
If a second nsec is ever added to our_nsecs(), the poster has to be taught to sign with the key matching the ride being rewritten — it currently always uses NSEC, so a second entry would turn an "edit" into a duplicate.
Editing keeps the ride's original source, so correcting an imported ride does not re-label it as one recorded here.
Deleting is not restricted this way — it writes a local RideReport row and never touches the relays, so anyone listed on a ride can hide it whatever its source (_user_can_delete_ride in hitch/blueprints/main.py).
Two hidden tap gestures. Both are deliberately undocumented in the UI; this is the list.
Tapping the heatmap button in the map-mode switcher nine times toggles a client-side test mode: in-ride submissions are short-circuited (submitBody in hitch/static/inride.js), so you can walk through the whole "Start hitchhiking" flow on a real phone without writing anything to the DB or the Nostr relays. From the fourth tap a toast counts down. While it is on, a draggable amber warning button sits under the search bar; tap it for an explanation and an exit. The flag is inride.testMode in localStorage — it survives reloads until you turn it off.
On /ride/<d_tag>, tapping the Share button five times offers to attach that ride to your account. Much of the map was logged without an account — people submitted anonymously before registering, and the whole hitchmap.com import arrived that way — so a hitchhiker who recognises their own ride can take it back. The claimed ride then counts on their profile, in their stats and trips, and becomes editable.
can_claim in ride_detail).d tag, the published_at tag, the original source and any anonymous co-hitchhikers. The page reloads afterwards, since the byline, the edit link and the delete button all change.POST /claim-ride/<d_tag>) re-checks all three conditions itself — the attribute on the button is only a hint — so a ride from another platform is refused with a toast saying where to edit it instead.logs/ride_ips.csv trail as a submission.Code: the script block at the bottom of hitch/templates/ride_detail.html, claim_ride in hitch/blueprints/main.py.