Emergency volunteer coordination system using Bluetooth mesh networks for infrastructure-independent task dispatch during crisis events.
Anchor coordinates emergency response volunteers through a token-gated task system that operates over Bluetooth LE mesh networks when traditional infrastructure fails. The system generates tasks from incident triggers, matches them to available volunteers based on skills and location, and dispatches assignments via BitChat mesh with unique acceptance codes for verification.
- Infrastructure-Independent: Operates over Bluetooth LE mesh when internet/cellular networks are unavailable
- Token-Gated Tasks: 4-character acceptance codes prevent unauthorized task claiming
- Intelligent Matching: Skills-based task assignment with availability and location awareness
- AI-Powered Coordination: Optional AI features for task generation, volunteer matching, and message routing
- Real-Time Coordination: Live dashboard updates via Convex reactive queries
- Audit Trail: Complete system history for compliance and post-incident analysis
- Escalation System: Automatic task reassignment when volunteers don't respond
- Bridge Architecture: HTTP polling bridge connects web app to mesh network
Anchor includes optional AI-powered features using OpenAI for intelligent coordination:
- 🤖 Dynamic Task Generation: AI creates contextually relevant tasks based on incident details (vs hardcoded templates)
- 🎯 Smart Volunteer Matching: AI assists with difficult-to-match tasks when rule-based matching fails
- 📨 Emergency Message Routing: Automatically analyze and route incoming mesh messages to appropriate volunteers
Quick Start:
// Enable AI for task generation
const tasks = await generateForIncident({ incident_id, use_ai: true });
// Use AI for difficult matches
const result = await matchIncidentWithAI({ incident_id, use_ai_fallback: true });
// Process emergency message with AI
const analysis = await processEmergencyMessage({
message: "Medical emergency at Main St",
incident_id,
auto_assign: true
});Setup: Set OpenAI API key in Convex environment:
bunx convex env set OPENAI_API_KEY "sk-..."📖 Full Documentation: docs/AI_INTEGRATION.md
- Bun 1.0+
- Convex account (sign up at https://convex.dev)
- BitChat iOS/Android app for volunteers
- Rust 1.85+ (for bridge component at ~/bitchat-terminal)
# From the project root, run Convex dev
bunx convex dev
# This will:
# 1. Login/create account (if first time)
# 2. Create/select a project
# 3. Generate types in convex/_generated/
# 4. Create .env.local with CONVEX_URLAfter running convex dev, copy the CONVEX_URL from .env.local to frontend/.env as VITE_CONVEX_URL:
# Copy CONVEX_URL from .env.local to frontend/.env
echo "VITE_CONVEX_URL=$(grep CONVEX_URL .env.local | cut -d '=' -f2)" >> frontend/.envcd backend
cp .env.example .env
# Edit .env with Convex deploy key if needed
bun install
bun run src/index.tsBackend runs on http://localhost:8000
cd frontend
cp .env.example .env
# Edit .env with your Convex URL (from convex dev output)
bun install
bun devFrontend runs on http://localhost:5173
cd ~/bitchat-terminal
# Create .env
cat > .env <<EOF
CONVEX_URL=$(grep CONVEX_URL ~/anchor/.env.local | cut -d '=' -f2)
BRIDGE_MODE=true
POLL_INTERVAL_SECS=5
EOF
# Build
cargo build --release
# Run (requires sudo for Bluetooth)
sudo -E ./target/release/bitchat --bridgeSee Bridge Integration Guide for full details.
Use the admin dashboard at http://localhost:5173/admin or call Convex mutations directly:
import { useMutation } from 'convex/react';
import { api } from './convex/_generated/api';
const createIncident = useMutation(api.incidents.create);
const incidentId = await createIncident({
title: "River Flood - Section B",
incident_type: "flood",
severity: "high",
trigger_data: { water_level: 15.2, threshold: 12.0 }
});const generateTasks = useMutation(api.tasks.generateForIncident);
const taskIds = await generateTasks({ incident_id: incidentId });const matchIncident = useMutation(api.matching.matchIncident);
const result = await matchIncident({ incident_id: incidentId });- Tasks are created with
status='pending' - Admin clicks "Dispatch" in UI → updates to
status='dispatched' - Bridge polls Convex, finds dispatched tasks
- Bridge broadcasts to BitChat mesh network
Tasks dispatched to mesh show: TASK#3: Check levee B5 | Code: X7Y2
Volunteer responses:
X7Y2 A # Accept task
X7Y2 D # Decline task
X7Y2 DONE # Mark complete
Bridge validates code and updates Convex automatically.
Anchor uses Convex Auth for authentication, which stores user credentials directly in Convex (no separate database required).
- Password-based authentication
- Email/password signup and login
- Session management handled by Convex
- No external auth service needed
Convex Auth requires JWT_PRIVATE_KEY and JWKS environment variables to be set in your Convex deployment.
Generate the keys:
# Install jose if needed
bun add -d jose
# Generate keys
bun run generateKeys.mjsThis will output two environment variables. Set them in Convex:
Option 1: Using Convex CLI
bunx convex env set JWT_PRIVATE_KEY "your-private-key-value"
bunx convex env set JWKS '{"keys":[...]}'Option 2: Using Convex Dashboard
- Go to Convex Dashboard
- Select your project
- Navigate to Settings → Environment Variables
- Add
JWT_PRIVATE_KEYandJWKSwith the generated values
Important: Set these for both development and production environments if deploying to production.
To add OAuth (GitHub, Google, etc.), update convex/auth.ts:
import { GitHub, Google } from "@convex-dev/auth/providers";
export const { auth, signIn, signOut, store } = convexAuth({
providers: [Password, GitHub, Google],
});See Convex Auth docs for full configuration options.
VITE_CONVEX_URL=https://your-project.convex.cloud
VITE_API_URL=http://localhost:8000PORT=8000
CONVEX_URL=https://your-project.convex.cloud
CONVEX_DEPLOY_KEY=your-convex-deploy-keyCONVEX_URL=https://your-project.convex.cloud
BRIDGE_MODE=true
POLL_INTERVAL_SECS=5Web App (React + Bun)
↓
Convex (Reactive Database + Functions)
↓ (HTTP Polling)
Bridge Process (Rust - bitchat-terminal)
↓ (Bluetooth LE)
BitChat Mesh Network (iOS/Android)
Convex schema defined in convex/schema.ts:
- volunteers: User profiles with BitChat usernames, skills, availability schedules
- incidents: Emergency events with severity, type, trigger data
- tasks: Work items with acceptance codes, status, required skills
- task_assignments: Assignment history and responses for audit trail
- audit_log: Complete system audit trail
- mesh_messages: Bluetooth mesh message log for debugging
convex/volunteers.ts: Volunteer CRUD operationsconvex/incidents.ts: Incident managementconvex/tasks.ts: Task management and generationconvex/matching.ts: Skills-based volunteer matching algorithmconvex/escalation.ts: Timeout-based task reassignment (scheduled)convex/audit.ts: System audit trail generationconvex/crons.ts: Scheduled escalation checksconvex/task_assignments.ts: Volunteer response trackingconvex/mesh_messages.ts: Mesh network message loggingfrontend/src/pages/: Dashboard, incident, and volunteer management UIs
The bridge process connects web infrastructure to mesh network:
- Bridge polls Convex every N seconds for tasks with
status='dispatched' - Bridge formats and broadcasts tasks to BitChat mesh network
- Bridge receives volunteer response codes from mesh
- Bridge validates codes and updates Convex with task status
- Web app reflects changes in real-time via Convex reactive queries
Bridge Location: ~/bitchat-terminal (separate repository)
Integration Docs: docs/CONVEX_BRIDGE_INTEGRATION.md
# Start Convex dev server (generates types automatically)
convex dev
# Deploy to production
convex deploycd backend
bun run src/index.tscd frontend
bun devcd ~/bitchat-terminal
cargo build --release
sudo -E ./target/release/bitchat --bridge -d# Backend
cd backend
bun test
# Frontend
cd frontend
bun test
# Bridge integration
cd ~/anchor
bun test test/bridge-integration.test.ts- Runtime: Bun (JavaScript/TypeScript)
- Backend: Hono (Web framework) + Convex
- Auth: Convex Auth (password-based authentication)
- Database: Convex (reactive database)
- Frontend: React + Vite + Convex React hooks
- Styling: TailwindCSS
- Mesh Network: BitChat (Bluetooth LE)
- Bridge: Rust (bitchat-terminal at ~/bitchat-terminal)
Dependencies: convex, @convex-dev/auth, hono, react-router-dom, zustand.
api.volunteers.list- List all volunteersapi.volunteers.get- Get volunteer by IDapi.volunteers.getByStatus- Filter by statusapi.incidents.list- List all incidentsapi.incidents.get- Get incident by IDapi.incidents.getByStatus- Filter by statusapi.tasks.list- List tasks (filterable by status/incident)api.tasks.get- Get task by IDapi.matching.matchTasksToVolunteers- Calculate matchesapi.task_assignments.listByTask- Get responses for taskapi.mesh_messages.listByTask- Get mesh logs for task
api.volunteers.create- Create volunteerapi.volunteers.update- Update volunteerapi.incidents.create- Create incidentapi.tasks.create- Create taskapi.tasks.update- Update task (including status → 'dispatched')api.tasks.generateForIncident- Generate default tasksapi.matching.assignTaskToVolunteer- Assign taskapi.matching.matchIncident- Match and assign all tasksapi.audit.logAuditEvent- Log audit eventapi.task_assignments.create- Record volunteer responseapi.mesh_messages.create- Log mesh message
internal.escalation.checkAndEscalateTasks- Runs every minute via cron
- Convex functions use validators for all inputs
- Internal functions are not exposed to public API
- Acceptance codes prevent unauthorized task claiming
- Authentication handled by Convex Auth with secure session management
- Password hashing and secure storage built into Convex Auth
- Bridge uses Convex public HTTP API (add authentication if needed)
This project has been migrated from Supabase to Convex. Key changes:
- Database: PostgreSQL → Convex reactive database
- Real-time: Supabase subscriptions → Convex reactive queries
- Backend API: REST endpoints → Convex queries/mutations
- Scheduled Jobs: PostgreSQL triggers → Convex cron jobs
- Type Safety: Manual types → Auto-generated Convex types
- Bridge Integration: PostgreSQL LISTEN/NOTIFY → HTTP polling
-
Create Koyeb Account: Sign up at koyeb.com
-
Deploy from GitHub:
- Connect your GitHub repository to Koyeb
- Select the
backenddirectory as the build context - Set build command:
bun install - Set run command:
bun start - Set port:
8000(or use Koyeb's auto-detected port)
-
Configure Environment Variables in Koyeb dashboard:
PORT=8000 CONVEX_URL=https://your-project.convex.cloud CONVEX_DEPLOY_KEY=prod:your-project|your-deploy-key -
Get Convex Deploy Key:
- Go to Convex dashboard → Settings → Deploy Keys
- Create a new production deploy key
- Copy and add to Koyeb environment variables
-
Create Vercel Account: Sign up at vercel.com
-
Deploy from GitHub:
- Import your GitHub repository
- Vercel will auto-detect Vite configuration
- Root directory:
frontend - Build command:
bun run build(auto-detected) - Output directory:
dist(auto-detected)
-
Configure Environment Variables in Vercel dashboard:
VITE_CONVEX_URL=https://your-project.convex.cloud VITE_API_URL=https://your-backend.koyeb.app -
Deploy: Vercel will automatically deploy on every push to main branch
Before deploying frontend/backend, deploy your Convex functions:
# From project root
bunx convex deploy --prod
# This will:
# 1. Deploy all functions to production
# 2. Output your production CONVEX_URL
# 3. Generate production deploy keysUse the production CONVEX_URL in both frontend and backend environment variables.
See Bridge Integration Guide for systemd service setup.
- Convex functions deployed to production
- Backend deployed to Koyeb with correct environment variables
- Frontend deployed to Vercel with correct environment variables
- Bridge running on dedicated device (Raspberry Pi, Linux server)
- Health check endpoint responds:
https://your-backend.koyeb.app/health - Frontend loads and connects to Convex
- Auth flow works end-to-end
- Test incident creation and task generation
- Test task dispatch to mesh network
- Test volunteer response from mesh
- Backend Health:
GET https://your-backend.koyeb.app/health - Convex Dashboard: Monitor function calls, logs, and database queries
- Vercel Dashboard: Monitor deployments and analytics
- Koyeb Dashboard: Monitor backend logs and performance
- Bridge Logs:
sudo journalctl -u bitchat-bridge -f
MIT