Skip to Content
DocsDevelopersClient integration

Client integration

This recipe assumes you’re building with React (Next.js, Remix, Vite, etc.). The same concepts apply elsewhere.

Install the building blocks

npm install @fractalshq/sync @fractalshq/auth
  • @fractalshq/sync – React provider + hooks for distributions, claims, cohorts.
  • @fractalshq/auth – Auth core (server + SIWS utilities) and React helpers (via @fractalshq/auth/react).

Environment variables to set

Wire both the public (client) and private (server) endpoints so your app knows where to talk to Auth and Sync:

AUTH_BASE_URL=https://auth.fractals.fun NEXT_PUBLIC_AUTH_BASE_URL=/api/v1/fractals-auth AUTH_INTERNAL_API_KEY=sk_live_xxx # server-only SYNC_BASE_URL=https://sync.fractals.fun NEXT_PUBLIC_SYNC_BASE_URL=/api/v1/sync # or your proxy path SYNC_API_KEY=sk_sync_xxx # server-only NEXT_PUBLIC_SYNC_API_KEY=pk_sync_xxx # optional if you expose read-only calls
  • NEXT_PUBLIC_* values are safe for the browser (they usually point at your Next.js proxy routes).
  • Keep the *_API_KEY secrets on the server—only the proxy handler should read them.

Wrap your app

import { SyncProvider } from "@fractalshq/sync/react"; import { AuthProvider } from "@fractalshq/auth/react"; export function App() { return ( <AuthProvider baseURL={process.env.NEXT_PUBLIC_AUTH_BASE_URL}> <SyncProvider baseUrl={process.env.NEXT_PUBLIC_SYNC_BASE_URL} apiKey={process.env.NEXT_PUBLIC_SYNC_API_KEY} > <Dashboard /> </SyncProvider> </AuthProvider> ); }

AuthProvider keeps a SIWS session alive (see Phantom’s SIWS primer ), while SyncProvider exposes hooks that already include your API key + environment. Under the hood, @fractalshq/auth/react also mounts tx-auth helpers so your app can request wallet signatures for server-initiated transactions (e.g., distribution funding, claims, or Ledger/hardware-wallet flows) without building nonce/relay plumbing manually.

Launching a distribution from the UI

import { useSyncApi } from "@fractalshq/sync/react"; import { useTxAuth } from "@fractalshq/auth/react"; export function FundCohortButton() { const { distributions } = useSyncApi(); const { signAndSend } = useTxAuth(); async function handleClick() { const { transaction, summary } = await distributions.create({ cohortId: "growth-users", splitTemplateId: "weekly-50-50", mint: "GEOD...", schedule: { startVestingTs: Math.floor(Date.now() / 1000), endVestingTs: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60, }, }); await signAndSend(transaction); console.info(`Funded distribution ${summary.distributionId}`); } return <button onClick={handleClick}>Fund cohort</button>; }
  • cohortId and splitTemplateId come from the dashboard so you never reconstruct data locally.
  • signAndSend reuses the wallet connection maintained by AuthProvider.

Adding a claim button

import { useSyncClaims } from "@fractalshq/sync/react"; export function ClaimRewards({ distributionId }: { distributionId: string }) { const { fetchClaimTx } = useSyncClaims(); const { signAndSend } = useTxAuth(); async function claim() { const { transaction, expectedAmount } = await fetchClaimTx({ distributionId }); await signAndSend(transaction); alert(`Claimed ${expectedAmount} tokens`); } return <button onClick={claim}>Claim rewards</button>; }

Use the (coming soon) widget if you prefer a zero-code surface:

<SyncClaimWidget distributionId="dist_23" wallet={wallet} onClaimed={refreshStats} />

Backend glue

For Next.js App Router:

// app/api/sync/[...route]/route.ts import { createSyncHandler } from "@fractalshq/sync/server"; import { withApiAuth } from "@fractalshq/auth"; const handler = createSyncHandler({ apiKey: process.env.SYNC_API_KEY! }); export const GET = withApiAuth(handler); export const POST = withApiAuth(handler);

createSyncHandler proxies requests to Sync, injects your project ID, and respects cohort permissions. Pair it with Fractals Auth so every call already has an authenticated wallet session.

Last updated on