Ludicord
Guide 01 · Start here

Getting started

Create your first Ludicord Activity and understand the development loop.

Ludicord 3.1.0Public source 20c4889

Ludicord is a full-stack React framework for Discord Activities. It connects the Activity UI, Discord identity, trusted HTTP handlers, and realtime connections in one project. This guide takes you from an empty folder to a running Activity.

iNote

Before you begin: Install Node.js 20.19 or newer and create a Discord application. You can preview the UI in a normal browser, but real guild, channel, user, and Activity-instance data only exists when Discord launches the Activity.

#Create a project

Run the generator and choose a project name. Tailwind CSS is enabled by default; answer n if you prefer plain CSS.

Terminalbash
1npx create-ludicord-app@latest my-activity
2cd my-activity

For a repeatable non-interactive setup, pass the choices as flags:

Terminalbash
1npx create-ludicord-app@latest my-activity --tailwind --package-manager npm --git

The generator installs Ludicord, React, TypeScript, and the selected styling tools. It also creates working examples for an embed, a protected API route, and a realtime audience counter.

#Add your Discord credentials

Copy .env.example to .env.local, then add the application values from the Discord Developer Portal.

.env.localdotenv
1LUDICORD_DISCORD_CLIENT_ID=your_application_id
2LUDICORD_DISCORD_CLIENT_SECRET=your_client_secret
3LUDICORD_SESSION_SECRET=use_a_random_value_at_least_32_characters
4LUDICORD_DISCORD_PUBLIC_KEY=your_public_key

Never commit .env.local. Only the Client ID is safe to expose to the Activity browser. The Client Secret and Session Secret are read by the Ludicord server.

#Start development

Terminalbash
1npm run dev

Ludicord prints the local URL and compiles the files under app/. Open the URL for a browser preview. Edit app/embeds/home/embed.tsx; a successful client update uses Fast Refresh, while API and WebSocket route edits reload without restarting the development server.

The browser preview is intentionally limited. outsideDiscord: "allow" lets the page render, but Discord hooks return unavailable data until the Activity is launched inside Discord.

#Understand the first render

app/pages.tsx is the persistent shell. EmbedOutlet renders the active screen from app/embeds, starting with home.

app/pages.tsxtsx
1import { EmbedOutlet, LudicordActivity } from "ludicord";
2import "./globals.css";
3
4export default function Pages() {
5 return (
6 <LudicordActivity defaultEmbed="home">
7 <EmbedOutlet />
8 </LudicordActivity>
9 );
10}

The framework discovers the root and embed files, generates route types, initializes Discord, and supplies loading or error boundaries around the active screen.

#Your development loop

ActionWhat Ludicord does
Edit an embed or componentRecompiles the client and preserves compatible React state
Add an embed.tsxDiscovers a new typed screen route
Edit an API route.tsReplaces the server handler without a process restart
Edit a WebSocket route.tsReloads the route and reconnects affected clients
Run npm run buildValidates routes, types, client assets, and server output

#Next step

Continue to Installation for every generator option, or jump to Discord setup when the local UI is already running.