This codelab focuses on building a Zoom App using Next.js. The sample application serves as a boilerplate that demonstrates how to extend a web application into the Zoom client and integrate with various Zoom services. You'll learn how to create a Zoom Marketplace app using the Zoom Manifest API, integrate Supabase for authentication, and surface the application within the Zoom client. This tutorial also introduces core concepts for building engaging experiences in Zoom Workplace—including Zoom Apps, Team Chat, chatbots, and deep linking from the browser to the Zoom client.

⚠️ Warning: Some feature requires a paid plan.

💡 Tip: If you don't have a paid workspace for development, you can join by signing up for a free Zoom account, which provides access to all Zoom Developer platform features. To learn more about powering your service with Zoom, visit Zoom for Startups.

✓ How to structure and configure the manifest JSON to define your app's properties and integration points with Zoom.

✓ How to implement secure API communication by configuring proper OAuth scopes and webhook endpoints.

✓ How to manage manifest versioning to maintain your app's functionality during updates.

What you'll Need

Prerequisites

Ngrok is a tool that creates secure tunnels to your local development server, allowing you to expose your localhost to the internet over HTTPS. It's especially useful for testing webhooks, APIs, or any feature that requires a publicly accessible URL during development.

In this tutorial, ngrok is used to serve the sample Zoom App over HTTPS. This is a requirement for all Zoom Apps, as they must be hosted on a secure (HTTPS) endpoint in order to be embedded within the Zoom client and interact with Zoom services.

To run multiple ngrok connections using a configuration file:

ngrok start nextjs supabase

Ngrok will output the origin it has created for your tunnel, eg https://9a20-38-99-100-7.ngrok.io. You should see the tunnel traffic:

Use your ngrok URL

After starting ngrok, you'll get a public HTTPS URL like https://9a20-38-99-100-7.ngrok.io. Use those origins for any Zoom Manifest or configuration that requires a secure URL.

Replace any placeholder URL such as https://example.ngrok.io with your actual ngrok-generated URL.

For example:

"https://example.ngrok.io" → "https://9a20-38-99-100-7.ngrok.io"

Make sure to update all instances in your manifest file, environment variables, and redirect URIs accordingly.

App manifests are JSON files that define the configuration of Zoom App Marketplace apps.

Manifest schema

Manifests are JSON-formatted configuration files for Zoom Apps. You can use a manifest to create a general app via the Marketplace build flow or API, or to update the configuration of an existing general app. Manifests are portable, allowing you to share and reuse them across environments.

In this section, you will create a user-managed Zoom App Marketplace general app and configure it with Zoom App and Team Chatbot features.

Create your App: How to Create and Configure a Zoom App (User-Managed) with the Manifest API

  1. Visit the Zoom App Marketplace
  2. Start Building a New App
    • Click the "Develop" dropdown in the top-right.
    • Select "Build App".
  3. Choose App Type:
    • When prompted to choose an app type, select "General App" unless you have a specific use case.
    • Click "Create".
  4. Choose App Management Type
    • Select User-managed App. This allows individual users to install and authorize your app to access their Zoom data — similar to apps accessing a user's Google Drive or Gmail
  5. Configure Basic App Information
    • On the "Basic Information" page:
    • Scroll down to the Redirect URL for OAuth section. For testing with Postman, add the Postman redirect URI:
https://oauth.pstmn.io/v1/callback

  1. Get App ID from URL: App ID
  2. Make a PATCH request to update the app (test with Postman). After configuring the app, test it by sending a PATCH request to Zoom's API to update your app metadata or description.

Example Postman setup:

Use the Ngrok output origins created for your tunnel, eg https://9a20-38-99-100-7.ngrok.io:

{
  "manifest": {
      "display_information": {
          "display_name": "Zoom Apps Next.js Sample App"
      },
      "oauth_information": {
          "usage": "USER_OPERATION",
          "development_redirect_uri": "https://example.ngrok.io/auth/callback",
          "production_redirect_uri": "",
          "oauth_allow_list": [
              "https://example-backend.ngrok.io/auth/v1/callback",
              "https://oauth.pstmn.io/v1/callback",
              "https://example.ngrok.io/auth/callback"
          ],
          "strict_mode": false,
          "subdomain_strict_mode": false,
          "scopes": [
              {
                  "scope": "marketplace:read:app",
                  "optional": false
              },
              {
                  "scope": "user:read:user",
                  "optional": false
              },
              {
                  "scope": "zoomapp:inmeeting",
                  "optional": false
              },
              {
                  "scope": "imchat:userapp",
                  "optional": false
              }
          ]
      },
      "features": {
          "products": [
              "ZOOM_CHAT",
              "ZOOM_MEETING"
          ],
          "development_home_uri": "https://example.ngrok.io",
          "production_home_uri": "",
          "domain_allow_list": [
              {
                  "domain": "appssdk.zoom.us",
                  "explanation": ""
              },
              {
                  "domain": "ngrok.io",
                  "explanation": ""
              }
          ],
          "in_client_feature": {
              "zoom_app_api": {
                  "enable": false,
                  "zoom_app_apis": []
              },
              "guest_mode": {
                  "enable": false,
                  "enable_test_guest_mode": false
              },
              "in_client_oauth": {
                  "enable": false
              },
              "collaborate_mode": {
                  "enable": false,
                  "enable_screen_sharing": false,
                  "enable_play_together": false,
                  "enable_start_immediately": false,
                  "enable_join_immediately": false
              }
          },
          "zoom_client_support": {
              "mobile": {
                  "enable": false
              },
              "zoom_room": {
                  "enable": false,
                  "enable_personal_zoom_room": false,
                  "enable_shared_zoom_room": false,
                  "enable_digital_signage": false,
                  "enable_zoom_rooms_controller": false
              },
              "pwa_client": {
                  "enable": false
              }
          },
          "embed": {
              "meeting_sdk": {
                  "enable": false,
                  "enable_device": false,
                  "devices": []
              },
              "contact_center_sdk": {
                  "enable": false
              },
              "phone_sdk": {
                  "enable": false
              }
          },
          "team_chat_subscription": {
              "enable": true,
              "enable_support_channel": false,
              "slash_command": {
                  "command": "hello_world",
                  "command_hints": [],
                  "enable_add_to_channel": false,
                  "development_message_url": "https://example.ngrok.io/api/zoom/webhooks/chatbot",
                  "production_message_url": "",
                  "sender_type": "zoom",
                  "welcome_msg": {
                      "title": "",
                      "body": ""
                  },
                  "trust_domain_list": []
              },
              "shortcuts": [
                  {
                      "shortcut_id": "",
                      "action_label": "Open App",
                      "action_id": "app_opened",
                      "action_types": [
                          "MESSAGE_ACTION",
                          "COMPOSE_BOX"
                      ],
                      "action_usage": "DIALOG",
                      "dialog_config": {
                          "title": "create_message",
                          "size": "M"
                      }
                  }
              ]
          },
          "event_subscription": {
              "enable": false,
              "events": []
          }
      }
  }
}

Resource:

  1. Update an app by manifest API

Supabase is an open-source backend-as-a-service platform that provides developers with a set of tools to build scalable web and mobile applications quickly. It is built on top of PostgreSQL and offers instant APIs, real-time capabilities, authentication, and database management through a user-friendly interface.

Key features of Supabase include:

Supabase offers a developer-friendly alternative to Firebase, with the advantage of SQL-based querying and full control over your data.

Install Supabase CLI

Follow these instructions for installing Supabase CLI for local development:

Supabase configuration:

Congratulations! You have successfully built a multi-feature Zoom app using a manifest file.

To continue learning and extend your app's capabilities, explore the following resources:

Learn more