Rising Tide Developers
UI PackageAuth

Auth Providers

The auth provider components under RisingTideProviders - RisingTideAuthProvider, AppModeProvider, ModeGate and ConditionalProviders.

RisingTideProviders mounts everything on this page for you. The components are documented for apps that compose the stack by hand and for reading the shipped order.

RisingTideAuthProvider

The lower-level auth composition. It takes the app's SDK client and the inner ProtocolUserConfig, and must be inside PrivyProvider.

import { PrivyProvider } from "@privy-io/react-auth";
import { RisingTideAuthProvider } from "@rising-tide/ui/auth";

<PrivyProvider appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}>
  <RisingTideAuthProvider
    sdk={rtClient}
    userConfig={{
      storagePrefix: "myapp",
      linkInviteCodes: true,
      onSignupComplete: () => {},
    }}
  >
    {children}
  </RisingTideAuthProvider>
</PrivyProvider>
PropRequiredPurpose
sdkyesThe app's RisingTideSDK instance
userConfigyesProtocolUserConfig: storagePrefix, linkInviteCodes and onSignupComplete are required; onSignOut and appId are optional
storagePrefixnoNamespace for the auth-method and app-mode storage keys. Default rt
appNamenoShown by ModeGate on the maintenance and coming-soon screens
modeLoadingComponentnoRetained for API compatibility; maintenance needs no loading state

It composes, outermost first: AuthMethodProvider -> InviteCodeProvider -> AppModeProvider -> ModeGate -> ConditionalProviders -> ProtocolUserProvider. The inner ProtocolUserProvider is what:

  • reads the Privy access token (or the wallet's signed challenge) and attaches it to the SDK client
  • creates the user record on first sign-in (POST /api/users), through the welcome dialog when the app mounts one
  • resolves the viewer's stxAddress and flattens their roles to an entitlements list
  • exposes all of it through useProtocolUser()

AppModeProvider

Holds the app's operational mode. The mode has two sources and one precedence rule: the operator-set App.mode served on GET /api/apps/{id}/config wins when it is set, in both directions - an app can be flipped into or out of maintenance without a redeploy; when the server value is null, the compiled NEXT_PUBLIC_APP_MODE holds; when the config cannot be read, the last-known server value (cached in local storage) holds, else the env.

<AppModeProvider storagePrefix="myapp" sdk={rtClient} appId={42}>
  {children}
</AppModeProvider>

All three props are optional. Without sdk and an app id (the prop or NEXT_PUBLIC_APP_ID) the provider never asks the server and the env value is the whole answer - which is what RisingTideProviders does for an app with no modeGate, so an ungated app holds no connection open for a question nothing acts on.

Modes (NEXT_PUBLIC_APP_MODE, default live):

ModeBehavior
liveNormal operation
maintenanceShows a maintenance screen
coming-soonShows a pre-launch splash

The mode is operational only. Whether signup requires an invite is a separate, server-driven concern - the App.requireInviteForSignup flag, read via apps.getConfig and surfaced as useProtocolUser().requiresInvite. Whether a viewer may be in the app at all is the entry curtain's question, on Providers.

ModeGate

Gates the app on the operational mode - it renders the maintenance or coming-soon screen when one is set, otherwise the app. Pass the app name for those screens.

<ModeGate appName="My App">
  {children}
</ModeGate>

ConditionalProviders

Composes PrivyTokenProvider (enabled only when the session's auth method is privy) and StacksProvider into a single wrapper. PrivyStateSync, which mirrors Privy's session state into the protocol user context, is mounted by ProtocolUserProvider itself. Used internally by the auth layer - apps use RisingTideProviders or RisingTideAuthProvider instead.