Quick Start
Create and run your first Discord Activity
Get a Discord Activity running in minutes with Robo.js.
Prerequisites
- Node.js 18 or later.
- A code editor such as VS Code.
- A Discord account.
- A Discord server you can test in (create one if needed).
Create a Project
Run the scaffolding command and select the activity kit:
npx create-robo@next my-activityFollow the prompts to configure your project. The default template uses React.
Terminal showing the create-robo CLI prompts during activity project creation, with the activity kit selected and React template options visible
Project Structure
src/app/— Frontend UI components.App.tsxis the entry point,Activity.tsxrenders the main view.src/api/— Backend API endpoints.token.tshandles authentication with Discord (exchanges a temporary code for an access token that proves the user's identity).src/hooks/— React hooks.useDiscordSdk.tsxinitializes the Embedded App SDK.config/vite.mjs— Vite configuration for the frontend build..env— Environment variables (configuration values stored outside your code, keeping secrets like passwords out of your source files).
Set Up Credentials
Before running your activity, create a Discord application and configure your environment variables.
- Go to the Discord Developer Portal and create a new application (see Developer Portal Setup for detailed steps).
- Copy your Application ID from the General Information tab.
- Copy your Client Secret from the OAuth2 tab.
- Add these values to the
.envfile in your project root:
# .env
DISCORD_CLIENT_ID="your_application_id"
VITE_DISCORD_CLIENT_ID="your_application_id"
DISCORD_CLIENT_SECRET="your_client_secret"Both DISCORD_CLIENT_ID and VITE_DISCORD_CLIENT_ID must be set to the same value. See Credentials for a full explanation of each variable.
A code editor showing the .env file with DISCORD_CLIENT_ID, VITE_DISCORD_CLIENT_ID, and DISCORD_CLIENT_SECRET environment variables filled in
Your First Change
Open src/app/Activity.tsx and modify the content:
export function Activity() {
return (
<div>
<h1>Hello, Discord!</h1>
</div>
)
}export function Activity() {
return (
<div>
<h1>Hello, Discord!</h1>
</div>
)
}Save the file. The dev server picks up changes automatically via hot reload.
Run in Development
Start the development server:
npm run devA tunnel creates a public HTTPS URL that points to your local computer, which Discord requires to load your activity. The scaffolded dev script includes the --tunnel flag, so a tunnel URL appears in the terminal output automatically.
You should see output similar to this in your terminal:
Ready on port 3000
Tunnel URL: https://abc-123-xyz.trycloudflare.comCopy the tunnel URL from your terminal and paste it as the Root Mapping in the Developer Portal's URL Mappings. Without this, Discord cannot reach your local server.
Terminal output showing the Robo.js dev server running with a Cloudflare tunnel URL, indicating the server is ready with an HTTPS tunnel for Discord testing
Test on Discord
Open Discord and join a voice channel. Click the Activities button (the rocket ship icon) in the voice channel toolbar, then select your activity from the list.
Discord voice channel with the Activities shelf open, showing the custom activity listed, with the rocket ship icon button visible in the toolbar
Troubleshooting
| Issue | Solution |
|---|---|
npx robo dev fails to start | Ensure Node.js 18+ is installed. Run node -v to check. |
| Activity not appearing in Discord | Verify URL Mappings in the Developer Portal match the tunnel URL from the terminal. |
| Blank screen after launching | Check the browser console for Content Security Policy (CSP) errors — these are browser rules controlling which URLs your app can load. Ensure DiscordProxy.Vite() is in config/vite.mjs. This Vite plugin rewrites network requests so they work through Discord's proxy. |
| Authentication errors | Confirm DISCORD_CLIENT_ID, VITE_DISCORD_CLIENT_ID, and DISCORD_CLIENT_SECRET are set correctly in .env. |
| Hot reload not working | Make sure the dev server is running (npx robo dev). Check for syntax errors in your code. |
| Tunnel URL not appearing | Check your internet connection. The Cloudflare tunnel requires outbound access. |
