Frameworks
Nextjs
Next.js App Router
PresenceKit's React hooks subscribe in a client component. Keep your Next.js route/page as a Server Component if desired; place the live widget behind "use client".
terminalbash
bun add @iconical/presencekitClient component
components/discord-presence.tsx:
components/discord-presence.tsxtsx
"use client";
import { LivePresenceCard } from "@iconical/presencekit/react-ui";
export default function DiscordPresence() {
return (
<LivePresenceCard
userId="123456789012345678"
theme={{ accent: "#ac1c23" }}
loadingFallback={<p>Connecting to PresenceKit…</p>}
errorFallback={<p>Presence is currently unavailable.</p>}
/>
);
}Then use it in your route:
app/page.tsxtsx
import DiscordPresence from "@/components/discord-presence";
export default function Page() {
return <main><DiscordPresence /></main>;
}Custom activity layout
components/status-widget.tsxtsx
"use client";
import { usePresence } from "@iconical/presencekit/react";
import { ActivityArtwork } from "@iconical/presencekit/react-ui";
export function MyActivities({ userId }: { userId: string }) {
const { data, loading, error } = usePresence({ userId });
if (loading) return <p>Loading…</p>;
if (error || !data?.presence) return <p>No activity.</p>;
return <div>{data.presence.activities.map((activity, index) => (
<div key={activity.id ?? `${activity.name}-${index}`}>
<ActivityArtwork activity={activity} preferred="cover" size={48} />
<span>{activity.name}</span>
</div>
))}</div>;
}ActivityArtwork uses an ordinary HTML img, so it does not require adding artwork hosts to Next.js images.remotePatterns. It handles broken URLs with an alternate image and initials fallback.
Important
- Do not instantiate a browser-tab shared connection manager as a process-global server singleton.
- The hook keeps visitor subscriptions in client components, and automatically cleans up.
- The npm package needs no
NEXT_PUBLIC_*API key: the official API endpoint is built in. - Handle
pending/nullsnapshots and revoked sharing.
Was this page helpful?