@playaos/react
v0.1.0
Published
React hooks for PlayaOS — members, dues, shifts, applications, and org config
Maintainers
Readme
@playaos/react
React hooks for PlayaOS — wrap your app in a provider and query members, dues, shifts, applications, and org config with full TypeScript types.
Install
npm install @playaos/react @playaos/api-client @tanstack/react-query
<ApplicationForm>also needszod— it's an optional peer of@playaos/api-client/schemas:npm install zod.
Quick Start
import { createClient } from "@playaos/api-client";
import { QueryClient } from "@tanstack/react-query";
import { PlayaOSProvider, useMembers } from "@playaos/react";
const client = createClient({
baseUrl: "https://your-camp.playaos.app",
apiKey: "pk_live_...",
});
const queryClient = new QueryClient();
function App() {
return (
<PlayaOSProvider client={client} queryClient={queryClient}>
<MemberList />
</PlayaOSProvider>
);
}
function MemberList() {
const { data: members, isPending, isError } = useMembers();
if (isPending) return <p>Loading…</p>;
if (isError) return <p>Failed to load members.</p>;
return (
<ul>
{members.map((m) => (
<li key={m.id}>{m.name ?? m.email}</li>
))}
</ul>
);
}Hooks
| Hook | Returns | staleTime |
|------|---------|-----------|
| useMembers(params?) | Member[] | 30s |
| useMember(id) | Member | 30s |
| useApplications(params?) | Application[] | 30s |
| useDues(params?) | DuesStatus[] | 10s |
| useShifts(params?) | Shift[] | 30s |
| useOrg() | OrgConfig | 5min |
All hooks return UseQueryResult<T, ApiClientError> — branch on error.status or error.code for typed error handling.
Query Keys
All keys follow the stable shape ["@playaos", resource, method, params]. Import the keys factory to invalidate programmatically:
import { keys } from "@playaos/react";
// Invalidate all PlayaOS queries
queryClient.invalidateQueries({ queryKey: ["@playaos"] });
// Invalidate only members
queryClient.invalidateQueries({ queryKey: keys.members.all() });Provider
<PlayaOSProvider> accepts:
client(required) — aPlayaOSClientfrom@playaos/api-clientqueryClient(optional) — bring your ownQueryClient; defaults to a shared singleton
If queryClient is omitted, a singleton is created on first render and reused. Pass your own for SSR or test isolation.
<ApplicationForm> — drop-in apply widget
A self-contained, multi-step camp application form. It renders the full apply
wizard, validates with the same Zod schema as the portal (@playaos/api-client/schemas),
submits through useApplicationSubmit, and shows success/error states — no Tailwind
config or stylesheet import required in your app.
import { createClient } from "@playaos/api-client";
import { ApplicationForm, PlayaOSProvider } from "@playaos/react";
const client = createClient({ baseUrl: "https://your-camp.playaos.app", apiKey: "pk_live_..." });
export function Apply() {
return (
<PlayaOSProvider client={client}>
<ApplicationForm
orgId="your-camp"
onSubmitted={(res) => console.log("Application", res.applicationId)}
theme={{ primary: "#b5402b", radius: "12px" }}
/>
</PlayaOSProvider>
);
}Props
| Prop | Type | Notes |
|------|------|-------|
| orgId | string (required) | The org the application belongs to (rendered as data-org-id; routing is via the client). |
| onSubmitted | (result: ApplicationCreateResponse) => void | Called after a successful submission. |
| theme | ApplicationFormTheme | Token overrides mapped to --paf-* CSS custom properties. |
| referralCode | string | Prefills the referral code. |
| acknowledgmentContent | ReactNode | Override the step-0 expectations copy. |
| accessToken | string | PlayaOS IdP JWT to submit on behalf of a known profile. |
| className | string | Appended to the scoped root element. |
Theming
Styles are scoped under .playaos-af and injected at runtime. Override any token
via the theme prop or your own CSS:
.playaos-af { --paf-primary: #2563eb; --paf-radius: 14px; }Tokens: primary, primaryContrast, fg, muted, bg, surface, border,
error, radius, fontFamily.
Bundle size
Budget: < 150 kB gzipped. react, @tanstack/react-query, @playaos/api-client
(and its zod dependency) are peer dependencies and externalized from the build,
so they are not double-shipped. The package's own code — hooks + <ApplicationForm>
(markup, validation glue, and the injected scoped stylesheet) — is ~7 kB gzipped.
