Discord data
Read complete user, guild, channel, role, permission, member, and raw payload data.
{ user_id: "742…", global_name: "Choler", voice_state: {…} }→
Ludicord exposes convenient normalized fields and preserves the complete Discord response in raw. This gives common UI a stable shape without hiding fields that advanced Activities need.
#Read user, guild, and channel
1import { useDiscordChannel, useDiscordGuild, useDiscordUser } from "ludicord/discord";23export default function embed() {4 const user = useDiscordUser();5 const guild = useDiscordGuild();6 const channel = useDiscordChannel();78 return <p>{user?.displayName} in {guild?.name} / {channel?.name}</p>;9}
The hooks return null until the data exists. An ID can be available before extended names or metadata, so render defensively.
#Normalized fields and raw payloads
raw is read-only and contains the complete object received for that resource, excluding OAuth credentials. Discord may add fields over time, so validate an unknown raw field before using it.
1const accentColor = typeof guild?.raw.accent_color === "number"2 ? guild.raw.accent_color3 : null;
#Read the combined snapshot
useDiscordData() returns the complete reactive event snapshot: user, guild, channel, participants, voice state, speaking IDs, layout, locale, diagnostics, scopes, permissions, members, entitlements, and latest raw events.
1const discord = useDiscordData();23return <pre>{JSON.stringify({4 channel: discord.channel?.raw,5 member: discord.currentGuildMember?.raw,6 scopes: discord.scopes,7}, null, 2)}</pre>;
Use focused hooks in ordinary components so they rerender only for the state they need. Use the combined snapshot for diagnostics and dashboards.
#Load guild channels, roles, and members
Extended guild data comes from Ludicord's trusted server bridge, not directly from browser-supplied IDs.
1const channels = useDiscordGuildChannels();2const roles = useDiscordGuildRoles();3const member = useDiscordGuildMember();4const permissions = useDiscordPermissions();
Each server resource provides data, status, error, updatedAt, and refresh(). Keep loading and unavailable states visible instead of substituting fake names.
#Paginate the full guild member list
1const roster = useDiscordGuildMembers({ limit: 100 });23return <button disabled={!roster.hasMore || roster.status === "loading"} onClick={roster.loadMore}>4 Load more members5</button>;
Full guild member lists require a server-only bot token and Discord's GUILD_MEMBERS privileged intent. A participant list is not a substitute: participants are people inside this Activity instance, while a guild roster may include everyone in the server.
#Call supported Discord commands
useDiscordCommands() exposes the installed SDK commands without allowing application code to replace Ludicord's authorization commands.
1const commands = useDiscordCommands();23async function openInvite() {4 if (commands.supports("openInviteDialog")) {5 await commands.call("openInviteDialog");6 }7}
Command support depends on Discord client, platform, context, and granted scopes. Check supports() and handle rejection.
#Work with permission bitfields
useDiscordPermissions() preserves the original bitfield strings and adds safe hasGuild, hasChannel, and hasMember helpers that accept bigint, number, or string permission values.
Permission checks in client UI can hide unavailable controls. Repeat every security-sensitive decision on the trusted server.
#Next step
Use Participants and voice to model the people currently in the Activity and their live voice state.