For Twilio use, we leveraged ngrok-free to create a webhook to access our server (locally running via docker).
What it’s doing Caller → Twilio cloud → https://xxxx.ngrok-free.app → ngrok → your Mac :8001 → Florence When someone calls your Twilio number:
HTTP webhook — Twilio POSTs to https://YOUR-TUNNEL.ngrok-free.app/twilio/voice Florence returns TwiML: “connect this call to our media stream.”
WebSocket — Twilio opens wss://YOUR-TUNNEL.ngrok-free.app/twilio/media Live audio flows both ways (Pipecat / Whisper / Piper).
Status callbacks — Hang-up etc. go to /twilio/status.
Your .env ties it together:
PUBLIC_BASE_URL — must match the ngrok hostname (used for Twilio signature checks) PUBLIC_WEBSOCKET_URL — the wss://…/twilio/media URL Twilio puts in TwiML If those don’t match the URL ngrok is actually serving, webhooks fail or signatures get rejected.
Why “ngrok-free” specifically It’s ngrok’s free tier — fine for hackathon/local dev:
Random subdomain (e.g. 11cd-79-127-206-186.ngrok-free.app) URL changes when you restart ngrok → update .env + Twilio console webhooks Sometimes shows an ngrok interstitial on browser hits (usually not an issue for Twilio server webhooks) Alternatives: paid ngrok (fixed domain), Cloudflare Tunnel, deploy to a real host.
Log in or sign up for Devpost to join the conversation.