Saltar al contenido principal

<RiftProvider>

Root of the SDK runtime. Provides the cross-cutting context every SDK hook and component reads — API base URLs, locale, theming tokens, behavioral callbacks, transport overrides, optional auth. Mount once near the top of the embedded surface; nest <RiftEvent> inside for per-event scope.

Import

import { RiftProvider } from "@feelrift/react";

Basic usage

import { RiftProvider } from "@feelrift/react";

export function App({ children }) {
return <RiftProvider locale="es-MX">{children}</RiftProvider>;
}

Props

NameTypeRequiredDefaultDescription
apiBaseUrlstringNohttps://api.feelrift.comAPI host for every SDK request. Override for staging or self-hosted Rift deployments.
altchaBaseUrlstringNohttps://altcha.feelrift.comAltcha challenge endpoint. Independent of apiBaseUrl because the challenge endpoint runs on a separate origin.
localestringNoundefinedBCP 47 preferred locale (e.g. "es-MX"). Negotiated against the event's locales.supported by useLocale().
stringsRecord<string, string>NoundefinedPer-key string overrides; looked up before the bundled en / es tables. See Internationalization.
appearanceAppearanceNoundefinedTyped mirror of the --rift-* CSS custom properties. Written onto the provider's root element on mount and on every change.
theme"light" | "dark"No"light"Theme variant. "dark" writes data-theme="dark" on the wrapper, activating the SDK's neutral dark token variant. See theme below.
onRiftCallbacksNoundefinedBehavioral callbacks fired on SDK state transitions. See on below for the full list.
authAuthConfigNoundefinedOpt-in attendee authentication. When set, the SDK mounts the auth context and exposes useSession().
tokenStorage"memory" | "session" | "local"No"memory"Where to persist the OIDC user. "memory" (default) loses tokens on full reload but the silent renewal restores them; "session" survives same-tab reloads; "local" survives across tabs/sessions with the largest XSS exposure.
childrenReactNodeYesSubtree that consumes the SDK context.

apiBaseUrl

Set explicitly for staging or multi-environment deployments where the same SDK build hits different hosts at runtime. Defaults to https://api.feelrift.com.

<RiftProvider apiBaseUrl="https://api.staging.feelrift.com">
{children}
</RiftProvider>

altchaBaseUrl

The Altcha challenge endpoint runs on a separate origin from the API; this prop is its own slot rather than a path on apiBaseUrl.

locale

The SDK ships en and es locale tables. useLocale() negotiates the active locale by:

  1. Reading this prop.
  2. Falling back to the event's config.locales.default.
  3. Falling back to en.

For locales beyond en / es, pass per-key overrides via strings or extend the bundled tables.

strings

Overrides looked up before the bundled locale tables. Useful for one-off label tweaks across the embed:

<RiftProvider
strings={{
"checkout.confirm": "Pagar ahora",
"reservation.reserve": "Apartar boletos",
}}
>
{children}
</RiftProvider>

For larger sets, prefer extending the bundled STRINGS_BY_LOCALE table — both surfaces are merged the same way at lookup time.

appearance

Typed mirror of the SDK's CSS tokens. Each key maps 1:1 to a --rift-* custom property by camelCase → kebab-case (colorPrimary--rift-color-primary). Values are written onto the root element via applyAppearance() at mount and on every prop change.

<RiftProvider
appearance={{
variables: {
colorPrimary: "#0066ff",
radiusMd: "8px",
fontFamily: "Inter, system-ui, sans-serif",
},
}}
>
{children}
</RiftProvider>

CSS tokens remain the canonical source — consumers can override with plain CSS targeting [data-rift-root] and skip this prop entirely.

theme

Opts in to the SDK's neutral dark token variant by writing data-theme="dark" onto the [data-rift-root] wrapper. The matching CSS overrides every --rift-color-* token; the rest (radius, spacing, typography) stays the same.

<RiftProvider theme="dark">{children}</RiftProvider>

The dark palette is neutral, not branded — the SDK ships generic dark surface colors. Layer brand-specific colors on top via appearance or plain CSS:

<RiftProvider
theme="dark"
appearance={{ variables: { colorPrimary: "#E61919" } }}
>
{children}
</RiftProvider>

The theme prop is purely convenience — consumers driving theme state from a parent element (e.g. <html data-theme="dark">) can omit the prop entirely. The dark token variant matches both [data-rift-root][data-theme="dark"] AND [data-theme="dark"] [data-rift-root], so an ancestor's attribute activates it without prop plumbing.

Note The SDK's wrapper does NOT paint color, background-color, font-family, or font-size on itself — tokens set values on SDK component classes, and everything outside the SDK's own components inherits the consumer's host styling normally.

on

Behavioral callbacks fired on SDK state transitions. Each is optional; SDK components render reasonable defaults when a callback isn't supplied.

CallbackPayloadFires when
reservationCreated(reservation: ActualReservation) => voidA reservation succeeds.
reservationExpired() => voidThe countdown reaches 00:00.
reservationPriceChanged({ oldTotal, newTotal }) => voidThe server's reservation total differs from the estimate the UI displayed.
checkoutWindowClosed() => voidCheckout fails with code: "checkout_window_closed".
paymentSucceeded(orderId, orderStatusToken) => voidA paid confirmPayment resolves OK, or a free order completes immediately.
paymentFailed(error: RiftApiError | StripeError) => voidServer-side checkout or Stripe-side confirmPayment fails.
signedIn() => voidAnonymous session transitions to authenticated.
signedOut() => voidsignOut() clears the local session.
error(error: RiftApiError) => voidCatch-all — every RiftApiError the SDK surfaces.
<RiftProvider
on={{
paymentSucceeded: (orderId) => router.push(`/thanks?o=${orderId}`),
paymentFailed: (err) => Sentry.captureException(err),
error: (err) => Sentry.captureMessage(`Rift: ${err.code}`),
}}
>
{children}
</RiftProvider>

auth

Opt-in attendee authentication. When omitted, every flow that doesn't require an authenticated attendee (availability, reservation, anonymous checkout) keeps working unchanged. When set, the SDK mounts the auth context and exposes useSession() (with signIn / signOut actions), useAuthCallback(), and useAttendeeOrders().

tokenStorage

Picks where the OIDC user (access token + expiry) lives:

  • "memory" (default) — least durable, least XSS exposure. Tokens vanish on full reload; the auth context restores them via silent renewal when a silentRedirectUri is configured.
  • "session" — survives same-tab reloads; cleared when the tab closes.
  • "local" — survives across tabs and full browser sessions with the largest XSS exposure (any script on the origin can read it).
<RiftProvider auth={authConfig} tokenStorage="session">
{children}
</RiftProvider>

Render output

Renders a single <div data-rift-root=""> wrapper. The data-rift-root attribute is the CSS scope that isolates the SDK's custom properties from the host page — pages can target it directly:

[data-rift-root] {
--rift-color-primary: #ff6600;
}

The wrapper is display: block by default; override via the appearance prop or external CSS if a different layout is needed.

Behavior

  • Provider context. Provides the SDK runtime context to its subtree — every SDK hook and component reads through this provider.
  • Persistent-state hydration. Rehydrates persisted state (reservation token, order id) in a post-mount effect, so the first server render matches the first client render. See Server-side rendering.
  • Appearance application. Writes appearance.variables to the root element as --rift-* CSS custom properties on mount and on every appearance prop change.
  • Auth mounting. When auth is set, wraps children in <AuthProvider>. Otherwise renders children directly with no extra wrapper.
  • Multiple providers. Multiple <RiftProvider> instances on the same page are supported but each must scope its own subtree. Persisted state (reservation, config cache) is per-provider — two providers will not share a reservation token.

Examples

Themed embed with callbacks

import { RiftEvent, RiftProvider } from "@feelrift/react";

<RiftProvider
locale="es-MX"
appearance={{
variables: {
colorPrimary: "#0066ff",
colorPrimaryForeground: "#ffffff",
radiusMd: "8px",
},
}}
on={{
paymentSucceeded: (orderId) => router.push(`/thanks?o=${orderId}`),
paymentFailed: (err) => Sentry.captureException(err),
}}
>
<RiftEvent eventId="evt_summerfest_2026">{/* event-scoped UI */}</RiftEvent>
</RiftProvider>;

Staging override

<RiftProvider
apiBaseUrl="https://api.staging.feelrift.com"
altchaBaseUrl="https://altcha.staging.feelrift.com"
>
{children}
</RiftProvider>

With opt-in auth + sessionStorage persistence

<RiftProvider
auth={{
clientId: "rift_app_abc123",
authorizeUrl: "https://auth.feelrift.com/oauth/authorize",
tokenUrl: "https://auth.feelrift.com/oauth/token",
redirectUri: "https://your.site/auth/callback",
silentRedirectUri: "https://your.site/auth/silent-callback",
}}
tokenStorage={
typeof window !== "undefined" ? window.sessionStorage : undefined
}
>
{children}
</RiftProvider>