LogoRobo.js

Embedded App SDK

Connect your activity to Discord

The Embedded App SDK (@discord/embedded-app-sdk) connects your activity to Discord. Since activities run inside Discord's embedded frame, this SDK provides the bridge between your web app and Discord's features — handling authorization, authentication, and access to Discord APIs.

Setup

The SDK is included in activity templates. DiscordContextProvider wraps the app in src/app/App.tsx:

This code is already in your project if you used the activity template.

src/app/App.tsx
import { DiscordContextProvider } from '../hooks/useDiscordSdk'
import { Activity } from './Activity'

export default function App() {
  return (
    <DiscordContextProvider authenticate scope={['identify', 'guilds']}>
      <Activity />
    </DiscordContextProvider>
  )
}
src/app/App.jsx
import { DiscordContextProvider } from '../hooks/useDiscordSdk'
import { Activity } from './Activity'

export default function App() {
  return (
    <DiscordContextProvider authenticate scope={['identify', 'guilds']}>
      <Activity />
    </DiscordContextProvider>
  )
}

This provider initializes the SDK, handles the OAuth2 flow, and makes the SDK instance available to child components.

DiscordContextProvider

PropTypeDescription
authenticatebooleanPrompt users to authenticate on load
scopestring[]OAuth2 scopes to request
loadingScreenReactNodeComponent shown during authentication

When authenticate is set, the provider automatically runs the full authorization and authentication flow on mount.

useDiscordSdk Hook

Access SDK state and user data from any component:

src/app/Activity.tsx
import { useDiscordSdk } from '../hooks/useDiscordSdk'

export function Activity() {
  const { authenticated, session, status } = useDiscordSdk()

  if (!authenticated) {
    return <div>Connecting...</div>
  }

  return <div>Welcome, {session?.user.username}</div>
}
src/app/Activity.jsx
import { useDiscordSdk } from '../hooks/useDiscordSdk'

export function Activity() {
  const { authenticated, session, status } = useDiscordSdk()

  if (!authenticated) {
    return <div>Connecting...</div>
  }

  return <div>Welcome, {session?.user.username}</div>
}
FieldTypeDescription
accessTokenstring | nullOAuth2 access token
authenticatedbooleanWhether authentication succeeded
discordSdkDiscordSDKSDK instance
errorstring | nullError message if authentication failed
sessionDiscordSession | nullAuthenticated user session
statusstringCurrent status: pending, loading, authenticating, ready, error

Status progresses: pending -> loading -> authenticating -> ready (or error if something goes wrong at any step).

A Discord Activity running in the embedded panel showing 'Welcome, username', demonstrating the SDK has authenticated the user and retrieved session data

FocusThe activity displaying the authenticated user's username from SDK sessionZoom100%NotesShow a Discord Activity in a voice channel embedded panel displaying 'Welcome, [username]'. Discord UI around the activity should be visible for context.

SDK Instance

The discordSdk object provides access to Discord commands and events.

CommandDescription
ready()Signal the SDK is ready
commands.authorize()Request OAuth2 authorization
commands.authenticate()Authenticate with an access token
commands.getChannel()Get current channel info
commands.getInstanceConnectedParticipants()List connected participants
subscribe()Subscribe to SDK events

Example using the SDK instance directly:

src/app/Activity.tsx
const { discordSdk } = useDiscordSdk()

const channel = await discordSdk.commands.getChannel({ channel_id: discordSdk.channelId })
src/app/Activity.jsx
const { discordSdk } = useDiscordSdk()

const channel = await discordSdk.commands.getChannel({ channel_id: discordSdk.channelId })

Mock Mode

The template auto-detects whether the app runs inside Discord by checking for a frame_id query parameter — a value Discord adds to the URL when loading your app inside its embedded frame. Outside Discord, it uses DiscordSDKMock for local development.

Mock mode generates random values for user, guild, and channel IDs, stored in session storage so they persist across refreshes within the same tab.

Override mock values via query parameters:

ParameterDescription
user_idOverride the mock user ID
guild_idOverride the mock guild ID
channel_idOverride the mock channel ID

A browser window showing the activity running at localhost outside of Discord, operating in mock mode with randomly generated user data

FocusThe activity in a standalone browser window with mock dataZoom100%NotesShow browser at localhost:5173 with the activity running outside Discord. Mock data visible (random username or mock ID). Browser address bar showing localhost to emphasize it's outside Discord.

Vanilla Projects

For non-React projects, import the SDK directly. Call ready() and handle authorization and authentication manually:

src/app/main.ts
import { DiscordSDK } from '@discord/embedded-app-sdk'

const discordSdk = new DiscordSDK(import.meta.env.VITE_DISCORD_CLIENT_ID)
await discordSdk.ready()
src/app/main.js
import { DiscordSDK } from '@discord/embedded-app-sdk'

const discordSdk = new DiscordSDK(import.meta.env.VITE_DISCORD_CLIENT_ID)
await discordSdk.ready()

See the Authentication page for the full vanilla authorization flow, including the code-for-token exchange.

Next Steps

On this page