Skip to content

zoom/arlo

Arlo the meeting assistant

Arlo Meeting Assistant πŸ¦‰

Your intelligent meeting companion that lives inside Zoom


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.


⚠️ IMPORTANT: RTMS Access Required

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:

  1. Fill out the RTMS access form at zoom.com/realtime-media-streams
  2. Describe your use case - Mention you're building a meeting assistant
  3. Wait for approval - The Zoom team will review your request and enable RTMS on your account

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.


✨ Features

  • πŸ“ 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
  • πŸ₯ Industry Verticals β€” Specialized modes for Healthcare, Legal, Sales, Customer Support, and general note-taking

πŸ₯ Industry Verticals

Arlo supports industry-specific modes that customize the AI prompts, features, terminology, and UI for different use cases. Select your vertical during first-run setup or change it anytime in Settings.

General (Default Note-Taker)

The full-featured default mode for any meeting type β€” team syncs, 1:1s, project meetings, and more.

  • Meeting Summary β€” Collapsible AI-generated summary with key points, auto-refreshes as meeting progresses
  • Key Moments β€” Auto-detected highlights (announcements, agreements, concerns, insights, milestones) with star/favorite
  • Participant Stats β€” Talk time breakdown, visual participation chart, balance indicator
  • Decisions Log β€” Track decisions with who made them, auto-detected + manual entry
  • Open Questions β€” Capture unanswered questions with open/answered/all filters
  • Smart Bookmarks β€” Quick one-click bookmarking with categories (Important, Follow Up, Idea, Favorite)
  • Notes β€” Free-form meeting notes textarea
  • Action Items β€” Track tasks with owner assignment

Healthcare (Clinical Documentation)

Designed for doctors and clinicians who need to document patient encounters while staying present with their patients.

  • SOAP Notes Panel β€” Auto-populated Subjective, Objective, Assessment, and Plan sections
  • Patient Context β€” Sidebar showing conditions, allergies, and medications
  • Previous Sessions β€” Quick access to past appointment notes
  • Clinical Alerts β€” Real-time warnings for drug interactions, contradictions, allergy mentions
  • Quick Actions β€” One-click lab orders, referrals, Rx templates, follow-up scheduling
  • Healthcare Tags β€” Auto-extracted symptoms, diagnoses, medications, procedures

Legal (Depositions & Testimony)

Built for attorneys handling depositions, client interviews, and witness testimony.

  • Contradiction Detector β€” Flags conflicting statements with severity levels and side-by-side comparison
  • Legal Terms Panel β€” Auto-extracts parties, dates, amounts, locations, documents, and legal citations
  • Exhibit Tracker β€” Log and track document references with timestamps and context
  • Privilege Markers β€” Mark attorney-client, work product, and confidential sections

Sales (Deal Tracking & Qualification)

Built for sales professionals tracking deals, competitive intelligence, and buyer signals.

  • Deal Tracker β€” Opportunity details with pipeline stage visualization, value, close date, key contacts
  • Deal Qualification β€” Track Budget, Authority, Need, Timeline criteria with detected signals
  • Competitor Mentions β€” Real-time detection with sentiment analysis (positive/negative/neutral/mixed)
  • Commitments Panel β€” Track next steps with owner assignment (us vs them), due dates, completion status
  • Call Notes β€” Free-form notes for key takeaways and follow-ups

Customer Support (Call Center)

Built for support agents handling customer calls β€” aligned with Zoom's upcoming Call Center RTMS support.

  • Sentiment Meter β€” Live animated gauge showing customer mood (Angry β†’ Frustrated β†’ Neutral β†’ Satisfied β†’ Happy) with trend indicator
  • Escalation Alerts β€” Real-time detection of manager requests, churn risk, frustration signals with acknowledge/dismiss actions
  • Resolution Tracker β€” Visual workflow (Issue Identified β†’ Solution Offered β†’ Resolution Confirmed) with handle time tracking
  • Agent Assist β€” Contextual knowledge base suggestions + compliance checklist with progress tracking
  • Quick Responses β€” One-click copy for empathy, hold, clarify, and resolve templates

πŸš€ Quick Start

Prerequisites

πŸ’‘ Recommended: Create a free ngrok account to get a static domain - makes webhook testing much easier!

1. Clone Repository

git clone https://github.com/your-org/arlo-meeting-assistant.git
cd arlo-meeting-assistant

2. Request RTMS Access (Critical!)

This step is required before you can use RTMS features:

  1. Go to zoom.com/realtime-media-streams
  2. Fill out the access request form with your details
  3. Describe your use case (e.g., "Building a real-time meeting assistant with live transcription")
  4. Wait for approval - The Zoom team will review and enable RTMS on your account
  5. Once approved, RTMS features will appear in your Zoom App settings

3. Create Zoom App

  1. Go to Zoom App Marketplace
  2. Click Develop β†’ Build App β†’ General App
  3. Name your app (e.g., "Arlo Meeting Assistant")
  4. 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.json from this repo to pre-configure your app's scopes, SDK capabilities, event subscriptions, and more. See App Manifest below for details.

4. Configure Environment

# 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)

5. Set Up ngrok (Expose Local Server to Internet)

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:

  1. Create a free ngrok account at ngrok.com

  2. Install ngrok (if not already installed):

    # macOS (Homebrew)
    brew install ngrok
    
    # Or download from https://ngrok.com/download
  3. 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.

  1. Claim your free static domain:

  2. Start ngrok with your static domain:

    ngrok http 3000 --domain=yourname-arlo.ngrok-free.app
  3. 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 3000

Copy the https:// URL from the ngrok output (e.g., https://abc123.ngrok-free.app)

⚠️ Note: This URL changes every time you restart ngrok, requiring you to update all Zoom App webhook URLs each time.

Verify ngrok is running:

Open your ngrok URL in a browser - you should see the Arlo frontend once the app is running.

6. Update Zoom App Configuration

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):

  1. In Features β†’ Event Subscriptions, also subscribe to:

    • meeting.participant_joined (to detect when you join a meeting)
  2. 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);
      }
    }
  3. 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.

7. Update .env with ngrok URL

# Edit .env
PUBLIC_URL=https://your-ngrok-url.ngrok-free.app

8. Start Application

# 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

9. Test in Zoom

  1. Start or join a Zoom meeting
  2. Click Apps β†’ Find your app
  3. Click Add App (first time only)
  4. Authorize the app
  5. Click "Start Arlo"
  6. See live transcription appear!

πŸ“š Documentation

Comprehensive guides available in /docs/:


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    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

πŸ› οΈ Development

Project Structure

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/           # 15 views (Auth, Home, MeetingsList, MeetingDetail, InMeeting, Search, Settings, Upcoming, GuestΓ—2, Landing, Onboarding, OAuthError, NotFound, VerticalSelector)
β”‚       β”œβ”€β”€ contexts/        # 6 contexts (Auth, ZoomSdk, Meeting, Theme, Toast, Vertical)
β”‚       β”œβ”€β”€ features/        # Industry vertical components
β”‚       β”‚   β”œβ”€β”€ general/     # Meeting summary, key moments, decisions, questions, participation, bookmarks
β”‚       β”‚   β”œβ”€β”€ healthcare/  # SOAP notes, clinical alerts, patient context, quick actions
β”‚       β”‚   β”œβ”€β”€ legal/       # Contradiction detector, exhibit tracker, privilege markers
β”‚       β”‚   β”œβ”€β”€ sales/       # Deal tracker, qualification, competitor mentions, commitments
β”‚       β”‚   └── support/     # Sentiment meter, escalation alerts, resolution tracker, agent assist
β”‚       β”œβ”€β”€ hooks/           # useZoomAuth (OAuth PKCE)
β”‚       β”œβ”€β”€ utils/           # Shared formatters (timestamps, durations, dates)
β”‚       β”œβ”€β”€ components/      # AppShell, ArloLogo, 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

Common Commands

# 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 --build

Database Migrations

cd 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

πŸ§ͺ Testing

Manual Testing Checklist

  • 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

Debugging

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/health

Database:

npm run db:studio
# Opens GUI at http://localhost:5555

RTMS:

docker-compose logs -f rtms
curl http://localhost:3002/health

🀝 Contributing

This is an open-source starter kit designed to be forked and customized!

How to Customize

  1. Fork this repository
  2. Modify for your use case:
    • Add your own AI prompts
    • Customize UI/styling
    • Add new features
    • Change AI provider
  3. Share your improvements (optional PR)

Feature Ideas

  • 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

πŸ“¦ App Manifest (Beta)

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.

Prerequisites

  • 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

Using the Manifest

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:

  1. Log into Zoom Marketplace β†’ Manage β†’ select your app
  2. Open the manifest panel (persistent menu bar or Basic Information page)
  3. Click Upload New Manifest and select zoom-app-manifest.json
  4. Zoom validates the manifest and shows a green checkmark on success
  5. Close the manifest window, refresh your browser, and confirm changes

Download from an existing app:

  1. In the manifest panel, click the download icon to save the current configuration
  2. Edit the JSON locally, then re-upload to apply changes

What's Included

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

Limitations (Beta)

  • 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)

πŸ“– Learn More


βš–οΈ License

MIT License - See LICENSE for details


πŸ’¬ Support


🌟 Acknowledgments

Built with:


Ready to build your own meeting assistant? Star this repo ⭐ and get started!

About

Arlo is a meeting assistant that runs natively in Zoom as an embedded app. Using Realtime Media Streams (RTMS) and the Apps SDK, it captures live transcripts, generates summaries and delivers meeting intelligence all running natively inside of a Zoom meeting. Designed for developers building the next generation of meeting tools.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Contributors