@factoredui/react
v0.5.1
Published
React bindings for FactoredUI — provider, hooks, path context, SDUI renderer
Maintainers
Readme
@factoredui/react
React bindings for FactoredUI — provider, hooks, path context, and SDUI renderer.
Part of the FactoredUI monorepo.
Install
npm install @factoredui/core @factoredui/react @supabase/supabase-jsSetup
Wrap your app in <Provider>. This initializes capture automatically.
import { createClient } from '@supabase/supabase-js'
import { Provider } from '@factoredui/react'
const supabase = createClient(url, anonKey, {
db: { schema: 'factoredui' }
})
function App() {
return (
<Provider supabase={supabase}>
<YourApp />
</Provider>
)
}Provider props:
supabase— Supabase client (required)adapter— customCaptureAdapter(defaults to web adapter)platform—"web" | "ios" | "android"(defaults to"web")flushIntervalMs— event batch interval (default 5000)flushBatchSize— max events per batch (default 50)sessionTimeoutMs— session inactivity timeout (default 30 min)
Path Context
Structure your component tree with path providers. Events are automatically tagged with hierarchical paths.
import { Flow, Page, Component, Element } from '@factoredui/react'
<Flow name="onboarding">
<Page name="review">
<Component name="photo-grid">
<Element name="upload-button">
<button>Upload</button>
</Element>
</Component>
</Page>
</Flow>
// Path: onboarding/review/photo-grid/upload-buttonRead the current path anywhere:
import { useComponentPath } from '@factoredui/react'
const path = useComponentPath()
// → "onboarding/review/photo-grid"Hooks
All hooks use the Supabase client from <Provider> context.
useFlag
import { useFlag } from '@factoredui/react'
function CheckoutPage() {
const { variant, loading, error } = useFlag('checkout-redesign')
if (loading) return <Spinner />
if (error) return <Fallback />
return variant === 'treatment' ? <NewCheckout /> : <OldCheckout />
}useFactors / useComponentFactors
const { factors, loading } = useFactors() // current user's factors
const { factors, loading } = useComponentFactors('checkout/cta') // aggregated for a componentuseGovernanceLog
const { entries, loading } = useGovernanceLog(experimentId)
// Realtime — updates as new governance verdicts arriveuseExperimentDashboard
const { experiments, loading } = useExperimentDashboard({ status: 'running' })useExperimentResults
const { results, loading } = useExperimentResults(experimentId, ['completion_rate', 'error_rate'])usePlatform
const platform = usePlatform() // "web" | "ios" | "android"SDUI Renderer
Render server-driven UI specs:
import { renderSpec } from '@factoredui/react'
import { loadSpec, createSpecStorage, devSignatureVerifier } from '@factoredui/core'
const spec = await loadSpec(supabase, 'home-hero', storage, devSignatureVerifier)
function HeroSection() {
return <>{renderSpec(spec.tree, componentRegistry, actionRegistry, dataSources)}</>
}useSourceData
Resolve async data sources for spec bindings:
import { useSourceData } from '@factoredui/react'
const { data, loading, error } = useSourceData(spec.dataSources, supabase)Peer Dependencies
@factoredui/core ^0.2.0@supabase/supabase-js ^2.0.0react ^18.0.0 || ^19.0.0
License
MIT
