Wir wollen die OpenStreetMap Daten darauf überprüfen, wo Rechtsabbiegerpfeile einrichten nach StVo möglich ist.
  • TypeScript 85.7%
  • CSS 11.5%
  • Astro 2.7%
Find a file
2026-04-06 23:06:08 +02:00
data/input Rework 2026-03-15 20:55:04 +01:00
public/data Rework 2026-03-15 20:55:04 +01:00
scripts Rework 2026-03-15 20:55:04 +01:00
src Rework 2026-03-15 20:55:04 +01:00
supabase Rework 2026-03-15 20:55:04 +01:00
tests/turn-preview Rework 2026-03-15 20:55:04 +01:00
.env.example Rework 2026-03-15 20:55:04 +01:00
.gitignore Rework 2026-03-15 20:55:04 +01:00
AGENTS.md Rework 2026-03-15 20:55:04 +01:00
astro.config.mjs Rework 2026-03-15 20:55:04 +01:00
CLAUDE.md feat: implement community entry management and voting system 2026-03-14 18:10:06 +01:00
package-lock.json Rework 2026-03-15 20:55:04 +01:00
package.json Rework 2026-03-15 20:55:04 +01:00
README.md Update README.md 2026-04-06 23:06:08 +02:00
tsconfig.json Rework 2026-03-15 20:55:04 +01:00

Better Bike Turns

Static-first civic-tech web app for Karlsruhe bicycle right-turn-on-red screening. Note: the entire work has been done by @maxliesegang I (@Ivovic) am currently learning html and css and just opened the project on the open data days in Karlsruhe.

Stack

  • Astro
  • TypeScript
  • Leaflet
  • proj4
  • tsx
  • Optional Supabase vote sync over the REST API
  • Node.js >= 22.12.0

What ships today

The repository has two main parts:

  1. scripts/build-review-data.ts prepares static review data for Karlsruhe.
  2. The Astro frontend loads that generated data into a Leaflet review map.

The data build:

  • fetches Karlsruhe traffic signals, drivable roads, and bicycle infrastructure from Overpass
  • optionally imports official city bicycle green-arrow records from data/input/karlsruhe-official-green-arrows.csv
  • keeps only OSM traffic signals that can be linked to at least one plausible right turn onto a different road with bicycle infrastructure on the exit side
  • writes prepared JSON assets into public/data/

The frontend:

  • loads the generated manifest and OSM signal dataset
  • renders one marker per kept OSM signal
  • shows a right-turn preview when a signal is selected
  • shows screening notes and OSM tag status in the detail panel
  • supports local upvote/downvote review state, with optional shared vote sync through Supabase

The current UI does not load the official CSV GeoJSON as a separate map layer. Instead, official CSV matches are surfaced by marking the nearest kept OSM signal as official.

Product framing

  • The app is a review aid only, not an approval tool.
  • Every generated OSM signal remains a plausible review item that still needs expert review.
  • Official city records are used as context and matching evidence, not as automatic approval.

Local development

npm install
npm run data:build
npm run dev

If the generated files are missing, the app still boots but the review UI shows a missing-data state until public/data/ is rebuilt.

Generated files

npm run data:build writes:

  • public/data/karlsruhe-osm-car-signals.geojson: the primary frontend dataset, containing kept OSM signals plus screening metadata
  • public/data/karlsruhe-official-green-arrows.geojson: the imported official city records as a standalone reference/export file
  • public/data/karlsruhe-review-manifest.json: counts, heuristic metadata, disclaimers, and output paths

Overpass responses are cached under .cache/osm/, keyed by SHA-256 of the query body.

To force fresh Overpass responses:

npm run data:refresh

Screening heuristic

The current builder:

  • skips explicitly pedestrian-only signals
  • links each candidate signal to a nearby approach road and junction sample
  • honors traffic_signals:direction=forward/backward when a signal is mapped onto the linked approach road
  • uses mapped one-way traffic flow on the linked road before falling back to side-of-road inference
  • keeps only signals with at least one plausible clockwise right turn onto a different outgoing road
  • requires mapped bicycle infrastructure on the exit side of that turn
  • records crossing tags, signal offset, multiple plausible turns, and nearby official records as review notes instead of hard exclusions
  • stores a rightTurnHint with bearings and turn angle so the UI can render a preview arc
  • lets the preview note inherit a nearby named road corridor when the outgoing connector itself is unnamed but the aligned exit road makes the reviewed turn leg clear
  • lets the preview fallback stay on the signal's own road corridor when OSM splits that approach into connected continuation segments before the junction
  • marks only the single closest kept OSM signal within 25 m of an official CSV record as official

In the current generated dataset, kept OSM signals are classified as either highlighted or official.

Review UI behavior

  • Fit all zooms to the generated review dataset.
  • Basemap switches between OpenStreetMap street tiles and Esri satellite imagery.
  • Highlighted toggles the orange halo overlay for highlighted signals; it does not hide the underlying markers.
  • Clicking near overlapping markers cycles through nearby candidates. Shift+click also cycles.
  • Votes are stored locally in the browser by default.
  • When PUBLIC_SUPABASE_URL and PUBLIC_SUPABASE_ANON_KEY are set, the app also loads shared vote aggregates and upserts one vote per browser session and signal.

Without Supabase, votes stay in browser local storage under better-bike-turns:review-votes:v1.

Official CSV import

Place the city export at:

data/input/karlsruhe-official-green-arrows.csv

Accepted coordinate columns (first match wins):

Purpose Accepted column names
Longitude / easting lon, longitude, lng, x, easting, rechtswert
Latitude / northing lat, latitude, y, northing, hochwert
CRS override epsg, crs, srid
Record ID id, identifier, signal_id, geometry_id
Street name street, strasse, straße
Title / location title, location, name
Status status, state
Notes note, notes, comment, comments

If projected x/y coordinates are used without an explicit CRS column, the importer defaults to EPSG:25832.

Verification

npm test
npm run check
npm run build

Notes:

  • npm test exercises the right-turn preview geometry against the generated public/data/karlsruhe-osm-car-signals.geojson fixture.
  • npm run build builds the Astro site but does not regenerate public/data/.
  • npm run build:all runs the data build first and then the Astro build.

Optional Supabase vote sync

Set these public environment variables to enable shared vote sync:

PUBLIC_SUPABASE_URL=
PUBLIC_SUPABASE_ANON_KEY=

Apply the schema and policies from:

supabase/review_votes.sql

The schema enforces one vote per browser session per signal with unique(signal_id, session_id). The client uses plain REST calls and falls back to local-only voting if sync is unavailable.