React Hooks SDK
Build React applications powered by FlowMason pipelines with type-safe hooks and real-time streaming.
FlowMason provides React hooks for seamless integration with React applications, including real-time streaming, loading states, and error handling.
Installation
npm install @flowmason/react
Setup Provider
Wrap your app with the FlowMason provider:
import { FlowMasonProvider } from '@flowmason/react';
function App() {
return (
<FlowMasonProvider
studioUrl="http://localhost:8999/api/v1"
apiKey={process.env.REACT_APP_FLOWMASON_API_KEY}
>
<YourApp />
</FlowMasonProvider>
);
}
usePipeline Hook
The primary hook for running pipelines:
import { usePipeline } from '@flowmason/react';
function ContentGenerator() {
const { run, result, loading, error, progress } = usePipeline('content-generator');
const handleGenerate = async () => {
await run({ topic: 'AI trends in 2024' });
};
return (
<div>
<button onClick={handleGenerate} disabled={loading}>
{loading ? 'Generating...' : 'Generate Content'}
</button>
{progress && (
<div className="progress-bar">
<div style={{ width: `${progress.percentComplete}%` }} />
<span>Stage: {progress.currentStage}</span>
</div>
)}
{error && <div className="error">{error.message}</div>}
{result && (
<div className="result">
<h3>Generated Content</h3>
<p>{result.output.content}</p>
<small>Tokens: {result.usage?.totalTokens}</small>
</div>
)}
</div>
);
}
useStreamingPipeline Hook
For real-time streaming updates:
import { useStreamingPipeline } from '@flowmason/react';
function StreamingChat() {
const {
run,
stages,
currentStage,
isStreaming,
partialOutput,
finalResult,
} = useStreamingPipeline('chat-pipeline');
return (
<div>
<button onClick={() => run({ message: 'Hello!' })}>
Send Message
</button>
{/* Show stage progress */}
<div className="stages">
{stages.map(stage => (
<div
key={stage.id}
className={`stage ${stage.status}`}
>
{stage.name}: {stage.status}
{stage.durationMs && ` (${stage.durationMs}ms)`}
</div>
))}
</div>
{/* Show streaming output */}
{isStreaming && (
<div className="streaming">
<span className="typing-indicator" />
{partialOutput}
</div>
)}
{/* Show final result */}
{finalResult && (
<div className="response">
{finalResult.output.response}
</div>
)}
</div>
);
}
usePipelineList Hook
Fetch and display available pipelines:
import { usePipelineList } from '@flowmason/react';
function PipelineSelector({ onSelect }) {
const { pipelines, loading, error, refetch } = usePipelineList({
status: 'published',
category: 'content',
});
if (loading) return <div>Loading pipelines...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<select onChange={(e) => onSelect(e.target.value)}>
<option value="">Select a pipeline</option>
{pipelines.map(p => (
<option key={p.id} value={p.id}>
{p.name} v{p.version}
</option>
))}
</select>
);
}
useRunHistory Hook
Access pipeline execution history:
import { useRunHistory } from '@flowmason/react';
function RunHistory({ pipelineId }) {
const { runs, loading, hasMore, loadMore } = useRunHistory({
pipelineId,
limit: 10,
});
return (
<div>
<h3>Recent Runs</h3>
<ul>
{runs.map(run => (
<li key={run.runId}>
{run.status} - {new Date(run.startedAt).toLocaleString()}
<span className={run.success ? 'success' : 'failed'}>
{run.success ? '✓' : '✗'}
</span>
</li>
))}
</ul>
{hasMore && (
<button onClick={loadMore} disabled={loading}>
Load More
</button>
)}
</div>
);
}
useFlowMason Hook
Access the underlying FlowMason client:
import { useFlowMason } from '@flowmason/react';
function CustomComponent() {
const fm = useFlowMason();
const customAction = async () => {
// Direct access to all SDK methods
const pipeline = await fm.getPipeline('my-pipeline');
const components = await fm.listComponents({ category: 'ai' });
// ...
};
return <button onClick={customAction}>Custom Action</button>;
}
TypeScript Support
Full type inference for pipeline inputs and outputs:
import { usePipeline } from '@flowmason/react';
// Define your pipeline types
interface ContentInput {
topic: string;
style?: 'formal' | 'casual';
maxLength?: number;
}
interface ContentOutput {
title: string;
content: string;
tags: string[];
}
function TypedComponent() {
const { run, result } = usePipeline<ContentInput, ContentOutput>(
'content-generator'
);
const handleRun = () => {
// TypeScript validates input
run({
topic: 'AI',
style: 'formal',
maxLength: 500,
});
};
// result.output is typed as ContentOutput
return result ? <div>{result.output.title}</div> : null;
}
Error Boundaries
Handle pipeline errors gracefully:
import { PipelineErrorBoundary } from '@flowmason/react';
function App() {
return (
<PipelineErrorBoundary
fallback={({ error, reset }) => (
<div className="error-container">
<h2>Pipeline Error</h2>
<p>{error.message}</p>
<button onClick={reset}>Try Again</button>
</div>
)}
>
<ContentGenerator />
</PipelineErrorBoundary>
);
}
Configuration Options
<FlowMasonProvider
studioUrl="https://api.flowmason.com/v1"
apiKey="sk-..."
orgId="org-123"
defaultTimeout={60000}
onError={(error) => {
// Global error handler
console.error('Pipeline error:', error);
Sentry.captureException(error);
}}
onSuccess={(result) => {
// Global success handler
analytics.track('pipeline_completed', {
pipelineId: result.pipelineId,
duration: result.durationMs,
});
}}
>
<App />
</FlowMasonProvider>
Server-Side Rendering (Next.js)
For Next.js applications:
// app/providers.tsx
'use client';
import { FlowMasonProvider } from '@flowmason/react';
export function Providers({ children }) {
return (
<FlowMasonProvider
studioUrl={process.env.NEXT_PUBLIC_FLOWMASON_URL}
apiKey={process.env.NEXT_PUBLIC_FLOWMASON_API_KEY}
>
{children}
</FlowMasonProvider>
);
}
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
Best Practices
- Use streaming for long-running pipelines - Provides better UX with progress updates
- Implement error boundaries - Gracefully handle pipeline failures
- Cache pipeline metadata - Use
usePipelineListto avoid repeated fetches - Type your inputs/outputs - Leverage TypeScript for safer code
- Handle loading states - Always show feedback during execution