# Municipal Transit Planner

Municipal Transit Planner is a web-based planning tool for exploring public transit networks, evaluating service changes, and producing route and stop-level planning reports. It is designed for municipal transportation teams, transit agencies, consultants, and community planners working with scheduled service data.

The application imports GTFS feeds, displays routes and stops on an interactive map, calculates common service metrics, and lets planners compare proposed scenarios with the current network.

## Features

- Import static GTFS feeds from local files or remote URLs
- Explore routes, stops, trips, calendars, and service frequencies
- Visualize transit coverage on an interactive map
- Filter service by route, mode, date, time period, and municipality
- Identify low-frequency areas and potential coverage gaps
- Create draft scenarios with adjusted routes, stops, and headways
- Compare baseline and proposed service levels
- Export maps, summary tables, and scenario results
- Configure local projections, walking assumptions, and analysis periods
- Run locally with SQLite or connect to PostgreSQL/PostGIS

## Requirements

- Node.js 20 or later
- npm 10 or later
- PostgreSQL 15 with PostGIS 3.3 or later

For evaluation and small datasets, SQLite can be used instead of PostgreSQL.

## Installation

Clone the repository and install the dependencies:

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

Create a local configuration file:

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

For the default PostgreSQL setup, create a database and enable PostGIS:

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

Run the database migrations:

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

Start the development server:

```bash
npm run dev
```

The application will be available at `http://localhost:3000`.

## Usage

### Import a GTFS feed

Import a feed from a ZIP file:

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

Or import a remote feed:

```bash
npm run planner -- gtfs:import https://data.example.gov/gtfs.zip
```

Use `--replace` to replace an existing feed with the same agency identifier:

```bash
npm run planner -- gtfs:import ./data/city-transit.zip --replace
```

### Run an analysis

Generate a service summary for a weekday morning peak:

```bash
npm run planner -- analyze \
  --date 2026-09-15 \
  --from 07:00 \
  --to 09:00 \
  --output ./exports/morning-peak
```

The output includes route frequencies, scheduled vehicle trips, service hours, stop activity, and coverage estimates.

### Create and compare scenarios

Scenarios can be created in the web interface or imported from JSON:

```bash
npm run planner -- scenario:import ./scenarios/proposed-network.json
```

Compare a proposal with the active baseline:

```bash
npm run planner -- scenario:compare proposed-network \
  --baseline current-service \
  --output ./exports/scenario-comparison.csv
```

Scenario changes do not modify the imported source feed. They are stored as overlays and can be revised or removed independently.

### Production build

Create and run an optimized production build:

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

## Configuration

Configuration is loaded from environment variables in `.env`.

```dotenv
NODE_ENV=development
PORT=3000

DATABASE_URL=postgresql://transit_planner:password@localhost:5432/transit_planner

APP_BASE_URL=http://localhost:3000
SESSION_SECRET=replace-with-a-long-random-value

DEFAULT_TIMEZONE=America/Toronto
DEFAULT_LOCALE=en-CA
DEFAULT_CURRENCY=CAD

MAP_TILE_URL=https://tile.openstreetmap.org/{z}/{x}/{y}.png
MAP_ATTRIBUTION=© OpenStreetMap contributors
MAP_DEFAULT_LATITUDE=43.6532
MAP_DEFAULT_LONGITUDE=-79.3832
MAP_DEFAULT_ZOOM=11

ANALYSIS_CRS=EPSG:26917
DEFAULT_WALKING_SPEED_KMH=4.8
DEFAULT_STOP_BUFFER_METRES=400
MAX_GTFS_UPLOAD_MB=100

EXPORT_DIRECTORY=./exports
LOG_LEVEL=info
```

### Database

Set `DATABASE_URL` to a PostgreSQL/PostGIS connection string for production use.

For a local SQLite database:

```dotenv
DATABASE_URL=file:./data/transit-planner.db
```

PostGIS is recommended for large feeds, multi-agency analysis, and spatial queries.

### Map tiles

`MAP_TILE_URL` may point to any compatible XYZ tile service. Verify the provider's usage policy before deploying the application publicly. Some providers require an API key or custom attribution.

### Coordinate reference system

`ANALYSIS_CRS` controls the projected coordinate system used for distance and area calculations. Choose an appropriate local CRS for the municipality. Using a geographic CRS such as `EPSG:4326` may produce inaccurate buffer and coverage measurements.

### Authentication

Local development runs with a single planner account by default. For shared deployments, configure an external OpenID Connect provider:

```dotenv
AUTH_PROVIDER=oidc
OIDC_ISSUER_URL=https://login.example.gov
OIDC_CLIENT_ID=transit-planner
OIDC_CLIENT_SECRET=replace-me
OIDC_ALLOWED_GROUPS=Transit Planning,Transportation Analytics
```

## Data Notes

GTFS data describes scheduled service and may not match actual operations. Coverage estimates use straight-line stop buffers unless a pedestrian network is configured. Validate outputs before using them for budget, accessibility, or public consultation decisions.

Do not commit GTFS feeds, database files, exported reports, or `.env` files containing credentials to source control.

## Testing

Run the automated test suite:

```bash
npm test
```

Run linting and type checks:

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

## License

This project is licensed under the MIT License. Map data and imported transit datasets remain subject to their respective licenses and terms of use.