Ports

Adapters

Demo adapters are the default. Hosted vendors plug in through env vars without code changes.

PortDemo ($0)First paid stepEnv
Trips, ledger, tokensMemory mapsNeon or Supabase PostgresDATABASE_URL
Presence, buckets, pub/subMemory mapsUpstash RedisREDIS_URL
Domain eventsIn-process busCloudAMQPRABBITMQ_URL
Cards & ConnectSimulated PIStripe ConnectSTRIPE_SECRET_KEY
Web loginDemo cookieSupabase AuthNEXT_PUBLIC_SUPABASE_URL
UploadsMemory signed URLR2/S3UPLOAD_DRIVER=s3
ETAHaversineMapbox, then Google, then OSRMMAPBOX_ACCESS_TOKEN
UnlockSimulated acceptIoT webhookIOT_UNLOCK_WEBHOOK
TelematicsSimulated neighborhood pingBouncie / Samsara / Smartcar / …TELEMATICS_PROVIDER
Mail.data/mail.json + /admin/mailResendRESEND_API_KEY
Voice/SMSSimulated numberTwilio proxyTWILIO_ACCOUNT_SID

getContainer() picks Redis and AMQP only when URLs exist. Everything else keeps working. That is the turnkey: you do not maintain a second “demo backend.”

backend/infra/container.ts
const cache = hasRedis() ? new RedisCacheStore(...) : new MemoryCacheStore();
const bus = hasRedis() || publisher ? new DurableEventBus(...) : new InMemoryEventBus();