fluidsoul

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>
  )
}

On this page