Inspiration
What it does
How we built it
ShuttleConnect — Book your seat. Skip the queue. What inspired us Every weekday morning, thousands of Nairobians line up outside shuttle booking offices on Accra Road and River Road — sometimes as early as 5 AM — just to secure a seat to Eldoret, Kisumu, or Kitale. Companies like Mololine Shuttle and North Rift Shuttle move hundreds of passengers daily, yet in 2026 they still operate almost entirely on phone calls and walk-ins. There is no way to check seat availability at midnight, no way to pay via M-Pesa from your couch, and no digital ticket to show at the stage. We built ShuttleConnect because we live this problem. It is not a hypothetical — it is the Tuesday morning queue at the Mololine office, the unanswered call during lunch hour, and the "come check tomorrow" that wastes half your day.
What we built ShuttleConnect is a multi-tenant SaaS platform — think Shopify, but for Kenyan shuttle companies (Saccos). Each Sacco gets their own dashboard to manage routes, departures, and seats. Passengers book online, pay via M-Pesa, and receive a QR-coded e-ticket in seconds. The core architecture is a shared database, isolated data model: Every table carries a company_id foreign key, and Supabase Row Level Security (RLS) policies enforce that Mololine never sees North Rift's bookings — and vice versa. Every query is scoped: sqlSELECT * FROM routes WHERE company_id = auth.uid()::int; Seat pricing uses a simple demand multiplier. If a departure is pp p% full, the suggested price PP P is: P=Pbase×(1+0.4⋅p100),P∈[0.8⋅Pbase, 2⋅Pbase]P = P_{\text{base}} \times \left(1 + 0.4 \cdot \frac{p}{100}\right), \quad P \in [0.8 \cdot P_{\text{base}},\ 2 \cdot P_{\text{base}}]P=Pbase×(1+0.4⋅100p),P∈[0.8⋅Pbase, 2⋅Pbase] This is surfaced to Sacco admins as an AI suggestion via Gemini 1.5 Flash, which also powers ShuttleBot — a RAG chatbot that reads live Supabase data on every query so it can answer "Does Mololine have seats tomorrow at 8 AM?" with real information, not hallucinations.
Tech stack LayerTechnologyFrontendReact + Vite + Tailwind CSSBackendNode.js + ExpressDatabaseSupabase (PostgreSQL + RLS)AuthSupabase Auth (email + phone OTP)PaymentsM-Pesa Daraja API (STK Push)AIGemini 1.5 Flash (chatbot + pricing)SMSAfrica's TalkingHostingVercel (frontend) + Render (backend)
Challenges we faced Multi-tenancy security was the hardest engineering problem. Getting Supabase RLS policies right — especially with JWT custom claims carrying company_id — took several iterations. A misconfigured policy leaks one Sacco's data to another, which is a trust-destroying bug. We wrote integration tests specifically to assert cross-tenant isolation before moving on. M-Pesa STK Push timing is non-deterministic. The Daraja API fires a push to the user's phone, but the callback can arrive anywhere from 3 seconds to 3 minutes later — or not at all if the user dismisses it. We built a polling loop on the frontend and an idempotent webhook handler on the backend to handle all three outcomes gracefully. The AI chatbot context window needed careful budgeting. Injecting all departures, routes, and companies into every Gemini call gets expensive and slow. We solved this by fetching only the next 48 hours of departures and compressing the JSON before injection, keeping the context under 2,000 tokens per query.
What we learned
Row Level Security in Postgres is genuinely powerful — it moves authorization into the database layer, which means even a buggy API endpoint cannot leak cross-tenant data. Building for Kenyan infrastructure means designing for intermittent connectivity and feature phones first. The USSD fallback (*384#) was not an afterthought — for a large portion of upcountry passengers, it is the primary interface. The best demo is a real transaction. Watching M-Pesa fire on a physical phone and a QR ticket appear on screen is more convincing than any slide.
What's next
East Africa expansion — Uganda and Tanzania have the same problem and the same Sacco model. Driver app — real-time manifest so drivers know exactly who is boarded. Dynamic route suggestions — Gemini analyzing booking patterns to recommend new routes to Saccos. Offline-first PWA — passengers in low-connectivity areas can still view and download their ticket.
Challenges we ran into
Accomplishments that we're proud of
What we learned
What's next for shuttleConnect
Built With
- darajaapi
- express.js
- node.js
- react
- supabase


Log in or sign up for Devpost to join the conversation.