React Integration
React hooks and provider for fluidsoul — useFluidsoulContext, useFluidsoulEvents.
React Integration
The fluidsoul-js/react package provides React hooks and a provider for seamless integration.
Setup
Wrap your app with FluidsoulProvider:
import { FluidsoulProvider } from "fluidsoul-js/react"
const config = {
apiUrl: process.env.NEXT_PUBLIC_FLUIDSOUL_API_URL!,
token: process.env.NEXT_PUBLIC_FLUIDSOUL_API_TOKEN!,
workspaceId: process.env.NEXT_PUBLIC_FLUIDSOUL_WORKSPACE_ID!,
}
export default function App({ children }: { children: React.ReactNode }) {
return (
<FluidsoulProvider config={config}>
{children}
</FluidsoulProvider>
)
}useFluidsoulContext
Fetch and manage a user's context.
import { useFluidsoulContext } from "fluidsoul-js/react"
function Dashboard({ userId }: { userId: string }) {
const { context, loading, error, refresh } = useFluidsoulContext(userId)
if (loading) return <Skeleton />
if (error) return <ErrorMessage error={error} />
if (!context) return <DefaultDashboard />
return (
<div>
<h1>Welcome back</h1>
<p>You are a {context.user_category}</p>
{/* Order features by priority */}
{context.feature_priorities.map((feature) => (
<FeatureCard key={feature} name={feature} />
))}
{/* Apply recommended defaults */}
<Settings defaults={context.recommended_defaults} />
{/* Show onboarding for new users */}
{context.user_maturity === "new" && <OnboardingTips />}
<button onClick={refresh}>Refresh context</button>
</div>
)
}useFluidsoulEvents
Send events from your components.
import { useFluidsoulEvents } from "fluidsoul-js/react"
function ReportButton({ userId }: { userId: string }) {
const { sendEvent } = useFluidsoulEvents()
const handleClick = () => {
sendEvent({
userId,
eventType: "report_viewed",
metadata: { category: "analytics" },
})
}
return <button onClick={handleClick}>View Report</button>
}Full adaptive dashboard example
"use client"
import { useFluidsoulContext, useFluidsoulEvents } from "fluidsoul-js/react"
export function AdaptiveDashboard({ userId }: { userId: string }) {
const { context, loading } = useFluidsoulContext(userId)
const { sendEvent } = useFluidsoulEvents()
if (loading) return <div>Loading...</div>
const defaults = context?.recommended_defaults ?? {}
const features = context?.feature_priorities ?? ["dashboard"]
const maturity = context?.user_maturity ?? "new"
return (
<div>
{/* Feature ordering based on user context */}
<nav>
{features.map((feature) => (
<a
key={feature}
href={`#${feature}`}
onClick={() =>
sendEvent({ userId, eventType: "feature_accessed", metadata: { feature } })
}
>
{feature}
</a>
))}
</nav>
{/* Onboarding hints for new users */}
{maturity === "new" && (
<div>New here? Start with a quick tour.</div>
)}
{/* Apply defaults */}
{Object.entries(defaults).map(([key, value]) => (
<div key={key}>{key}: {String(value)}</div>
))}
</div>
)
}Next.js App Router pattern
Use server components to fetch context and pass it to client components:
// app/dashboard/page.tsx (Server Component)
import { getContext } from "fluidsoul-js"
import { DashboardClient } from "./dashboard-client"
export default async function DashboardPage() {
const config = {
apiUrl: process.env.FLUIDSOUL_API_URL!,
token: process.env.FLUIDSOUL_API_TOKEN!,
workspaceId: process.env.FLUIDSOUL_WORKSPACE_ID!,
}
const userId = "user_123" // from your auth
const context = await getContext(config, userId)
return <DashboardClient context={context} userId={userId} />
}// app/dashboard/dashboard-client.tsx (Client Component)
"use client"
import type { UserContext } from "fluidsoul-js"
export function DashboardClient({
context,
userId,
}: {
context: UserContext | null
userId: string
}) {
const features = context?.feature_priorities ?? ["dashboard"]
return (
<div>
{features.map((f) => (
<section key={f}>{f}</section>
))}
</div>
)
}