-
-
Event Radar: a curated feed of conferences with open calls for speakers.
-
One-Tap Booking: send a direct offer with event, date, venue and fee.
-
Live availability calendar and Plinth talk history on every speaker profile.
-
Speaker profile: bio, ratings, bookings and Rostrum pricing tiers per format.
-
Discovery: browse verified speakers and MCs by vibe tag, rating and price.
Inspiration
Every corporate event lives or dies on one hire: the keynote speaker or the MC. And yet booking that person is still done the way it was done in 2005 — a chain of email intros through a speaker bureau that takes 20–30 % of the fee, week-long back-and-forth on availability, PDF contracts, and a separate scramble for technical requirements and travel logistics. Speakers hate it too: the bureau owns the client relationship, payouts are slow, and a new voice with no bureau has almost no way in.
We kept meeting brilliant speakers — especially outside the US/UK circuit — who could not get discovered, and event organizers who were overpaying for a shortlist of five names a bureau happened to represent. The gap between those two groups is a classic marketplace problem hiding behind an industry that never got its "Uber moment." We wanted to build the product that collapses find → agree → pay into a single evening, takes a fair cut instead of a punitive one, and treats an unrepresented speaker in Lagos or Manila exactly like a represented one in New York.
The idea for YapElite, and its core product features, were conceptualised by Loveness Nleya, a speaker and a member of my team on this project.
What it does
YapElite is a two-sided mobile marketplace for elite speakers, MCs and facilitators.
For organizers:
- Discovery grid — a Bento-style browse of verified speakers with "Vibe Tags" (HighEnergy, Technical, Inspirational, Storytelling, Leadership…), price tiers, and a Sizzle Reel (their talk video).
- One-Tap Booking — send a direct offer; the speaker accepts or declines from their dashboard. Confirm, and a 30 % deposit is captured into escrow.
- Dais — an RFP board: post a brief, collect competitive bids, pick one.
- Booking-scoped chat — realtime SignalR chat per booking, with read receipts and attachments.
For speakers (the Green Room):
- Accept/decline offers in one tap, manage a real-time availability calendar, publish price tiers ("Rostrum"), and track past engagements ("Plinth").
- Sessionize import — pull your existing speaker profile and session history straight from Sessionize so onboarding is 30 seconds, not 30 minutes.
- Event Radar — a curated feed of conferences with open calls for speakers, so you always have somewhere to pitch.
- Performance analytics: response rate, acceptance rate, repeat-booking rate, earnings.
Payments. Real-world speaking fees settle through Stripe Connect (organizer → platform escrow → speaker payout, milestone-based: 30 % deposit on confirm, 70 % on completion). This is a real-world service, so it correctly sits outside app-store IAP.
Monetization (RevenueCat). Everything digital is a RevenueCat-powered purchase: YapElite Pro for Speakers and YapElite Pro for Organizers subscriptions, plus one-off "Featured Boost" and "Priority RFP" consumables.
How we built it
Backend — layered modular monolith.
- .NET 10 + ABP Framework 10.3 using strict Domain-Driven Design. Aggregates:
Speaker,Booking(a formal state machine:PendingOffer → Accepted → Confirmed → InProgress → Completed, withDeclined / Cancelled / Disputedbranches),Rfp/Bid,EscrowPayment,ChatRoom,BookingLogistics. - PostgreSQL via EF Core; Redis for cache and SignalR backplane.
- ABP Identity + OpenIddict for standards-compliant OAuth2/OIDC — the Flutter app authenticates with the RFC-6749 password grant against
/connect/token. - SignalR for realtime chat and presence.
- AI services (backend only for now): OpenAI Whisper for Sizzle Reel transcription, text-embedding-3-small for matchmaking, and Chat Completions for "why this speaker" briefs, each with a rule-based fallback when no API key is present. The app does not surface these yet; the screens are on the roadmap.
- Stripe.NET for Stripe Connect escrow; a dev fallback keeps the flow testable without live keys.
- Deployed on Azure Container Apps (managed identity → ACR + Key Vault, no long-lived secrets), Postgres Flexible Server, custom domain
api.yapelite.com, Sentry for errors, OpenTelemetry → Azure Monitor. CI/CD is GitHub Actions with OIDC federation (5-job matrix: backend tests, Flutter analyze/test, iOS release, Android APK+AAB, release binaries).
Frontend — Flutter.
- Riverpod (codegen) + go_router typed routes; freezed models; dio HTTP; signalr_netcore for chat.
- Design system in code: "Elite Simplicity / Quiet Luxury" — Obsidian
#0D0D0D/ Midnight#0A1628grounds, a single Electric Teal#00E5C8accent, Inter/Lexend, 8px radius everywhere, Bento-box grids. Dark mode primary, full light-mode variant, persisted toggle. - flutter_stripe for the escrow payment sheet, RevenueCat
purchases_flutterfor the subscription paywall and consumables. - 100+ Flutter tests, 250+ backend xUnit tests, and a Maestro end-to-end suite covering registration, discovery, booking, RFP, chat and logout.
Practices. Strict TDD (every AppService has a mocked-repository xUnit test, every UI component has a widget test), a documented state ledger + handover per session, and a "3-Tap Rule": every primary goal — find, chat, book — completes in ≤ 3 taps.
Challenges we ran into
- Two payment rails, one product. Real speaking fees must use Stripe (real-world service, exempt from IAP); digital Pro features must use store IAP via RevenueCat. Designing entitlements so the two never collide — and so a Pro speaker's lower platform take-rate is enforced server-side from the RevenueCat entitlement, not the client — took real thought.
- ABP's global antiforgery filter silently rejected our public web account-deletion page's
fetch()calls, because ABP sets anXSRF-TOKENcookie on every response and then demands a matching token no static page can produce.curlnever caught it (no cookie jar); a real browser did. Fixed viaAbpAntiForgeryOptions.AutoValidateFilter. - The system back button backgrounded the whole app instead of running our
PopScopecallbacks — a knowngo_routerbug fixed in 14.6.1; we were pinned to 13.2.0. - The entire custom-permission system rejected every policy-gated action for every user, always, since our ABP Identity migration — a missing
AbpPermissionManagementDomainIdentityModuledependency that the xUnit suite (which fakes the current user) structurally could not catch. Only live Maestro testing surfaced it. flutter test's default 800×600 viewport is wide enough to hide layout overflow bugs that every real phone shows — we now write widget tests at a real device size.- A shared-by-name local Postgres container got recreated by a sibling project mid-build and swapped our database out from under us.
Accomplishments that we're proud of
- A complete, tested booking lifecycle — offer, escrow deposit, confirmation, auto-generated event documents, completion payout — not a mockup.
- A design system disciplined enough that the landing site, the app, and the account-deletion page share one token map — and a brand ("Quiet Luxury") that actually reads as premium instead of loud.
- Production-grade ops for a hackathon app: OIDC-only CI/CD, managed-identity secrets, custom domain + managed TLS, crash reporting, a first fully-green 5-job pipeline.
- Google Play account-deletion & data-retention compliance shipped before it was urgent.
What we learned
- Marketplaces are a trust-engineering problem, not a CRUD problem. Verified badges, escrow milestones, dispute states and transparent take-rates are the product; the list views are just the wrapper.
- You cannot verify a cookie-dependent bug with
curl. Test with the transport your users actually use. - RevenueCat entitlements are a clean server-side authority. Letting the backend read entitlement state (via webhook + REST) to set a speaker's take-rate turned "premium tier" from a UI flag into a real business rule.
- Ship the compliance and the paywall early. Store review is the long pole; everything else can iterate after launch.
What's next for YapElite
- AI matchmaking briefs — describe the event in a sentence and get ranked speakers with a "why this speaker" explanation. The matching engine exists on the backend; the in-app experience is next.
- Auto-generated booking logistics — tech and hospitality requirements and a travel itinerary scaffolded when a booking is confirmed. The backend creates them today; the screens to view and edit them are next.
- iCal sync for the speaker availability calendar.
- Rehearsal Room — record a practice answer to a mock organizer question; Whisper transcribes; the LLM scores clarity, pace and filler words and gives feedback before the real stage.
- Bureau mode — white-label multi-tenant workspaces so existing speaker bureaus run their whole roster on YapElite.
- Web-to-app funnel (RevenueCat Funnels + Stripe) so an organizer can start a Pro checkout from a Google result and land in the app already subscribed.
- Deeper Event Radar — auto-match a speaker's Vibe Tags to open CFPs and push "you'd be a fit for this" via OneSignal.
- Payout rails beyond Stripe for emerging-market speakers (local payout partners).
Built With
- abp-framework
- azure-container-apps
- csharp
- dart
- dio
- docker
- dotnet-10
- flutter
- freezed
- github-actions
- go-router
- onesignal
- openai-embeddings
- openai-whisper
- openiddict
- postgresql
- redis
- revenuecat
- riverpod
- signalr
- stripe
- stripe-connect
Log in or sign up for Devpost to join the conversation.