# Municipal Transit Planner

Municipal Transit Planner is a web-based planning tool for evaluating public transit routes, stops, schedules, and service coverage. It helps municipal transportation teams compare service scenarios, identify underserved neighborhoods, and prepare data-backed recommendations for operational and capital planning.

> **Status:** Active development. Outputs should be reviewed by qualified planning and operations staff before use in public reports or service decisions.

## Features

- Import routes, stops, schedules, and municipal boundaries from GTFS and GeoJSON
- Visualize existing and proposed transit networks on an interactive map
- Measure population, employment, and key-destination coverage
- Compare route, stop, frequency, and service-hour scenarios
- Estimate fleet requirements, travel times, and operating costs
- Flag long stop spacing, schedule conflicts, and coverage gaps
- Apply accessibility, equity, and minimum-service criteria
- Export maps, summary tables, GeoJSON, and CSV reports
- Save scenarios for review without modifying source datasets
- Record assumptions and configuration values for reproducible analysis

## Requirements

- Node.js 20 or later
- PostgreSQL 15 or later
- PostGIS 3.3 or later
- A valid GTFS feed
- Optional GeoJSON files for municipal boundaries and analysis zones

## Installation

Clone the repository and install dependencies:

```bash
git clone https://github.com/example/municipal-transit-planner.git
cd municipal-transit-planner
npm install
```

Create a PostgreSQL database and enable PostGIS:

```sql
CREATE DATABASE transit_planner;
\connect transit_planner
CREATE EXTENSION postgis;
```

Copy the example environment file and update it for your system:

```bash
cp .env.example .env
```

Run database migrations:

```bash
npm run db:migrate
```

Import a GTFS feed:

```bash
npm run import:gtfs -- ./data/gtfs.zip
```

Start the development server:

```bash
npm run dev
```

Open `http://localhost:3000` in a browser.

## Usage

### Create a planning scenario

1. Open **Scenarios** and select **New Scenario**.
2. Choose the baseline GTFS feed and analysis boundary.
3. Add, remove, or adjust routes, stops, frequencies, and service periods.
4. Enter planning assumptions such as average operating speed and hourly cost.
5. Run the analysis.
6. Review coverage, fleet, cost, accessibility, and validation results.
7. Export the scenario or save it for internal review.

### Command-line analysis

Run an analysis from a scenario file:

```bash
npm run analyze -- \
  --scenario ./examples/crosstown-extension.yml \
  --output ./output/crosstown-extension
```

Validate a GTFS feed without importing it:

```bash
npm run validate:gtfs -- ./data/gtfs.zip
```

Export a saved scenario:

```bash
npm run export -- \
  --scenario-id 42 \
  --format geojson \
  --output ./output/scenario-42.geojson
```

### Supported input data

| Dataset | Format | Required |
| --- | --- | --- |
| Routes, stops, and schedules | GTFS ZIP | Yes |
| Municipal boundary | GeoJSON | Recommended |
| Census or analysis zones | GeoJSON | Optional |
| Population and employment attributes | CSV or GeoJSON properties | Optional |
| Key destinations | GeoJSON | Optional |

All spatial data should use WGS 84 (`EPSG:4326`) unless another coordinate reference system is explicitly configured.

## Configuration

Application settings are read from `.env`.

```dotenv
NODE_ENV=development
PORT=3000

DATABASE_URL=postgresql://planner:planner@localhost:5432/transit_planner
SESSION_SECRET=replace-with-a-long-random-value

DEFAULT_TIMEZONE=America/Toronto
DEFAULT_CRS=EPSG:4326
DEFAULT_CURRENCY=CAD

MAX_UPLOAD_MB=100
GTFS_IMPORT_STRICT=true
LOG_LEVEL=info
```

Planning defaults are stored in `config/planning.yml`:

```yaml
coverage:
  walking_distance_m: 400
  rapid_transit_walking_distance_m: 800

service:
  minimum_headway_min: 60
  average_dwell_time_sec: 25
  layover_ratio: 0.12

costs:
  vehicle_hour: 165.00
  vehicle_km: 1.35

accessibility:
  require_wheelchair_boarding: true
  maximum_stop_spacing_m: 800
```

Scenario-level values override planning defaults. Environment variables control deployment and infrastructure settings; they do not override scenario assumptions unless documented.

Never commit `.env`, database credentials, private ridership data, or unpublished planning files to version control.

## Production

Build and start the application:

```bash
npm run build
npm start
```

Before deploying:

- Use a managed PostgreSQL instance with PostGIS enabled.
- Set `NODE_ENV=production`.
- Generate a strong `SESSION_SECRET`.
- Configure HTTPS and a reverse proxy.
- Restrict access to unpublished scenarios and sensitive datasets.
- Schedule database backups.
- Review data-retention and public-records requirements.
- Confirm that the configured timezone matches the transit agency’s GTFS feed.

## Testing

Run the automated test suite:

```bash
npm test
```

Run linting and type checks:

```bash
npm run lint
npm run typecheck
```

## Data and Planning Limitations

Coverage calculations represent proximity to service, not guaranteed accessibility or ridership. Travel-time and cost estimates depend on configured assumptions and source-data quality. Validate results against field conditions, current operating practices, collective agreements, accessibility standards, and applicable municipal policies before adoption.