# SpokeLink Regional Bike Share

SpokeLink is a regional bike-sharing network platform for managing stations, bikes, docks, trips, pricing zones, and rider access across multiple cities and transit agencies.

## Overview

This project provides the backend services and operator tools for a shared micromobility network. It supports real-time station availability, bike assignment, trip lifecycle tracking, regional fare rules, maintenance workflows, and public data feeds for partner apps.

The system is designed for municipalities, transit authorities, and private operators running a coordinated bike-share program across several service areas.

## Features

- Real-time bike and dock availability by station
- Trip start, pause, resume, and end workflows
- Support for e-bikes, classic bikes, cargo bikes, and adaptive cycles
- Regional service zones and geofencing
- Membership, day-pass, and pay-as-you-go pricing
- Station health and maintenance status tracking
- Bike battery, lock, and firmware telemetry
- Operator dashboard API
- Public GBFS-compatible data feeds
- Role-based access for operators, mechanics, and support teams
- Audit logging for trips, billing events, and fleet actions

## Install

### Requirements

- Node.js 20+
- PostgreSQL 15+
- Redis 7+
- npm 10+

### Setup

```bash
git clone https://github.com/example/spokelink.git
cd spokelink
npm install
```

Create a local environment file:

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

Run database migrations:

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

Seed development data:

```bash
npm run db:seed
```

Start the development server:

```bash
npm run dev
```

The API will be available at:

```text
http://localhost:8080
```

## Usage

### Check Station Availability

```bash
curl http://localhost:8080/api/stations
```

Example response:

```json
[
  {
    "id": "stn_1024",
    "name": "Central Station",
    "city": "Riverton",
    "available_bikes": 12,
    "available_docks": 8,
    "status": "active"
  }
]
```

### Start a Trip

```bash
curl -X POST http://localhost:8080/api/trips \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "bike_id": "bike_8841",
    "station_id": "stn_1024"
  }'
```

### End a Trip

```bash
curl -X POST http://localhost:8080/api/trips/trip_5509/end \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "station_id": "stn_1088",
    "dock_id": "dock_04"
  }'
```

### Generate Public Feeds

```bash
npm run feeds:generate
```

Feeds are written to:

```text
public/gbfs/
```

## Configuration

Configuration is managed with environment variables.

| Variable | Description | Default |
| --- | --- | --- |
| `NODE_ENV` | Runtime environment | `development` |
| `PORT` | API server port | `8080` |
| `DATABASE_URL` | PostgreSQL connection string | Required |
| `REDIS_URL` | Redis connection string | `redis://localhost:6379` |
| `JWT_SECRET` | Secret used to sign access tokens | Required |
| `REGION_NAME` | Public name of the bike-share region | `SpokeLink Region` |
| `DEFAULT_TIMEZONE` | Region timezone | `America/New_York` |
| `GBFS_BASE_URL` | Public base URL for GBFS feeds | Required in production |
| `TRIP_UNLOCK_FEE_CENTS` | Default unlock fee in cents | `100` |
| `TRIP_PER_MINUTE_CENTS` | Default per-minute riding rate | `20` |
| `LOW_BATTERY_THRESHOLD` | Battery percentage requiring maintenance | `20` |
| `MAINTENANCE_WEBHOOK_URL` | Optional webhook for service alerts | Empty |

Example `.env`:

```env
NODE_ENV=development
PORT=8080
DATABASE_URL=postgres://spokelink:spokelink@localhost:5432/spokelink
REDIS_URL=redis://localhost:6379
JWT_SECRET=replace-with-a-local-secret
REGION_NAME=North Valley Bike Share
DEFAULT_TIMEZONE=America/Toronto
GBFS_BASE_URL=http://localhost:8080/gbfs
TRIP_UNLOCK_FEE_CENTS=125
TRIP_PER_MINUTE_CENTS=18
LOW_BATTERY_THRESHOLD=25
```

## Development Scripts

```bash
npm run dev          # Start API with hot reload
npm run test         # Run test suite
npm run lint         # Run lint checks
npm run db:migrate   # Apply database migrations
npm run db:seed      # Seed local development data
npm run feeds:generate
```

## License

MIT