@rooguy/react
v1.0.1
Published
Rooguy Drop-In UI SDK for React
Readme
@rooguy/react
Drop-in React components and headless hooks for adding gamification UI to your React app. Leaderboards, quests, user profiles, storefronts, toast notifications — all with real-time SSE updates, theming, i18n, and accessibility baked in.
Installation
npm install @rooguy/reactPeer dependencies (you likely already have these):
npm install react react-domQuick Start
Wrap your app with RooguyProvider and drop in any widget:
import { RooguyProvider, RooguyLeaderboard } from "@rooguy/react";
function App() {
return (
<RooguyProvider
publishableKey="pk_live_abc123"
userToken="eyJhbGciOi..."
baseUrl="https://api.rooguy.com"
>
<RooguyLeaderboard timeframe="weekly" />
</RooguyProvider>
);
}Provider
<RooguyProvider> initializes the SDK, resolves the user, opens an SSE connection for real-time updates, and provides context to all child widgets and hooks.
| Prop | Type | Required | Description |
| ---------------- | ---------------------------------------- | -------- | ------------------------------------------------------------------- |
| publishableKey | string | Yes | Your project's publishable API key |
| userToken | string | No | JWT identifying the current user. Omit for anonymous read-only mode |
| baseUrl | string | No | API base URL (defaults to production) |
| theme | ThemeConfig | No | Custom theme overrides (maps to --rooguy-* CSS variables) |
| i18n | Partial<I18nDictionary> | No | Translation overrides |
| dir | 'ltr' \| 'rtl' | No | Text direction |
| analytics | 'full' \| 'interactions-only' \| 'off' | No | Analytics tracking mode (default: 'off') |
| onError | (error: RooguyError) => void | No | Global error callback |
Widgets
All widgets accept classes, fallback, and i18n props for customization.
RooguyLeaderboard
<RooguyLeaderboard
leaderboardId="weekly-top"
timeframe="weekly"
highlightCurrentUser
limit={10}
/>RooguyQuestList
<RooguyQuestList status="in_progress" />RooguyUserWidget
<RooguyUserWidget layout="compact" />RooguyStorefront
<RooguyStorefront limit={12} />RooguyUserProfile
<RooguyUserProfile sections={["header", "stats", "badges", "quests"]} />RooguyToastProvider
<RooguyToastProvider position="top-right" duration={5000} maxVisible={3} />RooguyGroup
<RooguyGroup
groupId="group-123"
sections={["header", "members", "leaderboard", "quests", "streaks"]}
layout="card"
/>RooguyGroupLeaderboard
<RooguyGroupLeaderboard groupType="team" limit={10} />RooguyTournamentBracket
<RooguyTournamentBracket tournamentId="tourney-456" layout="bracket" />RooguyNotificationCenter
<RooguyNotificationCenter layout="dropdown" limit={20} />RooguyBadgeShowcase
<RooguyBadgeShowcase
sortBy="earned_at"
filterByCategory="achievement"
layout="grid"
/>RooguyStreakWidget
<RooguyStreakWidget layout="card" />RooguyAchievementTimeline
<RooguyAchievementTimeline limit={20} filter={["badge", "level_up"]} />RooguyAhaScore
<RooguyAhaScore layout="gauge" />RooguyProfileShare
<RooguyProfileShare shareType="full" expiresInDays={7} />RooguyQuestionnaire
<RooguyQuestionnaire
questionnaireId="q-789"
mode="paginated"
allowRetake
onComplete={(result) => console.log(result.assignedPersona)}
/>Widget Variants
V1 widgets support a variant prop for alternative visual styles:
<RooguyLeaderboard timeframe="weekly" variant="podium" />
<RooguyQuestList status="in_progress" variant="checklist" />
<RooguyStorefront limit={12} variant="compact" />
<RooguyUserWidget layout="compact" variant="avatar-only" />
<RooguyToastProvider position="top-right" variant="minimal" />Headless Hooks
Use hooks directly when you want full control over rendering:
import { useLeaderboard, useQuests, useUserProfile } from "@rooguy/react";
function CustomLeaderboard() {
const { rankings, isLoading, currentUserRank } = useLeaderboard({
timeframe: "weekly",
});
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{rankings.map((entry) => (
<li key={entry.userId}>
{entry.displayName}: {entry.points} pts
</li>
))}
</ul>
);
}Available Hooks
| Hook | Returns |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| useLeaderboard(opts) | rankings, pagination, isLoading, error, refetch, currentUserRank |
| useQuests(opts) | quests, isLoading, error, refetch, claimReward |
| useUserProfile() | user, isLoading, error, refetch |
| useStorefront(opts) | items, pagination, isLoading, error, purchase, userBalance |
| useRooguyEvents(opts) | events, lastEvent, connectionStatus, clearEvents |
| useRooguy() | trackEvent |
| useExperiments() | activeExperiments, cohorts |
| useFullProfile(opts) | profile, badges, streaks, quests, inventory, activity, isLoading, error |
| useGroup(opts) | group, members, leaderboard, quests, streaks, buffs, inventory, isLoading, error, refetch, sections |
| useGroupLeaderboard(opts) | groups, pagination, isLoading, error, refetch, currentUserGroup |
| useTournament(opts) | tournament, participants, rounds, isLoading, error, refetch |
| useNotifications(opts) | notifications, unreadCount, isLoading, error, markAsRead, markAllAsRead, refetch, pagination |
| useBadges(opts) | badges, isLoading, error, refetch, totalCount |
| useStreaks(opts) | streaks, isLoading, error, refetch |
| useAchievements(opts) | achievements, pagination, isLoading, error, refetch |
| useAhaScore() | currentScore, declarativeScore, inferredScore, status, isLoading, error, refetch |
| useProfileShare() | generateShareLink, shareUrl, isGenerating, error, previewData |
| useQuestionnaire(opts) | questionnaire, questions, answers, setAnswer, submit, isSubmitting, isCompleted, assignedPersona, isLoading, error |
| useAnalytics() | trackEvent, trackImpression, trackInteraction, sessionId |
All hooks throw a descriptive error if used outside of <RooguyProvider>.
Theming
Override any CSS variable via the theme prop or directly in CSS:
<RooguyProvider
publishableKey="pk_live_abc123"
theme={{
primaryColor: '#6366f1',
borderRadius: '12px',
fontFamily: 'Inter, sans-serif',
}}
>All CSS classes use the rooguy- prefix. Use the classes prop on any widget to inject your own class names onto specific elements.
Internationalization
<RooguyProvider
publishableKey="pk_live_abc123"
i18n={{ rank: 'Rang', points: 'Punkte', claim: 'Einlösen' }}
>Widget-level i18n overrides take highest precedence (widget > provider > defaults).
Accessibility
- Semantic HTML (
<ol>,<progress>,<section>,<dialog>) - ARIA attributes on all interactive elements
aria-live="polite"for toast notifications- Focus trap in modals
- Keyboard navigable
- RTL support via
dirprop
