The SDK
Build your fan app on our platform.
The SDK revolution.fan itself runs on. A creator's page, whether a band, a club, a streamer or a venue, with its live wall, follows, comments, hearts and polls, Scout, and the fan's account and everything they follow: one typed client, and React hooks for the web and React Native. Your brand on top, the platform underneath.
Partner preview
Partners get the packages with their access; they are not on npm yet. Version 1 covers the 25 operations below. Sign-in by phone, push notifications, messages and Scout's voice come next. To build on it, tell us what you're building.
How it fits together
Quick start
The client
import { createClient } from "@revolution/client";
const api = createClient({
baseUrl: "https://api.revolution.fan",
// The signed-in fan's ID token, or null when nobody is signed in.
getToken: () => auth.currentUser?.getIdToken() ?? null,
appKey: "your-app-key",
});
const hub = await api.getHub({ path: { kind: "artist", slug: "an-artist" } });
hub.universe.name; // the creator
hub.now.state; // "quiet" | "live" | "show_tonight" | "release"
hub.shelves.items.length; // what their sources pulled onto the wall
await api.postComment({
path: { kind: "item", sid: hub.shelves.items[0].id },
body: { body: "See you there" },
});The hooks
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
RevolutionProvider, useHub, useFollowState, useToggleFollow,
} from "@revolution/react";
const queryClient = new QueryClient();
export function App() {
return (
<QueryClientProvider client={queryClient}>
<RevolutionProvider client={api}>
<CreatorPage kind="artist" slug="an-artist" />
</RevolutionProvider>
</QueryClientProvider>
);
}
function CreatorPage({ kind, slug }: { kind: string; slug: string }) {
const { data: hub } = useHub(kind, slug);
const { data: follow } = useFollowState(kind, slug);
const toggle = useToggleFollow(kind, slug);
if (!hub) return null;
return (
<button onClick={() => toggle.mutate(!follow?.following)}>
{follow?.following ? "Following" : "Follow"} {hub.universe.name}
</button>
);
}The cache is your app's own: its QueryClient, its defaults, its devtools. The provider only hands the hooks a client. Each hook has an options factory beside it (hubQuery, toggleFollowMutation and the rest), so a server can prefetch a page before it renders.
What version 1 covers
A creator's page
getHub, getPeople, getFollow, follow, unfollow, getCollection
Anyone reads the page; following and the fan's own collection need a signed-in fan
The owner's desk
getDeskItems, setItemState
The page's owner, to hide what their sources pulled in or put it back
A fan's follows
getLineup, getFollowsBinge
Signed-in fans
Talk on anything
getComments, postComment, deleteComment, getCommentCounts, toggleHeart, getHeartCounts, getPoll, answerPoll
Anyone reads; posting, hearts and answers need a signed-in fan
Scout
askScout, getScoutThread, markScoutThreadRead, getScoutInbox, getScoutObsessions
Anyone can ask; the thread, inbox and watches belong to a signed-in fan
The account
getMe, getProfile
The fan's own record when signed in; anyone's public profile
Comments, hearts and polls work on anything with an id: a post on a creator's wall, a show, a stream. The kind is part of the address.
Hooks
Every operation has its hook. What the ones that write do to the cache:
Signing in
The SDK carries the fan's own session: getToken returns the signed-in fan's ID token from the platform's sign-in, which partners set up with their access, or null. Reads that anyone can make answer signed out (a follow state is simply false); everything that belongs to a fan answers 401 until one signs in.
Errors and timeouts
import { ApiError } from "@revolution/client";
try {
await api.getHub({ path: { kind: "artist", slug: "nobody" } });
} catch (err) {
if (err instanceof ApiError) {
err.operation; // "getHub"
err.status; // 404
err.code; // the server's error code, when it sends one
}
}Any answer other than an operation's own success status throws an ApiError. A request is abandoned after 15 seconds, a turn with Scout after 45.
What we promise
Every operation in version 1 is called against a real database on every change to the platform, signed in and signed out, and its answer is checked against the schema the types are generated from. A field the SDK lists is never removed or retyped without a new version; new fields can appear at any time, and the types show only what is promised. The client has no dependencies; the hooks need React 18 or 19 and TanStack Query 5.