Skip to content
OMOS_e1

OpenMobility OS

Version: 0.54.0 (pre-release) — see CHANGELOG.md License: See LICENSE

The open, free, self-hostable operating system between open mobility data and political decisions. For any municipality. In any country.

OpenMobility OS is a decision, prioritization, and transparency platform for the mobility transition. It is not a consumer routing tool. It is built for municipalities, city planning departments, mobility and climate offices, local politics, civic initiatives, journalists, and researchers.

It answers questions like:

  • Which measures should a municipality prioritize first?
  • Where are the biggest levers for climate, safety, and quality of life?
  • Which streets, corridors, or neighborhoods need intervention first?
  • Which measures are quick to implement, politically viable, and data-backed?
  • How can these decisions be explained to the public?
omos_v047de_t2-shorter2

Leipzig (Germany) and Utrecht (Netherlands) are the two real-city demo workspaces — one developing its cycling infrastructure, the other a world-leading cycling city. Both ship real data connectors out of the box (Leipzig adds a live UBA air-quality feed; Utrecht adds the OVapi Netherlands transit GTFS), and any remaining placeholder layer is clearly labelled illustrative demo so it is never mistaken for real data. The platform is city-agnostic from day one. Any city, small town, municipality, or region worldwide can be added through open data, APIs, and configuration — regardless of country, language, data source, or administrative structure.

Table of Contents

Deployment Modes

OpenMobility OS supports three realistic operating models from the same codebase:

  1. Single-city — one municipality self-hosts its own instance. Set DEPLOYMENT_MODE=single-city and DEFAULT_WORKSPACE_SLUG=<your-city>.
  2. Multi-city — a county, region, transport association, or federal state hosts one instance for many places as separate workspaces. Set DEPLOYMENT_MODE=multi-city.
  3. Public demo — an open public instance showcasing example workspaces. Set DEPLOYMENT_MODE=public-demo. This is the default.

Screenshots

Platform landing Workspace dashboard Interactive map
grafik grafik grafik
Measures list Measure detail Data hub
grafik grafik grafik

Run docker compose up --build locally to see the full platform today.

Quickstart

Requirements: Docker and Docker Compose (see docker.com for installation).

One-command setup (automatic secrets)

git clone https://github.com/richardkfm/openmobility-os.git
cd openmobility-os
cp .env.example .env
# Auto-generate secure random values for SECRET_KEY and ADMIN_TOKEN
python3 -c "import secrets; print(f'SECRET_KEY={secrets.token_hex(50)}'); print(f'ADMIN_TOKEN={secrets.token_hex(32)}')" >> .env
docker compose up --build

Open http://localhost:8000 — you should see the platform landing page with four demo workspaces: Leipzig, Utrecht, Musterstadt, and Muster-Landkreis.

First boot fetches live OpenStreetMap data, so it can take a few minutes before the map layers are populated. Later restarts reuse what is already stored and come straight up. To refresh that data on purpose, run docker compose exec web python manage.py seed_demo --resync.

Step-by-step (for novice users)

  1. Install Docker (if not already installed)

  2. Clone the repository

    git clone https://github.com/richardkfm/openmobility-os.git
    cd openmobility-os
  3. Create .env with secure secrets

    cp .env.example .env
  4. Fill in random values (copy-paste the entire command below)

    python3 << 'EOF'
    import secrets
    with open('.env', 'a') as f:
        f.write(f'\nSECRET_KEY={secrets.token_hex(50)}\n')
        f.write(f'ADMIN_TOKEN={secrets.token_hex(32)}\n')
    print("✓ Secrets added to .env")
    EOF
  5. Start the platform

    docker compose up --build
  6. Open in your browser

    • Visit http://localhost:8000
    • You should see four demo workspaces immediately
    • To add a new workspace: click "New workspace" (requires ADMIN_TOKEN from .env)
  7. To stop, press Ctrl+C in the terminal. Data persists in the postgres_data volume until you run docker compose down -v.

Deploying to a remote server (not localhost)? The steps above are tuned for local use. Before you open the site by its domain or IP, add that host to ALLOWED_HOSTS in .env — otherwise Django answers every request with a bare 400 Bad Request (DisallowedHost). If you terminate TLS at a reverse proxy, also set CSRF_TRUSTED_ORIGINS. See Production Deployment and docs/DEPLOYMENT.md for the full hardening checklist.

Core Features (MVP)

  • Multi-workspace — arbitrary number of cities per installation
  • Target areas — draw an area on the map, attach a goal to it, and get a ranked plan of what to rebuild there: expected effect per segment with a source and an uncertainty range, and an explicit space budget saying how many parking spaces or traffic lanes the rebuild would cost. Targets for people killed or seriously injured are always zero — no percentage target is offered, and the plan reports how many people are still expected to be harmed rather than hiding it behind a percentage. See docs/AREA_TARGETS.md
  • Interactive maps — MapLibre GL JS with configurable tile sources
  • Parked cars, made visible — a map layer that fills kerbside parking and off-street car parks with one symbol per car, so the space a city gives to cars at rest can be counted instead of asserted. Where OpenStreetMap records parking the cars are drawn solid and counted as surveyed; where it is silent on a residential street they are drawn as a dashed outline and counted separately as modelled, and a street surveyed as having no parking is never filled in. Zoomed out, the estimate falls back to a density view on the kerbs and footprints it came from; where a city has too many cars to draw one by one, the legend says how many each symbol stands for. It reports capacity, not occupancy — how many cars fit, not how many are there now — and every number behind it (bay length, square metres per space, which street classes get a modelled kerb) is a parameter a workspace can override. See docs/PARKING_AND_WALKING.md
  • A walking score for every street — each street is rated comfortable, usable, tight, hostile or not enough data from ten inputs: how separated the pavement is, how fast and wide the traffic is, whether there are crossings, whether cars park on the kerb, and how wide, lit, step-free and well-surfaced the walk is. A factor the data cannot speak to is dropped from the average and named on the street — never scored as a middling value — and a street whose known inputs fall below the coverage threshold gets no rating at all rather than a guessed one. A pavement mapped as its own line is matched to its street by proximity, but a street surveyed as having no pavement is never overridden by a line that happens to run nearby. Every weight and threshold is a parameter a workspace can override, and all of them are printed on the workspace's Methodology page. On the map it is a coloured line in five named bands, faint where the rating rests on thin data and pale grey where there is not enough of it — no number is ever drawn over a street, and the 0–100 values appear only in a popup, only if you ask for them. A second mode colours the same streets by how their width splits between parked cars and people on foot. The Parking vs walking story view brings both halves up together. Available at /api/v1/workspaces/<slug>/walkability/; see docs/PARKING_AND_WALKING.md
  • Pedestrian space and off-street parking on the map — sidewalks, footpaths, pedestrian streets and steps come in from OpenStreetMap under either of the two ways it records them (a footway mapped as its own line, or a sidewalk tag on the street), and car parks arrive with their footprint and area rather than as a pin. A street that was surveyed and found to have no pavement is kept distinct from one nobody has mapped yet — the first is evidence, the second is silence, and a walkability reading that confused them would condemn every unmapped street
  • Map legend & distinct markers — an always-on legend below the map lists every active layer with a swatch shaped like how it is drawn; place-type point layers (schools, parking, transit stops, EV chargers, public buildings) use recognisable glyph icons instead of identical dots
  • Per-layer display controls — each layer has a display-mode switch (dots / icons / heatmap for points, normal / thick / dotted lines, filled / outline areas), an opacity slider, and a "focus" toggle that dims every other layer so one stands out. All choices are remembered in the browser
  • Base map switcher — pick a Light, Dark, or Satellite base map from a control on the map, independent of the UI theme; the choice is remembered
  • Full-screen map mode — expand the map, its on-map controls, and the legend to the whole screen for presentations; Escape returns to the page
  • Light & dark mode — a header toggle switches the whole UI between light and dark; the choice is remembered and defaults to the visitor's OS preference. The map base map follows the theme until you pick one explicitly
  • Data hub — browser-based connector management:
    • Add, edit, sync, enable/disable, and delete data sources from the UI
    • Upload local CSV or GeoJSON files directly (no remote URL required)
    • Connector description and config-field reference shown inline when adding a source
    • Activate / deactivate toggle: disabled sources disappear from the map without being deleted
  • Data connectors (fully implemented):
    • CSV (URL or direct file upload) with column mapping and encoding detection
    • GeoJSON URL with property remapping
    • OpenStreetMap via Overpass API — twenty-two built-in templates (streets, streets_with_speed, bike_network, dedicated_bike_network, transit_stops, schools, parking, trees, parks_and_green, water_bodies, sealed_surfaces, districts, kindergartens, hospitals, public_buildings, pedestrian_crossings, ev_chargers_osm, street_parking, car_lanes, obstacles, parking_lots, footways) plus a custom-query escape hatch. The last five are the heavy ones — they pull every street or car park in the bounding box with its full geometry — so they are never synced for you: add them from the data hub when you want them. pedestrian_crossings and streets_with_speed now arrive normalized: crossings carry whether they are signalised, marked, dropped-kerb and tactile, and a speed limit is parsed into a comparable figure whatever the local tagging habit (km/h, mph, or a national zone such as DE:urban, whose value you set per workspace rather than the software guessing it)
    • Static GTFS zip (transit stops, routes, coverage) — enriches stops with average headway, night service, and barrier-free status from the schedule
    • GBFS shared mobility — reads any operator's GBFS auto-discovery feed (bike share, e-scooters, mopeds, car sharing) and emits either available vehicles (free-floating, with form factor and propulsion) or stations (capacity, available vehicles, free docks, availability ratio). A planner's tool, not a rider app: pair with the map's heatmap mode to spot where shared vehicles cluster and where the pick-up gaps are. GBFS v2/v3. Optional availability gap analysis over time records snapshots (one click in the data hub, or on a schedule) and shows them as a map overlay colouring areas from "always available" to "usually empty", filterable by time window, hour of day, weekday and form factor — e.g. where do free cars run out on weekday mornings (see docs/SHARED_MOBILITY.md)
    • Accident CSV — Destatis Unfallatlas (Germany) and generic international, both with optional bounding-box clipping to the workspace
    • BikeMaps.org — global crowdsourced cycling collisions, near-misses, and hazards. Closes the well-documented under-reporting of vulnerable road users in police accident records (CC BY 4.0)
    • CKAN open-data portal — pulls resources from any CKAN-based portal (GovData.de, opendata.leipzig.de, daten.berlin.de, EU Open Data Portal, …) and delegates parsing to the GeoJSON or CSV connector by format preference
    • OGC WFS service — fetches a layer from any WFS endpoint (federal BKG WFS, state geoportals such as Geoportal Sachsen / NRW / Bayern, Umgebungslärm noise maps, …); auto-applies the workspace bbox
    • Generic REST/JSON — pulls a feature list out of any JSON endpoint (UBA Luftqualität, Sensor.Community, OpenChargeMap, BNetzA Ladesäulenregister, ADAC, municipal APIs) with configurable list path and geometry mapping
    • Mobilithek (German NAP) — gateway to the federal mobility-data access point (BMDV, successor to mCLOUD); dispatches to the matching parser based on a format hint. Supports both open distributions and subscriber mode with an X.509 client certificate (DATEX II realtime, restricted GTFS-RT). Built-in catalog browser (browse_catalog() / python manage.py browse_mobilithek --keyword GTFS --formats) parses the Mobilithek DCAT-AP feed so operators can discover dataset titles, publishers, and distribution URLs without manually searching the portal
    • German federal presets — one-URL onboarding for four key German open-data sources: Bundesnetzagentur EV charging register, UBA air-quality stations, DWD climate stations, and BASt traffic counts. Each preset encodes the source's column names, encoding, and geometry mapping so operators don't need to configure them manually
    • Zensus 2022 population grid — reads the Destatis 100 m grid-cell CSV (INSPIRE grid IDs in EPSG:3035), converts to WGS84 polygons, and emits demographic indicators per cell (population, under 18, 65+). Workspace-bbox-aware. Powers the equity-overlay rule that turns mobility measures into political arguments ("this serves 18 000 residents, 22 % of whom are children")
  • KPI importerspython manage.py import_kpis adfc|mid reads survey CSVs and writes results into workspace goals:
    • ADFC Fahrradklimatest — biennial cycling satisfaction grades (1–6) per city, matched to workspaces by name
    • MiD 2017 modal-split — walking, cycling, transit, and car share (%) per city/Kreis from the federal household travel survey
  • seed_unfallatlas command — bootstraps a German workspace with real Destatis accident data clipped to the workspace bounds, replacing the illustrative demo layer
  • Rule-based measures engine — generates prioritized interventions from available data
  • Transparent scoring — nine dimensions, every value traceable to its source
  • Honest data provenance — every layer is labelled live source, official snapshot, or illustrative demo, shown publicly on the dashboard ("Data basis"), the map layer list, and the methodology page, so visitors always know when a number is real versus an example
  • Public shareable URLs for every measure
  • Methodology pages — every formula and data source documented
  • New-workspace wizard — add any city in three steps; search for the place by name and the bounding box is filled in for you (geocoded via OpenStreetMap)
  • Internationalization — German and English out of the box, extensible to any language
  • Admin-token protection for write actions
  • Modern, sober UI — an emerald-accented design with the Inter typeface and the OMOS brand mark, kept professional for a public-sector audience. The web font is loaded from a privacy-friendly CDN with a system-font fallback, so offline self-hosted installs render correctly with no proprietary dependency.

Using the Platform

OpenMobility OS has a public read layer (no login) and an admin layer protected by ADMIN_TOKEN. In short, you can:

  • Explore workspaces from the landing page, dashboards (KPIs, goals, top measures, and a "Data basis" provenance summary), and the interactive map with toggleable layers, accident view modes, one-click story views, district score choropleths, PNG export, and saved views.
  • Read measures — a filterable list and a fully transparent detail page where every score exposes its inputs, formula, confidence, and data sources.
  • Administer (with the admin token) — log in, add a workspace via the geocoding wizard, manage and sync data sources in the data hub, browse upstream catalogs, import Unfallatlas accident data, and generate rule-based measures.

📖 The full step-by-step walkthrough lives in docs/USER_GUIDE.md — landing page, dashboard, map, measures, and every admin task (workspaces, data hub, connectors, catalogs, Unfallatlas, Mobilithek, Django admin, generating measures).

Architecture

  • Backend: Django 5 + GeoDjango + PostGIS + Django REST Framework
  • Frontend: Django templates + Tailwind CSS + HTMX + Alpine.js + MapLibre GL JS
  • Database: PostgreSQL 16 with PostGIS 3
  • Multi-tenancy: path-based URLs (/<workspace-slug>/...)

See CLAUDE.md for the full architecture overview, contribution workflow, versioning policy, and code style.

Production Deployment

For a production instance exposed to the internet: harden .env (DEBUG=False, strong SECRET_KEY/ADMIN_TOKEN, ALLOWED_HOSTS), run behind an Nginx or Caddy reverse proxy with TLS (the web container listens on 8000; keep the db port private), persist the postgres_data volume with regular pg_dump backups, and optionally point the map at self-hosted tile and Overpass servers.

To collect shared-mobility availability history automatically, start the opt-in collector sidecar alongside your stack with docker compose --profile snapshots up -d (see docs/SHARED_MOBILITY.md).

🚀 The full step-by-step guide — including reverse-proxy snippets, backups, and all map-tile / Overpass environment variables — lives in docs/DEPLOYMENT.md. See .env.example for the complete environment-variable reference.

Documentation

This README is the concise entry point. Longer, detailed guides live as separate Markdown files under docs/ — keep the README scannable and move any in-depth content into a docs/*.md file with a short summary and link back here.

  • docs/USER_GUIDE.md — full walkthrough of every page and admin task (dashboard, map, measures, data hub, connectors, generating measures)
  • docs/AREA_TARGETS.md — setting a goal for an area of the city, the space budget behind a rebuild proposal, and why targets for road deaths are always zero
  • docs/PARKING_AND_WALKING.md — the parked-car layer and the walking score: what each one claims, the ten factors and their weights, the class thresholds, the per-workspace overrides and the API
  • docs/SHARED_MOBILITY.md — connecting GBFS feeds (bikes/scooters/cars) and running availability gap analysis over time
  • docs/DEPLOYMENT.md — production hosting: reverse proxy, TLS, backups, tile servers, environment variables
  • CLAUDE.md — project philosophy, architecture, contributor guide
  • CONTRIBUTING.md — first-contribution guide
  • ROADMAP.md — development phases and upcoming features
  • CHANGELOG.md — release notes
  • NOTICE — third-party license attributions
  • /methodology/ (inside a running instance) — scoring methodology, data sources, connector reference
  • /about/ (inside a running instance) — self-hosting guide, version info

Contributing

Contributions are welcome from anyone — municipalities, developers, data journalists, planners, and researchers. Read CONTRIBUTING.md for the quickstart and workflow, and CLAUDE.md for project principles.

Roadmap

Near-term (post-MVP):

  • Climate adaptation layer: trees, green areas, heat corridors, desealing
  • Before/after map slider for measures
  • Citizen feedback on measures
  • GTFS-RT adapter for live transit delays (extends the Phase 9 static GTFS layers with realtime data)

See ROADMAP.md for the full phase-by-phase breakdown.

About

a tool for city planers to develop modern, shared traffic designs

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages