factcircuit
FactCircuit: an auditable claim-and-evidence verification loop with immutable provenance, staged checks, bounded retrieval, and reproducible evaluation.
Veloroutenplaner für Zürich in zwei Varianten, schnell oder komfortabel. Rechnet Verkehr, Velostreifen, Tramgleise, Kopfsteinpflaster, Steigung und die Wartezeit an Ampeln mit, je nach Abbiegerichtung
Translation pending
DataTypeScript · JavaGitHub @moritzlauperOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Veloroutenplaner für Zürich in zwei Varianten, schnell oder komfortabel. Rechnet Verkehr, Velostreifen, Tramgleise, Kopfsteinpflaster, Steigung und die Wartezeit an Ampeln mit, je nach Abbiegerichtung. Mit Zwischenzielen, GPX-Export und teilbarem Link.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Eine Karte, auf der jedes Haus einer Stadt eingefärbt ist. Grundlage sind zwei Kennzahlen, zwischen denen man umschaltet: • ÖV-Erreichbarkeit: Wie gut das Haus an Tram, Bus und S-Bahn angeschlossen ist. • Kulturvielfalt: Wie breit das Kulturangebot in Velo- oder Gehweite ist. Gezählt werden Bars, Cafés, Bühnen, Kinos, Museen, öffentliche Kunst, Bibliotheken, Badis und Quartiertreffs.Read the full README ↗
Eine Karte, auf der jedes Haus einer Stadt eingefärbt ist. Grundlage sind zwei Kennzahlen, zwischen denen man umschaltet:
Drei Städte, je eine Route: Zürich auf / (47'085 Häuser), Basel auf /basel (23'308),
Bern auf /bern (20'540). Im Bedienfeld ganz unten wechselt man zwischen ihnen. Alle drei
laufen durch dieselbe Pipeline. Die Zahlen und Beispiele weiter unten sind die von Zürich.
Für Zürich gibt es ausserdem den Velonavi auf der Startseite /, ein Velorouter, der ruhige Strecken,
Steigung, Lichtsignale und Belag abwägt. Er rechnet vollständig im Browser, siehe
Velonavi.
Unter /wohnungen steht eine Wohnungssuche für die Stadt Zürich: Mietinserate aus mehreren
Portalen auf einer Liste und einer Karte, jedes mit der ÖV- und Kulturkennzahl des Hauses. Siehe
Wohnungen.
Wer Daten korrigieren oder die Seite selbst betreiben will, findet die Anleitungen unter
docs/daten-anpassen.md und docs/betreiben.md.
Die Karte ist schwarzweiss. Dunkel heisst gut angeschlossen, hell schlecht. Farbe kommt dazu, wenn man die Bestplatzierten hervorhebt: Ein Verlauf von kräftigem Dunkelrot bei Rang 1 nach Hellrot am eingestellten Ende. Beim Öffnen sind die Top 1000 hervorgehoben, der Regler geht von dort in beide Richtungen.
Eingefärbt wird nach Rang, nicht nach Wert. Beim ÖV liegen zwei Drittel aller Häuser zwischen 26 und 34 Minuten. Nach Absolutwert wäre die Karte fast einfarbig.
Die Kennzahl je Haus ist die mittlere Reisezeit zu einer beliebigen Adresse der Stadt, Türe zu Türe. Man zieht eine zufällige Zürcher Adresse und misst, wie lange man von diesem Haus im Schnitt dorthin braucht. Für das bestangeschlossene Haus sind es 20,5 Minuten, im Median 30,7, am Stadtrand über 45.
Es sind nicht summierte Minuten, sondern der Durchschnitt. Die Zahl bleibt eine Zeitangabe, die man ohne Umrechnung lesen kann.
score(haus) = Σ_zelle gewicht(zelle) · reisezeit(haus, zelle) / Σ_zelle gewicht(zelle)
Zellen: Die Stadt ist in ein 300-Meter-Raster zerlegt, 830 Zellen enthalten Adressen. Der Zielpunkt einer Zelle ist der Schwerpunkt ihrer Adressen, nicht die geometrische Mitte.
Gewicht: Die Anzahl Adressen in der Zelle. Damit ist der Wert der Erwartungswert über eine zufällig gezogene Adresse. Dicht bebaute Ziele zählen entsprechend mehr. Der Wald am Uetliberg, wo kaum jemand wohnt, zieht den Schnitt nicht nach unten.
Reisezeit: Das Minimum aus direktem Fussweg und der besten ÖV-Verbindung.
reisezeit = min( fussweg_direkt,
min über nahe Haltestellen a von fussweg(haus, a) + öv_zeit(a, zelle) )
öv_zeit enthält Wartezeit, Fahrzeit, Umsteigen samt Zuschlag und den Fussweg von der
Ausstiegshaltestelle zum Ziel.
Taktdichte: Gesucht wird nicht zu einer Uhrzeit, sondern zu 24 Abfahrtszeiten im Fünfminutenraster zwischen 7 und 9 Uhr, gemittelt über alle. Wer alle sieben Minuten eine Verbindung hat, wartet im Schnitt kürzer als jemand mit Halbstundentakt. Dieser Unterschied landet in der Zahl.
Dass sich benachbarte Häuser leicht unterscheiden, kommt von den Fusswegen. Jedes Haus hat eigene Distanzen zu den bis zu acht nächsten Haltestellen. Das ergibt einen stufenlosen Verlauf statt Flächen mit Sprüngen an den Haltestellenkanten.
Die kurzen Wege (Haus zur Haltestelle, Haltestelle zum Ziel, und für die Kulturvielfalt
Haus zum Kulturort) laufen über ein Fusswegnetz aus OpenStreetMap, rund 420'000 Knoten in
Zürich, alle begehbaren Wegtypen samt Treppen, Brücken und Unterführungen. Ab jedem Anker
(Haltestelle oder Kulturort) rechnet ein gekappter Dijkstra die Gehzeit zu allen Häusern im
Budget. Ein Haus hinter der Limmat nimmt so den Umweg über die Brücke statt einer geraden
Linie. Steigung zählt Segment für Segment, das Auf und Ab bremst mehr als ein über die
ganze Strecke gemittelter Wert. Gegenüber der früheren Näherung Luftlinie · 1.35 werden
die Reisezeiten dadurch im Median rund anderthalb Minuten länger. Nur der lange „alles zu
Fuss"-Vergleichswert der ÖV-Kennzahl bleibt bei der Luftlinie.
Grundlage für die Fusswege ist Toblers Wanderfunktion, die die Steigung einrechnet. Die Gehgeschwindigkeit fällt exponentiell mit der Steigung, am schnellsten geht es bei rund fünf Prozent Gefälle statt in der Ebene:
v(s) = v0 · exp(-3.5 · |s + 0.05|) / exp(-3.5 · 0.05)
Der zweite Faktor normiert so, dass in der Ebene die konfigurierte Gehgeschwindigkeit herauskommt. Toblers Originalkonstante von 6 km/h gilt für Wanderer im Gelände und wäre für den Weg zur Tramhaltestelle zu hoch. Gerechnet wird der Mittelwert aus Hin- und Rückweg. Ein Haus am Zürichberg stünde sonst zu gut da, weil der Weg zur Haltestelle hinunter schnell geht.
Der Effekt ist deutlich: Häuser im Talboden (400–450 m ü. M.) kommen im Schnitt auf 29,0 Minuten, Häuser in Hanglage auf 600–650 m auf 42,1.
Das Höhenmodell stammt aus den frei nutzbaren Terrain-Kacheln von AWS, in denen die Höhe in
den Farbkanälen eines PNG steckt (h = R·256 + G + B/256 − 32768). Für die Schweiz kommen
die Daten aus dem swisstopo-Modell mit rund 25 m Rasterweite. Stichprobe gegen bekannte
Punkte: Zürich HB 411 m (real 408), Uetliberg 852 m (real 869). Für die Steigung entlang
eines Fussweges reicht das. Für einzelne Treppen nicht, und das ist auch nicht das Ziel.
Für jede der zehn Sorten (Cafés, Bars und Clubs, Bühnen, Kinos, Museen und Galerien,
öffentliche Kunst, Bibliotheken, Badis, Quartiertreffs, Restaurants) wird gezählt, was von
einem Haus aus in Reichweite liegt, mit der Reisezeit abklingend gewichtet (Σ exp(−t/τ)).
Standardmässig zählen 15 Gehminuten, in der Karte lässt sich auf Velo (10 Minuten)
umschalten. Vorgabe sind alle zehn Sorten, jede einzelne lässt sich abwählen.
Das Velo-Modell ist wie beim Gehen steigungsabhängig, aber monoton:
v(s) = min(6.5, 4.4 · exp(−10·s)) m/s. Bergauf ist das Tempo stark gebremst, bergab bis zu
einem Stadttempo-Deckel höher. Gemittelt wird über Hin- und Rückweg.
Rang und Farbe kommen nicht aus der Summe der Sorten, sondern aus der Summe der Wurzeln:
vielfalt(Haus) = Σ_Sorte √( index_Sorte )
Die Wurzel bremst jede einzelne Sorte. Die zwölfte Bar zählt kaum noch, das erste Museum viel. Ein Haus mit einem Angebot aus jeder Sorte schlägt eines mit dreissig Cafés und sonst nichts. So misst die Karte Vielfalt statt Dichte, und die Quartierzentren heben sich vom Zentrum ab, statt in einem Verlauf unterzugehen. Angezeigt wird weiterhin die blosse Anzahl Orte, weil man sie unmittelbar versteht.
Der naive Weg wäre, für jedes Gebäudepaar eine Verbindung abzufragen. Bei 47'085 Häusern sind das 2,2 Milliarden Paare. Mit einer Routing-API pro Anfrage ist das undenkbar, und bei den Preisen kommerzieller Distanzmatrizen nicht bezahlbar.
Drei Entscheidungen bringen das auf sieben Sekunden:
haltestelle × zielzelle, 564 × 830 statt 47'085 × 47'085. Das sind 13'536
Routing-Läufe (564 Starthaltestellen × 24 Abfahrtszeiten), nicht Milliarden.Gesamtlaufzeit auf einem Laptop: GTFS-Aufbereitung 17 Sekunden (dabei werden 28,8 Millionen
Zeilen stop_times.txt gelesen), Reisezeitmatrix 7 Sekunden, Gebäudewerte 1 Sekunde.
Alles offen und kostenlos, nichts davon braucht einen API-Schlüssel.
| Was | Quelle | Umfang |
|---|---|---|
| Fahrplan | opentransportdata.swiss, GTFS Fahrplanjahr 2026 | 197 MB gepackt, 3,2 GB entpackt |
| Gebäudegrundrisse, Adressen, Strassen, Gewässer, Ortsnamen | OpenStreetMap über overpass.osm.ch | 47'099 Gebäude, 57'507 Adressen |
| Stadtgrenze | OpenStreetMap, Relation admin_level=8 |
Zur Overpass-Instanz: overpass-api.de antwortet auf Gebäudeabfragen dieser Grösse
regelmässig mit „server too busy". Die Schweizer Instanz hält nur Schweizer Daten und
liefert dieselbe Abfrage in unter einer Sekunde.
Google Maps wäre für diesen Zweck der falsche Weg. Die Distance-Matrix-API rechnet pro Element ab, und schon eine grob vereinfachte Variante läge im sechsstelligen Frankenbereich, bei Daten, die als GTFS ohnehin frei verfügbar sind.
Stichprobe gegen den echten Fahrplan (pnpm verify, Abfahrt 8 Uhr):
8 min Zürich HB → Zürich Oerlikon
2 min Zürich HB → Zürich Stadelhofen
11 min Zürich HB → Zürich Flughafen
18 min Zürich, Bellevue → Zürich, Bucheggplatz
17 min Zürich, Paradeplatz→ Zürich, Milchbuck
21 min Zürich Altstetten → Zürich Tiefenbrunnen
33 min Zürich, Klusplatz → Zürich, Albisgütli
Bewusste Vereinfachungen:
Grundlage ist das Fuss- und Velowegnetz der Stadt Zürich aus dem Geoportal, rund 40'000 Kanten mit Velofreigabe, Einbahnen, Velostreifen und Abbiegeverboten. Die Pipeline ergänzt jede Kante mit dem signalisierten Tempo, den Lichtsignalen, der Velonetzplanung (Vorzugsrouten, Hauptnetz), den polizeilich registrierten Velounfällen der letzten zehn Jahre und aus OpenStreetMap mit Strassenklasse, Belag, Tramgleisen und Hindernissen. Daraus entsteht je Richtung eine Stressstufe von 1 (abgetrennt oder ruhig) bis 4 (Mischverkehr ab Tempo 50), angelehnt an das Level-of-Traffic-Stress-Schema.
Die Velofreigabe der Stadt ist lückenhaft. Ein Fussweg wird deshalb auch befahrbar, wenn die Velokarte der Stadt über ihn führt oder OSM ihn ausdrücklich fürs Velo freigibt, zusammen rund 26 km. Ein Beispiel ist der Weg neben dem Schulhaus Wengi zwischen Kanzlei- und Wengistrasse. Trottoirs neben einer befahrbaren Strasse bleiben aussen vor, ebenso die Biketrails am Uetliberg, die im Datensatz der Stadt als befahrbar gelten.
Der Graph landet als Binärdatei in public/data/zuerich/velo.graph. Der Router in
app/velonavi/router.ts sucht darauf im Browser mit A* über gerichtete Kanten. So kennt er
Abbiegeverbote und rechnet an Lichtsignalen je nach Manöver unterschiedlich lange Wartezeiten.
Geradeaus hängt die Wartezeit davon ab, wie viel Verkehr die gequerte Strasse im Vergleich zur
eigenen führt (im Mittel 22 Sekunden, von 3 bis 56), rechts abbiegen kostet praktisch nichts.
Der Verkehr kommt an 120 der 419 Signalknoten aus der Verkehrszählung der Stadt: Stundenwerte der Detektoren an den Lichtsignalanlagen, gemittelt über die Werktage von 6 bis 20 Uhr. An den übrigen Knoten folgt er aus Strassenklasse und Fahrspuren. Auf Tramachsen erfasst die Zählung nur die Autos, dort gilt mindestens der Wert aus der Strassenklasse. Gemessene Grünzeiten gibt es für die städtischen Anlagen nicht als offene Daten. Die Lichtsignal-Schnittstelle des ASTRA auf opentransportdata.swiss liefert den Grünanteil nur für 37 Knoten an Kantonsstrassen ausserhalb der Stadt (Stand Mai 2026).
Wer im Velonavi Fahrten aufzeichnet oder als GPX einliest, bekommt sie auf dem Gerät ausgewertet.
app/velonavi/fahrten.ts ordnet die Spur den Kanten zu, misst Fahrzeit und Standzeit vor
Ampeln und leitet daraus das eigene Tempo, einen Faktor je Kante und eine Wartezeit je Ampel
ab. Der Router rechnet danach mit diesen Werten. app/velonavi/vergleich.ts vergleicht ähnliche
Fahrten und Teilstrecken, die auf verschiedenen Wegen gefahren wurden. Die Spuren liegen auf dem Gerät. Die
Sicherung im Konto und das Lernen aus den Fahrten anderer (gemeinschaft.ts) brauchen ein
Supabase-Projekt und sind freiwillig, die Einrichtung steht in
docs/betreiben.md. Die Android-App zeichnet auch im Hintergrund auf:
docs/android.md.
Was in keiner Quelle stimmt, steht mit Begründung in pipeline/velo-korrekturen.json. Wie
man dort etwas ergänzt, beschreibt docs/daten-anpassen.md. Die
GitHub-Action velodaten.yml baut das Netz am 3. jedes Monats aus frischen Daten neu.
pnpm daten:velo # Rohdaten holen und Graph bauen
pnpm korrekturen:pruefen # velo-korrekturen.json prüfen, ohne die Pipeline
/wohnungen sammelt die Mietinserate der Stadt Zürich an einem Ort. Der Sammler
pipeline/20-wohnungen.ts fragt ab:
| Quelle | Wie |
|---|---|
| Flatfox | Öffentliche API: /api/v1/pin/ in Kacheln (höchstens 1000 Punkte je Abfrage), dann /api/v1/public-listing/?pk=… gebündelt. Flatfox gehört zur SMG und führt einen Teil der Homegate- und ImmoScout24-Inserate mit. |
| Ron Orp | __NEXT_DATA__ der Marktseite, die neuesten rund zehn Inserate mit Koordinaten. Früher Gesammeltes bleibt bis zum Ablaufdatum stehen. |
| WOKO | HTML der Liste freier Objekte, nur Zimmer |
| Stiftung PWG | HTML der Liste «zu vermieten», nur Wohnungen |
| ABZ | WordPress-Schnittstelle, Beitragstyp wohnung |
Nicht dabei sind Homegate und ImmoScout24 direkt, Newhome, Comparis, Tutti, Anibis und students.ch: Sie sperren Abrufe von GitHub aus mit Cloudflare, auch wenn ein echter Browser (Playwright) fragt. wgzimmer.ch verlangt ein reCaptcha, das Vermietungsportal der Stadt eine Anmeldung. Die Seite verlinkt sie unter «Weitere Quellen», bei Homegate und ImmoScout24 mit denselben Filtern.
Fällt eine Quelle aus, bleiben ihre Inserate vom letzten erfolgreichen Lauf bis zu drei Tage stehen, und die Seite sagt, welche Quelle nicht geantwortet hat.
Danach passiert viererlei:
city.geojson), ohne Koordinaten über die Postleitzahl.Der Workflow .github/workflows/wohnungen.yml lässt den Sammler alle fünf Minuten laufen und
ausserdem bei jedem Push, der ihn ändert. Weil GitHubs Zeitplan kurze Abstände unzuverlässig
bedient, läuft ein Lauf auf main als Schleife von knapp sechs Stunden und startet dann seinen
Nachfolger selbst; der stündliche Zeitplan fängt eine gerissene Kette wieder auf. Er legt wohnungen.json auf den Zweig wohnungen,
jedes Mal als einzigen Commit. Die Seite lädt die Datei über raw.githubusercontent.com und
schaut alle zwei Minuten nach Neuem; main und das Deployment bleiben unberührt. Wer selbst
betreibt, setzt NEXT_PUBLIC_WOHNUNGEN_URL (siehe .env.example). Ohne erreichbare Datei greift
die Seite auf public/data/zuerich/wohnungen.json zurück, so läuft es lokal:
node pipeline/20-wohnungen.ts # schreibt public/data/zuerich/wohnungen.json
pnpm dev # http://localhost:3000/wohnungen
Gemerkte und ausgeblendete Inserate, die Filter und der letzte Besuch (für «neu seit deinem letzten Besuch») bleiben im Browser, es braucht kein Konto.
Angemeldet speichert man auf /wohnungen die aktuelle Suche als Suchabo (Tabelle
wohnungen_suchabos). Nach jedem Lauf des Sammlers schickt pipeline/21-suchabos.ts jedem
aktiven Abo eine Mail mit den Inseraten, die seit dem letzten Lauf neu sind und zum Filter passen.
Gefiltert wird mit derselben Funktion wie auf der Seite (app/wohnungen/filter.ts). Nach dem
Anlegen kommt zuerst eine Bestätigung. Jede Mail hat einen Abmeldelink, der ohne Anmeldung
funktioniert (/wohnungen?abmelden=…).
Einrichtung, einmalig. Der Versand läuft in GitHub Actions, nicht bei Vercel; die Werte müssen deshalb auch dann in GitHub stehen, wenn sie bei Vercel schon hinterlegt sind (dort kopieren: Project → Settings → Environment Variables, Wert einblenden).
SUPABASE_URL: wie NEXT_PUBLIC_SUPABASE_URL bei Vercel, https://<projekt>.supabase.coSUPABASE_SERVICE_ROLE_KEY: bei Vercel meist SUPABASE_SERVICE_ROLE_KEY oder
STORAGE_SUPABASE_SERVICE_ROLE_KEY. Er liest alle Abos an der Row Level Security vorbei und
gehört nie in die Seite.RESEND_API_KEYSUCHABO_ABSENDER, sonst gilt angebunden <[email protected]>.Fehlt eine der drei Angaben, überspringt der Workflow den Versand.
pipeline/
config.ts die stadtunabhängigen Parameter an einer Stelle
staedte.ts Bounding-Box, Projektion und verify-Paare je Stadt
lib/csv.ts streamender CSV-Leser für die 2,5-GB-Fahrplandatei
lib/geo.ts lokale Projektion, Punkt-in-Polygon
lib/raptor.ts der Router
01-fetch-osm.ts OpenStreetMap über Overpass, mit Zwischenspeicher
01b-fetch-dem.ts Höhenkacheln von AWS
02-build-network.ts GTFS -> Haltestellen, Linienmuster, Fusswege
03-build-targets.ts Gebäude, Adressen, Zielraster, Kartengrundlage
04-compute-scores.ts Reisezeitmatrix und Gebäudewerte
verify.ts Stichprobe gegen bekannte Verbindungen
10-velo-daten.ts Velonavi: Geodaten der Stadt Zürich, Unfälle, Verkehrszählung, OSM
11-velo-netz.ts Velonavi: Routinggraph mit Stressstufen
velo-korrekturen.json Ortskenntnis, die in keinem Datensatz steht
korrekturen-pruefen.ts prüft velo-korrekturen.json gegen das Schema
app/
page.tsx Route /, lädt die Zürcher Kennzahlen
basel/, bern/ Routen /basel und /bern
methode/ Route /methode mit Text, Formeln, Open Source, Kontakt
karte.tsx MapLibre, Ebenen, Bedienfeld
suche.tsx Adresssuche im Browser
staedte.ts Name, Route, Startsicht je Stadt
meta.ts, site.ts, seo.ts geteilte Metadaten und SEO
besucher-zaehler.tsx GoatCounter-Einbindung
og/ Vorschaubilder je Stadt, beim Bauen gerendert
velonavi/ Velonavi (Startseite /): Oberfläche, Router, Fahrten, Vergleich, Konto
erreichbarkeitskarte/ Route /erreichbarkeitskarte (Zürich)
supabase/ Tabellen für die Sicherung der Fahrten und die Gemeinschaft
android/ Android-App (Capacitor mit eigenem Standort-Plugin), siehe docs/android.md
docs/ Daten anpassen, selbst betreiben und einbinden
scripts/ MapLibre-Worker und Schriftglyphen ins public-Verzeichnis
analytics/ Besuche pro Tag, siehe analytics/README.md
Jede Stadt liest ihre Kennzahl STADT aus der Umgebung (STADT=basel node …), schreibt
nach data/derived/<stadt>/ und public/data/<stadt>/ und teilt sich mit den anderen nur
den Fahrplan data/raw/gtfs_ch.zip und die Höhenkacheln data/raw/dem/. Eine neue Stadt
braucht einen Eintrag in pipeline/staedte.ts und app/staedte.ts plus eine
app/<stadt>/page.tsx.
pnpm install
pnpm daten # nur Zürich, lädt rund 330 MB und rechnet alles durch
pnpm daten:alle # Zürich, Basel und Bern nacheinander
pnpm dev
pnpm daten:basel und pnpm daten:bern rechnen je eine Stadt. Basel und Bern sind
kompakt, ihr OSM-Anteil ist klein, und der Fahrplan liegt nach dem ersten Lauf schon da.
Beide zusammen brauchen ein paar Minuten. Einzelne Schritte gehen mit
STADT=basel pnpm daten:osm und so weiter. Die Rohdaten unter data/raw/ werden nicht neu
geladen, solange sie da sind. Wer einen neuen Fahrplan will, löscht data/raw/gtfs_ch.zip.
Der Analysetag, das Abfahrtsfenster, die Rasterweite, das Gehminuten-Budget für die Kultur
und die Fusswegparameter stehen in pipeline/config.ts. Alles Stadtspezifische steht in
pipeline/staedte.ts: Bounding-Box, Projektionsmittelpunkt und die Haltestellen für
pnpm verify.
Die Seite hat keinen Serveranteil. Alle Daten liegen als Dateien in public/, das Konto im
Velonavi spricht aus dem Browser direkt mit Supabase. Die vier
Routen (/, /basel, /bern, /methode) werden beim Bauen vorgerendert. pnpm export
schreibt einen Ordner out/ mit reinen statischen Dateien, den jeder Gratis-Hoster
ausliefert. Mit allen drei Städten und dem Velonavi sind das rund 100 MB, das meiste davon
Gebäudegrundrisse und der Velograph.
pnpm export
Drei Wege, vom bequemsten zum dauerhaftesten:
out ins Fenster ziehen. Ohne Konto, in ein paar Sekunden eine Adresse zum
Weitergeben.npx wrangler pages deploy out --project-name zueri-karte.
Kostenlos ohne Bandbreitenlimite, was bei 15 MB Gebäudedaten pro Aufruf angenehm ist.
Ergibt zueri-karte.pages.dev.npx vercel --prod im Projektordner. Erkennt Next.js von selbst, dafür
braucht es kein pnpm export.Eine eigene Domain hängt man bei allen dreien in den Projekteinstellungen an. Die Seite muss
auf der obersten Ebene einer Domain liegen, weil die Datenpfade absolut sind. Unter einem
Unterpfad wie bei GitHub Pages (benutzer.github.io/angebunden/) findet sie ihre Dateien
nicht. Weitere Hinweise zu eigenen Deployments stehen in docs/betreiben.md.
Wie viele Leute pro Tag da waren, zählt ein cookieloses Script von
GoatCounter, ohne eigene Datenbank und ohne Consent-Banner.
Die GitHub-Action besucher-zahlen.yml holt die Tageszahlen einmal täglich über die API
und committet sie als analytics/besucher.csv und analytics/besucher.json auf den Zweig
besucherzahlen. Auf main liegen die beiden Dateien nicht, sonst käme dort jeden Tag ein
Bot-Commit an. Einrichtung und was die Zahl genau misst, steht in
analytics/README.md.
Medien, Redaktionen und alle anderen dürfen die Karte, Screenshots davon und die Zahlen verwenden. Als Quellenangabe reicht angebunden.ch.
Der Code steht unter der MIT-Lizenz (LICENSE).
Die abgeleiteten Kartendaten unter public/data/ stammen aus OpenStreetMap und stehen
unter der Open Database License (ODbL). Wer sie weiterverwendet, nennt OpenStreetMap und
stellt abgeleitete Datenbanken wieder unter die ODbL. Der Fahrplan kommt von
opentransportdata.swiss, die Höhen von swisstopo. Beide sind offen nutzbar mit
Quellenangabe. Der Velonavi nutzt zusätzlich Open Government Data der Stadt Zürich (Fuss-
und Velowegnetz, Lichtsignale, Tempo, Velonetzplanung, Verkehrsunfälle, Verkehrszählung), die
Nutzungsbedingungen stehen auf data.stadt-zuerich.ch. Die
Rohdaten liegen nicht im Repository, die Pipeline lädt sie.
whatshouldistudy/ ist ein eigenständiges Projekt, das hier nur vorübergehend liegt: eine englischsprachige
Seite, die aus YouTube, Google Takeout, Spotify, Reddit, GitHub und einem kurzen Fragebogen passende
Studienfächer und Studiengänge weltweit ermittelt. Eigene Abhängigkeiten, eigener Build, eigene Workflows
(wsis-daten.yml, wsis-pruefen.yml), Daten auf dem Zweig «whatshouldistudy-data». Die angebunden-App
bindet nichts davon ein. Details in whatshouldistudy/README.md.