Arlo is a forkable, open-source RTMS Meeting Assistant that showcases how developers can build real-time, intelligent meeting experiences directly inside Zoom β no meeting bot required!
This project was originally created as the "Meeting Assistant Starter Kit" and has evolved into Arlo, a lightweight example of how to:
- Stream and display live meeting transcripts in real time
- Save transcripts to a database for meeting history
- Generate AI-powered summaries and action items
- Search across past meetings
- Extend functionality using Zoom's Real-Time Media Streams (RTMS) APIs
Arlo is designed to help developers quickly prototype and deploy their own meeting assistants as Zoom Apps.
This app requires RTMS (Real-Time Media Streams) access to function. RTMS is Zoom's API for accessing live meeting audio and transcription data without requiring a bot in the meeting.
To get RTMS access:
- Request a Free Trial - Post in the Zoom Developer Forum requesting RTMS access for development
- Include your use case - Mention you're building a meeting assistant with Arlo
- Wait for approval - The Zoom team will enable RTMS on your account (usually within 1-2 business days)
Without RTMS access, this application will not work. The entire purpose of this starter kit is to demonstrate the power of RTMS for building real-time meeting intelligence.
β Once approved, you'll see RTMS features available in your Zoom App Marketplace settings.
- π Live Transcription - Real-time captions via RTMS (< 1s latency)
- π€ AI Insights - Summaries, action items, next steps (OpenRouter with free models)
- π Full-Text Search - Search across all meeting transcripts
- π¬ Chat with Transcripts - RAG-based Q&A over your meetings
- π― Meeting Highlights - Create bookmarks with timestamps
- π€ Export VTT - Download WebVTT files for video players
- π Home Dashboard β AI highlights and reminders from recent meetings
- π Dark Mode β OS detection with manual toggle, persisted preference
- π Export Markdown β Download meeting summary + transcript as MD
- ποΈ Multi-View Architecture β 14 views with HashRouter, shared AppShell
- π Secure - Zoom OAuth, encrypted tokens, ownership-enforced data isolation, rate limiting, HMAC webhook verification
- Node.js 20+ (Download)
- Docker + Docker Compose (Download)
- ngrok account + CLI (Sign up free) - Exposes localhost to internet for webhooks
- Zoom Account with Marketplace access
- π΄ RTMS Access - REQUIRED! Request via Zoom Developer Forum
π‘ Recommended: Create a free ngrok account to get a static domain - makes webhook testing much easier!
git clone https://github.com/your-org/arlo-meeting-assistant.git
cd arlo-meeting-assistantThis step is required before you can use RTMS features:
- Go to Zoom Developer Forum
- Create a new post with the title: "Request RTMS Access for Meeting Assistant Development"
- In your post, include:
Hi Zoom team, I'm building a meeting assistant using the Arlo Meeting Assistant starter kit and would like to request RTMS access for development and testing. Account email: [your-zoom-email@example.com] Use case: Building a real-time meeting assistant with live transcription App name: [Your App Name] Thank you! - Wait for approval (usually 1-2 business days)
- Once approved, RTMS features will appear in your Zoom App settings
- Go to Zoom App Marketplace
- Click Develop β Build App β General App
- Name your app (e.g., "Arlo Meeting Assistant")
- Note your Client ID and Client Secret
App Manifest (Beta): If you have access to the Zoom App Manifest beta, you can upload
zoom-app-manifest.jsonfrom this repo to pre-configure your app's scopes, SDK capabilities, event subscriptions, and more. See App Manifest below for details.
# Copy example environment file
cp .env.example .env
# Generate secrets
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" # SESSION_SECRET
node -e "console.log(require('crypto').randomBytes(16).toString('hex'))" # REDIS_ENCRYPTION_KEY
# Edit .env and add:
# - ZOOM_CLIENT_ID
# - ZOOM_CLIENT_SECRET
# - SESSION_SECRET (generated above)
# - REDIS_ENCRYPTION_KEY (generated above)ngrok creates a secure tunnel from the internet to your local development server, which is required for Zoom webhooks and OAuth callbacks.
First Time Setup:
-
Create a free ngrok account at ngrok.com
-
Install ngrok (if not already installed):
# macOS (Homebrew) brew install ngrok # Or download from https://ngrok.com/download
-
Authenticate ngrok with your account:
ngrok config add-authtoken YOUR_AUTHTOKEN
(Find your authtoken at https://dashboard.ngrok.com/get-started/your-authtoken)
π― Recommended: Use a Static Domain (FREE!)
ngrok now offers free static domains that don't change between restarts. This makes webhook configuration much easier since you won't need to update your Zoom App settings every time you restart ngrok.
-
Claim your free static domain:
- Go to https://dashboard.ngrok.com/domains
- Click "Create Domain" or "New Domain"
- You'll get a permanent domain like:
yourname-arlo.ngrok-free.app
-
Start ngrok with your static domain:
ngrok http 3000 --domain=yourname-arlo.ngrok-free.app
-
Benefits:
- β Same URL every time you restart ngrok
- β Configure Zoom webhooks once (no need to update)
- β Easier testing workflow
- β 100% free for development
Alternative: Use Random Domain (Changes Each Time)
If you prefer not to create an account or want a temporary setup:
ngrok http 3000Copy the https:// URL from the ngrok output (e.g., https://abc123.ngrok-free.app)
Verify ngrok is running:
Open your ngrok URL in a browser - you should see the Arlo frontend once the app is running.
In Zoom Marketplace β Your App:
Replace your-ngrok-url.ngrok-free.app below with your actual ngrok domain:
Basic Information:
- OAuth Redirect URL:
https://your-ngrok-url.ngrok-free.app/api/auth/callback - OAuth Allow List:
https://your-ngrok-url.ngrok-free.app
Features β Zoom App SDK:
- Add all required APIs (see CLAUDE.md)
β οΈ Enable RTMS β Transcripts (requires RTMS access approval)- Optional: Enable RTMS β Audio (for advanced features)
Features β Surface:
- Home URL:
https://your-ngrok-url.ngrok-free.app - Add to Domain Allow List:
https://your-ngrok-url.ngrok-free.app
Event Subscriptions (Important for RTMS!):
- Event notification endpoint URL:
https://your-ngrok-url.ngrok-free.app/api/rtms/webhook - Subscribe to events:
- β
meeting.rtms_started- Notifies when RTMS successfully starts - β
meeting.rtms_stopped- Notifies when RTMS ends
- β
- Copy your webhook URL from the "Event notification endpoint URL" field - you'll need this for testing
π‘ Pro Tip: If you're using a static ngrok domain, you only need to configure these webhooks once! With random domains, you'd need to update this URL every time you restart ngrok.
β‘ Optional: Auto-Start RTMS
To automatically start RTMS when meetings begin (without requiring users to click a button):
-
In Features β Event Subscriptions, also subscribe to:
meeting.participant_joined(to detect when you join a meeting)
-
In your backend code (
backend/src/routes/rtms.js), add a webhook handler:// Auto-start RTMS when participant joins if (event === 'meeting.participant_joined') { const { meeting_uuid, participant } = payload; // Check if this is the app user if (participant.id === appUserId) { await startRTMS(meeting_uuid); } }
-
Trade-off: Auto-start provides seamless UX but uses more RTMS quota. Manual start (current implementation) gives users control.
Note: The current implementation uses manual start (user clicks "Start Arlo") for better control and transparency.
# Edit .env
PUBLIC_URL=https://your-ngrok-url.ngrok-free.app# Install root dependencies
npm install
# Start with Docker (recommended)
docker-compose up --build
# OR start manually
npm run setup # Install all dependencies
npm run db:migrate # Run database migrations
npm run dev # Start all services- Start or join a Zoom meeting
- Click Apps β Find your app
- Click Add App (first time only)
- Authorize the app
- Click "Start Arlo"
- See live transcription appear!
Comprehensive guides available in /docs/:
- CLAUDE.md - Quick reference for Claude Code
- Architecture - System design and data flow
- Project Status - Roadmap and phases
- Specification - Feature spec and version milestones
- Troubleshooting - Common issues
- Zoom Apps Skills - SDK setup, RTMS guide, OAuth, security
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Zoom Meeting β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Arlo Meeting Assistant (React + Zoom SDK) β β
β ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββ
β HTTPS + WebSocket
ββββββββββββββββββΌβββββββββββββββββ
β Backend API (Express.js) β
β - OAuth 2.0 (PKCE) β
β - WebSocket Server β
β - RTMS Ingestion β
ββββββ¬ββββββββββββ¬βββββββββββββββββ
β β
βββββββββββΌββββ βββββΌβββββββββββββββ
β Postgres β β OpenRouter β
β Database β β (Free AI) β
βββββββββββββββ ββββββββββββββββββββ
Tech Stack:
- Frontend: React 18, Zoom Apps SDK 0.16, react-router-dom 6 (HashRouter), @base-ui/react, lucide-react
- Fonts: Source Serif 4 + Inter (self-hosted WOFF2)
- Backend: Node.js 20, Express, Prisma
- Database: PostgreSQL 15
- AI: OpenRouter (free models, no API key required)
- Real-time: WebSocket + RTMS SDK
arlo-meeting-assistant/
βββ backend/ # Express API server
β βββ src/
β β βββ server.js # Main server + rate limiting
β β βββ config.js # Environment config
β β βββ lib/prisma.js # Singleton PrismaClient
β β βββ routes/ # API routes (9 modules)
β β βββ services/ # Business logic
β βββ prisma/
β βββ schema.prisma # Database schema
β
βββ frontend/ # React Zoom App
β βββ public/
β β βββ index.html # Loads Zoom SDK
β β βββ fonts/ # Self-hosted Source Serif 4 + Inter
β βββ src/
β βββ App.js # HashRouter, routes, provider hierarchy
β βββ index.css # Design tokens, typography, themes
β βββ views/ # 14 views (Auth, Home, MeetingsList, MeetingDetail, InMeeting, Search, Settings, Upcoming, GuestΓ2, Landing, Onboarding, OAuthError, NotFound)
β βββ contexts/ # 5 contexts (Auth, ZoomSdk, Meeting, Theme, Toast)
β βββ hooks/ # useZoomAuth (OAuth PKCE)
β βββ utils/ # Shared formatters (timestamps, durations, dates)
β βββ components/ # AppShell, DeleteMeetingDialog, ParticipantTimeline, MeetingCard, etc.
β βββ components/ui/ # Button, Card, Badge, Input, Textarea, LoadingSpinner
β
βββ rtms/ # RTMS transcript ingestion
β βββ src/
β βββ index.js # Webhook handler + RTMS client
β
βββ docs/ # 15 comprehensive guides
βββ .env.example # Environment variables template
βββ zoom-app-manifest.json # Zoom App Manifest (beta)
βββ docker-compose.yml
βββ README.md
# Start all services
docker-compose up
# View logs
docker-compose logs -f backend
docker-compose logs -f rtms
# Restart service
docker-compose restart backend
# Database operations
npm run db:migrate # Run migrations
npm run db:studio # Open Prisma Studio GUI
npm run db:reset # Reset database (WARNING: deletes data)
# Clean restart
docker-compose down -v && docker-compose up --buildcd backend
# Create migration after schema changes
npx prisma migrate dev --name description_of_change
# Generate Prisma Client
npx prisma generate
# Reset database (development only)
npx prisma migrate reset- App loads in Zoom client
- OAuth flow completes
- "Start Arlo" button works
- Live transcript appears within 1s
- WebSocket connection stable
- Segments save to database
- Can scroll through transcript
- "Resume Live" button works
- Stop button ends RTMS
Frontend (Zoom App):
- Right-click in app β Inspect Element
- Check Console for errors
- Network tab shows API calls
Backend:
docker-compose logs -f backend | grep -i error
curl http://localhost:3000/healthDatabase:
npm run db:studio
# Opens GUI at http://localhost:5555RTMS:
docker-compose logs -f rtms
curl http://localhost:3002/healthThis is an open-source starter kit designed to be forked and customized!
- Fork this repository
- Modify for your use case:
- Add your own AI prompts
- Customize UI/styling
- Add new features
- Change AI provider
- Share your improvements (optional PR)
- Multi-language support
- Custom AI models (local LLMs)
- Team workspaces
- Calendar integration
- Video replay (like Fathom)
- Risk/compliance signals
- Background task extraction
- Public sharing links
Zoom App Manifests are JSON files that contain your app's configuration β scopes, SDK capabilities, event subscriptions, URLs, and more. This repo includes a pre-configured manifest at zoom-app-manifest.json that you can upload to quickly configure your Zoom App.
- You must be accepted into the Zoom App Manifest beta program (request access from Zoom)
- Your app must be a General App on the Zoom Marketplace
- You must be the account owner, admin, or have the "Zoom for developers" role
Before uploading, edit zoom-app-manifest.json and replace all instances of your-ngrok-url.ngrok-free.app with your actual ngrok domain (or production domain).
Upload to an existing app:
- Log into Zoom Marketplace β Manage β select your app
- Open the manifest panel (persistent menu bar or Basic Information page)
- Click Upload New Manifest and select
zoom-app-manifest.json - Zoom validates the manifest and shows a green checkmark on success
- Close the manifest window, refresh your browser, and confirm changes
Download from an existing app:
- In the manifest panel, click the download icon to save the current configuration
- Edit the JSON locally, then re-upload to apply changes
The manifest pre-configures:
- OAuth scopes:
zoomapp:inmeeting,meeting:read:meeting,meeting:write:open_app(optional),user:read(optional) - SDK capabilities: All 16 APIs used by Arlo (getMeetingContext, callZoomApi, authorize, showNotification, etc.)
- Event subscriptions:
meeting.rtms_started,meeting.rtms_stopped - In-client OAuth: Enabled (PKCE flow)
- Guest mode: Enabled with test guest mode
- Domain allow list: Your ngrok domain +
appssdk.zoom.us
- Manifests can only update existing apps, not create new ones
- Only user-editable values are updated; the build-flow UX verifies completeness
- Values are case-sensitive and must match Zoom's expected format
- RTMS access still requires separate approval from Zoom (the manifest alone does not grant RTMS)
MIT License - See LICENSE for details
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- RTMS Access Requests: Zoom Developer Forum - Post here to request free RTMS trial
- General Zoom Support: devforum.zoom.us
Built with:
Ready to build your own meeting assistant? Star this repo β and get started!
