Keeping crowds safe, one exit at a time.
ExitFlow is an AI-powered crowd dispersal system for large public events like concerts, stadium matches, and festivals. When 15,000 fans leave simultaneously, it prevents dangerous pile-ups by giving every attendee a personalized, staggered exit plan — and giving organizers a live control dashboard to manage bottlenecks in real time.
When a major event ends, every attendee heads for the exits at the same moment. Gates hit 100% capacity within minutes. Transit nodes get overwhelmed. Crowd crushes happen. ExitFlow solves this by staggering departures across 45-minute windows, routing people by section, and using AI to adapt when things go wrong.
Public Safety / Smart Events — preventing crowd crushes at post-event exits through AI-driven staggering, real-time density monitoring, and Gemini-generated interventions.
| Surface | URL |
|---|---|
| Landing page | / |
| Attendee view (demo ticket) | /attendee/TKT-00042 |
| Organizer dashboard | /dashboard |
Tickets range from TKT-00001 to TKT-15000. Each maps to a different section, gate, wave, and transit option.
- Personalized exit timeline — step-by-step: leave seat → walk to gate → board transit, each with a T+ offset from event end
- Live crowd pressure gauge — real-time density at your assigned gate, colour-coded green/yellow/red, updates every 5 seconds
- Gemini chat assistant — grounded in your specific plan (section, gate, transit, current crowd state). Handles questions like "Is there a quieter exit?", "Where's the nearest washroom?", "My child is lost"
- Mobile-first design — large touch targets, calm soft-blue palette
- Live Leaflet map of Wankhede Stadium and surroundings (real OpenStreetMap tiles, no API key needed)
- Heatmap circles on all 8 gates — radius and colour scale with live density
- Alert panel — fires when any gate exceeds 85% capacity for >10 seconds
- Gemini intervention suggestions — each alert includes a specific, actionable instruction (e.g. "Redirect ~673 attendees from sections P, Q, R to Gate 8 via the east concourse")
- AI Dispersal Strategy — Gemini 2.5 Pro rationale shown at the bottom of the panel
- Aggregate stats bar: total attendees, walking, at-gate, % dispersed, avg wait, simulation clock
| Gemini Call | Model | When |
|---|---|---|
| Dispersal strategy — wave assignments + rationale | gemini-2.5-pro |
Once at startup |
| Attendee chat — context-aware personal guide | gemini-2.5-flash |
Per chat message |
| Alert interventions — specific redirect instructions | gemini-2.5-flash |
Per new bottleneck alert |
All three have graceful fallbacks — the app runs fully without a Gemini API key.
┌──────────────────────────────────────────────────────────┐
│ FastAPI (main.py) │
│ │
│ GET / GET /attendee/<id> GET /dashboard │
│ POST /api/chat GET /api/crowd_state GET /api/alerts │
├──────────────────────────┬───────────────────────────────┤
│ simulator.py │ gemini_client.py │
│ • 15,000 attendees │ • generate_dispersal_ │
│ • 20 sections, 8 gates │ strategy() [2.5-pro] │
│ • 3 transit nodes │ • chat_with_attendee() │
│ • seated→walking→ │ [2.5-flash] │
│ at_gate→dispersed │ • generate_intervention() │
│ • Background tick / 5s │ [2.5-flash] │
│ • Alert rule engine │ • Result caching │
└──────────────────────────┴───────────────────────────────┘
Frontend: Plain HTML · Tailwind CSS (CDN) · Vanilla JS
Maps: Leaflet.js + OpenStreetMap (free, no key)
Deploy: Single Docker container · Google Cloud Run
Hardcoded to Wankhede Stadium, Mumbai (IPL Final 2025 scenario):
- 8 gates placed around the stadium perimeter
- 3 transit nodes: Churchgate Metro Station, Marine Lines Bus Depot, Wankhede Taxi Stand
- 20 seating sections (A–T), each with ~750 attendees
Attendees move through states: seated → walking → at_gate → dispersed.
The sim runs at 20× real time — the full 45-minute dispersal window completes in ~135 real seconds. Gaussian noise on density figures makes the heatmap feel organic.
# 1. Clone the repo
git clone <repo-url>
cd ExitFlow-Claude
# 2. Create a virtual environment
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS / Linux
# 3. Install dependencies
pip install -r requirements.txt
# 4. Add your Gemini API key (optional — app works without it)
cp .env.example .env
# Edit .env and set GEMINI_API_KEY=your_key_here
# 5. Run
uvicorn main:app --host 0.0.0.0 --port 8080 --reloadThen open:
- Landing page → http://localhost:8080/
- Attendee demo → http://localhost:8080/attendee/TKT-00042
- Dashboard → http://localhost:8080/dashboard
docker build -t exitflow .
docker run -p 8080:8080 -e GEMINI_API_KEY=your_key_here exitflow# Authenticate and set project
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
# Enable required APIs
gcloud services enable run.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com
# Build image remotely (no local Docker push needed)
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/exitflow .
# Deploy
gcloud run deploy exitflow \
--image gcr.io/YOUR_PROJECT_ID/exitflow \
--platform managed \
--region asia-south1 \
--port 8080 \
--set-env-vars GEMINI_API_KEY=your_key_here \
--allow-unauthenticated \
--memory 512Miasia-south1 (Mumbai) is the closest region to the venue — lowest latency for the demo.
ExitFlow-Claude/
├── main.py # FastAPI app — routes, lifespan, background tick
├── gemini_client.py # All Gemini API calls with caching and fallbacks
├── simulator.py # Venue data, 15k attendees, state machine, alerts
├── requirements.txt # Pinned dependencies
├── Dockerfile # python:3.11-slim, port 8080
├── .env.example # GEMINI_API_KEY template
├── templates/
│ ├── index.html # Landing page
│ ├── attendee.html # Mobile attendee view
│ └── dashboard.html # Organizer desktop dashboard
└── static/
├── css/custom.css # Leaflet overrides, typing animation
└── js/
├── attendee.js # Crowd pressure polling, Gemini chat drawer
└── dashboard.js # Leaflet map, heatmap circles, alert panel
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Landing page |
GET |
/attendee/{ticket_id} |
Attendee exit plan page |
GET |
/dashboard |
Organizer live dashboard |
POST |
/api/chat |
{ticket_id, message} → {reply} |
GET |
/api/crowd_state |
Gate densities, transit load, sim stats |
GET |
/api/alerts |
Active bottleneck alerts with AI suggestions |
GET |
/api/strategy |
Cached Gemini dispersal strategy text |
- All crowd density is simulated — no real sensor data
- No authentication on any route (demo/prototype scope)
- In-memory state only — restarting the server resets the simulation
- Gemini calls are best-effort; fallback heuristics ensure the app is always usable
| Service | Role |
|---|---|
| Gemini 2.5 Pro | One-time dispersal strategy at event start |
| Gemini 2.5 Flash | Real-time attendee chat assistant |
| Gemini 2.5 Flash | Per-alert organizer intervention suggestions |
| Cloud Run | Serverless container hosting (port 8080) |
| Cloud Build | Remote Docker image build and push |
| Container Registry | Docker image storage (gcr.io) |