React UI Components
@outstand-so/ui is a React component library that provides pre-built UI components and hooks for integrating Outstand's social media API into your React applications. It simplifies the process of building social media management interfaces by providing ready-to-use components for account management, post creation, media uploads, and analytics.
Installation
Install the package from npm:
npm install @outstand-so/uiOr with yarn:
yarn add @outstand-so/uiOr with pnpm:
pnpm add @outstand-so/uiGetting Started
Provider Setup
Wrap your application (or the part that uses Outstand components) with the OutstandProvider:
import { OutstandProvider } from '@outstand-so/ui';
function App() {
return (
<OutstandProvider apiKey="your-api-key" baseUrl="https://api.outstand.so">
{/* Your app components */}
</OutstandProvider>
);
}Props:
apiKey(required): Your Outstand API keybaseUrl(optional): Base URL for API requests. Defaults tohttps://api.outstand.sotenantId(optional): Tenant ID for multi-tenant applicationsinitialAccounts(optional): Pre-populate accounts without fetching
Components
Account Management
ConnectAccountButton
A button component that initiates OAuth flow for connecting a social media account.
import { ConnectAccountButton } from '@outstand-so/ui';
<ConnectAccountButton
network="x"
redirectUri="https://yourapp.com/callback"
apiKey="your-api-key"
onSuccess={(authUrl) => {
window.location.href = authUrl;
}}
onError={(error) => {
console.error('Connection error:', error);
}}
/>Props:
network(required): Social network to connect ("threads" | "bluesky" | "x" | "linkedin" | "youtube" | "instagram" | "facebook" | "tiktok" | "pinterest")redirectUri(required): URL to redirect after OAuth flowapiKey(required): Your API keytenantId(optional): Tenant ID for multi-tenant appsbaseUrl(optional): API base URLonSuccess(optional): Callback when auth URL is obtainedonError(optional): Error handlerclassName(optional): Additional CSS classeschildren(optional): Custom button contentvariant(optional): Button style ("default" | "outline" | "ghost")size(optional): Button size ("sm" | "md" | "lg")
ConnectAccountButtonGroup
Display multiple connection buttons in a group layout.
import { ConnectAccountButtonGroup } from '@outstand-so/ui';
<ConnectAccountButtonGroup
networks={['x', 'linkedin', 'instagram', 'facebook']}
redirectUri="https://yourapp.com/callback"
apiKey="your-api-key"
layout="grid"
variant="outline"
/>Props:
networks(required): Array of social networks to showredirectUri(required): OAuth callback URLapiKey(required): Your API keylayout(optional): Layout style ("horizontal" | "vertical" | "grid")- Other props same as
ConnectAccountButton
AccountsList
Display a paginated list of connected social accounts with management options.
import { AccountsList } from '@outstand-so/ui';
<AccountsList
apiKey="your-api-key"
onAccountSelect={(account) => {
console.log('Selected:', account);
}}
onAccountDisconnect={(accountId) => {
console.log('Disconnected:', accountId);
}}
pageSize={20}
/>Props:
apiKey(required): Your API keybaseUrl(optional): API base URLtenantId(optional): Tenant IDonAccountSelect(optional): Callback when account is selectedonAccountDisconnect(optional): Callback when account is disconnectedclassName(optional): Additional CSS classespageSize(optional): Number of accounts per page (default: 20)
AccountCard
Display a single social account card.
import { AccountCard } from '@outstand-so/ui';
<AccountCard
account={account}
onSelect={() => handleSelect(account)}
onDisconnect={() => handleDisconnect(account.id)}
/>Props:
account(required): SocialAccount objectonSelect(optional): Selection handleronDisconnect(optional): Disconnect handlerclassName(optional): Additional CSS classes
Post Creation
CreatePostForm
A complete form component for creating and scheduling posts.
import { CreatePostForm } from '@outstand-so/ui';
<CreatePostForm
apiKey="your-api-key"
enableScheduling={true}
enableDrafts={true}
onPostCreated={(post) => {
console.log('Post created:', post);
}}
onError={(error) => {
console.error('Error:', error);
}}
/>Props:
apiKey(required): Your API keybaseUrl(optional): API base URLaccounts(optional): Pre-selected accountsonPostCreated(optional): Callback when post is createdonError(optional): Error handlerclassName(optional): Additional CSS classesenableScheduling(optional): Enable scheduling UI (default: false)enableDrafts(optional): Enable draft saving (default: false)
PostComposer
A rich text editor component for composing post content with character limits and account-specific validation.
import { PostComposer } from '@outstand-so/ui';
<PostComposer
value={postContent}
onChange={setPostContent}
selectedAccounts={selectedAccounts}
placeholder="What's on your mind?"
maxLength={5000}
/>Props:
value(required): Current post contentonChange(required): Content change handlerselectedAccounts(optional): Selected accounts for validationplaceholder(optional): Placeholder textmaxLength(optional): Maximum character lengthclassName(optional): Additional CSS classes
NetworkSelector
Component for selecting which social accounts to post to.
import { NetworkSelector } from '@outstand-so/ui';
<NetworkSelector
accounts={accounts}
selectedIds={selectedAccountIds}
onChange={setSelectedAccountIds}
/>Props:
accounts(required): Array of SocialAccount objectsselectedIds(required): Array of selected account IDsonChange(required): Selection change handlerclassName(optional): Additional CSS classes
PostScheduler
Date and time picker for scheduling posts.
import { PostScheduler } from '@outstand-so/ui';
<PostScheduler
value={scheduledDate}
onChange={setScheduledDate}
minDate={new Date()}
maxDays={30}
/>Props:
value(required): Selected date (Date | null)onChange(required): Date change handlerclassName(optional): Additional CSS classesminDate(optional): Minimum selectable datemaxDays(optional): Maximum days in the future
NetworkConfigPanel
Configure platform-specific options for selected networks.
import { NetworkConfigPanel } from '@outstand-so/ui';
<NetworkConfigPanel
networks={['instagram', 'youtube', 'tiktok']}
configs={networkConfigs}
onChange={setNetworkConfigs}
/>Props:
networks(required): Array of network namesconfigs(required): Configuration objectonChange(required): Config change handlerclassName(optional): Additional CSS classes
Configuration Options:
- Threads:
{ reply_control?: "everyone" | "accounts_you_follow" | "mentioned_only" } - Instagram:
{ media_type?: "REELS" | "STORIES" | "FEED", share_to_feed?: boolean } - YouTube:
{ title?: string, description?: string, privacy_status?: "public" | "private" | "unlisted", category_id?: string, tags?: string[] } - TikTok:
{ privacy_level?: "PUBLIC_TO_EVERYONE" | "MUTUAL_FOLLOW_FRIENDS" | "SELF_ONLY", disable_duet?: boolean, disable_stitch?: boolean, disable_comment?: boolean }
Media Management
MediaUploader
Component for uploading images and videos.
import { MediaUploader } from '@outstand-so/ui';
<MediaUploader
apiKey="your-api-key"
onUploadComplete={(media) => {
console.log('Uploaded:', media);
}}
onUploadError={(error) => {
console.error('Upload error:', error);
}}
maxFiles={10}
acceptedTypes={['image/*', 'video/*']}
/>Props:
apiKey(required): Your API keybaseUrl(optional): API base URLonUploadComplete(optional): Callback with uploaded media filesonUploadError(optional): Error handlermaxFiles(optional): Maximum number of files (default: unlimited)acceptedTypes(optional): MIME types to acceptclassName(optional): Additional CSS classes
MediaPreview
Preview a single media file with optional remove action.
import { MediaPreview } from '@outstand-so/ui';
<MediaPreview
media={mediaFile}
onRemove={() => handleRemove(mediaFile.id)}
progress={uploadProgress}
/>Props:
media(required): MediaFile objectonRemove(optional): Remove handlerprogress(optional): Upload progress (0-100)className(optional): Additional CSS classes
MediaGallery
Display multiple media files in a grid layout.
import { MediaGallery } from '@outstand-so/ui';
<MediaGallery
media={mediaFiles}
onRemove={(index) => {
setMediaFiles(prev => prev.filter((_, i) => i !== index));
}}
columns={3}
/>Props:
media(required): Array of MediaFile objectsonRemove(optional): Remove handler with indexclassName(optional): Additional CSS classescolumns(optional): Grid columns (2 | 3 | 4, default: 3)
Analytics
PostMetrics
Display analytics for a specific post.
import { PostMetrics } from '@outstand-so/ui';
<PostMetrics
apiKey="your-api-key"
postId="post-id"
refreshInterval={30000}
/>Props:
apiKey(required): Your API keypostId(required): Post ID to display metrics forbaseUrl(optional): API base URLclassName(optional): Additional CSS classesrefreshInterval(optional): Auto-refresh interval in milliseconds
PostMetricsCard
Display metrics for a single account's post.
import { PostMetricsCard } from '@outstand-so/ui';
<PostMetricsCard
account={account}
metrics={metricsData}
platformPostId="123456789"
publishedAt="2025-01-15T10:30:00Z"
/>Props:
account(required): Account object with id, nickname, network, usernamemetrics(required): PostMetricsData objectplatformPostId(optional): Platform-specific post IDpublishedAt(optional): Publication timestampclassName(optional): Additional CSS classes
PostsWithMetrics
Display a paginated list of posts with their metrics.
import { PostsWithMetrics } from '@outstand-so/ui';
<PostsWithMetrics
apiKey="your-api-key"
socialAccountId="account-id"
pageSize={10}
/>Props:
apiKey(required): Your API keybaseUrl(optional): API base URLsocialAccountId(optional): Filter by account IDpageSize(optional): Posts per page (default: 10)className(optional): Additional CSS classes
OAuth Flow
OAuthCallback
Handle OAuth callback and finalize account connections.
import { OAuthCallback } from '@outstand-so/ui';
<OAuthCallback
apiKey="your-api-key"
onSuccess={(accounts) => {
console.log('Connected accounts:', accounts);
}}
onError={(error) => {
console.error('Connection error:', error);
}}
/>Props:
apiKey(required): Your API keybaseUrl(optional): API base URLonSuccess(optional): Callback with connected accountsonError(optional): Error handlerclassName(optional): Additional CSS classes
PageSelector
Select pages to connect (for networks like Facebook that have multiple pages).
import { PageSelector } from '@outstand-so/ui';
<PageSelector
network="facebook"
pages={availablePages}
onSelect={(selectedIds) => {
console.log('Selected pages:', selectedIds);
}}
isLoading={false}
/>Props:
network(required): Network namepages(required): Array of available pagesonSelect(required): Selection handlerisLoading(optional): Loading stateclassName(optional): Additional CSS classes
Hooks
useOutstand
Access the Outstand context (accounts, selected accounts, loading state).
import { useOutstand } from '@outstand-so/ui';
function MyComponent() {
const { accounts, selectedAccounts, setSelectedAccounts, isLoading } = useOutstand();
return (
<div>
{accounts.map(account => (
<div key={account.id}>{account.username}</div>
))}
</div>
);
}Returns:
apiKey: Current API keybaseUrl: Base URLtenantId: Tenant IDaccounts: Array of SocialAccountsetAccounts: Update accountsselectedAccounts: Array of selected account IDssetSelectedAccounts: Update selected accountsisLoading: Loading statesetIsLoading: Update loading state
useOutstandApi
Get API client methods for making requests.
import { useOutstandApi } from '@outstand-so/ui';
function MyComponent() {
const api = useOutstandApi({ apiKey: 'your-api-key' });
const fetchAccounts = async () => {
const response = await api.get('/v1/social-accounts');
if (response.success) {
console.log('Accounts:', response.data);
}
};
return <button onClick={fetchAccounts}>Fetch Accounts</button>;
}Returns:
get<T>(endpoint): GET requestpost<T>(endpoint, body): POST requestpatch<T>(endpoint, body): PATCH requestdelete<T>(endpoint): DELETE requestrequest<T>(endpoint, options): Custom request
useAccounts
Fetch and manage social accounts with pagination.
import { useAccounts } from '@outstand-so/ui';
function AccountsComponent() {
const {
accounts,
total,
isLoading,
error,
refetch,
disconnectAccount,
hasNextPage,
hasPrevPage
} = useAccounts({
apiKey: 'your-api-key',
limit: 20,
offset: 0
});
return (
<div>
{accounts.map(account => (
<div key={account.id}>
{account.username}
<button onClick={() => disconnectAccount(account.id)}>
Disconnect
</button>
</div>
))}
</div>
);
}Options:
apiKey(required): Your API keybaseUrl(optional): API base URLtenantId(optional): Tenant IDlimit(optional): Page sizeoffset(optional): Pagination offset
Returns:
accounts: Array of SocialAccounttotal: Total countisLoading: Loading stateerror: Error objectrefetch: Refetch functiondisconnectAccount: Disconnect functionhasNextPage: BooleanhasPrevPage: Boolean
usePosts
Fetch and manage posts with pagination.
import { usePosts } from '@outstand-so/ui';
function PostsComponent() {
const {
posts,
total,
isLoading,
error,
refetch,
createPost,
deletePost,
hasNextPage,
hasPrevPage
} = usePosts({
apiKey: 'your-api-key',
socialAccountId: 'account-id',
limit: 10
});
const handleCreate = async () => {
const response = await createPost({
content: 'Hello world!',
accounts: ['account-id']
});
if (response.success) {
console.log('Post created:', response.data);
}
};
return (
<div>
<button onClick={handleCreate}>Create Post</button>
{posts.map(post => (
<div key={post.id}>
{post.containers[0]?.content}
<button onClick={() => deletePost(post.id)}>Delete</button>
</div>
))}
</div>
);
}Options:
apiKey(required): Your API keybaseUrl(optional): API base URLsocialAccountId(optional): Filter by accountlimit(optional): Page sizeoffset(optional): Pagination offset
Returns:
posts: Array of Posttotal: Total countisLoading: Loading stateerror: Error objectrefetch: Refetch functioncreatePost: Create post functiondeletePost: Delete post functionhasNextPage: BooleanhasPrevPage: Boolean
usePostMetrics
Fetch analytics for a specific post.
import { usePostMetrics } from '@outstand-so/ui';
function MetricsComponent({ postId }: { postId: string }) {
const {
analytics,
isLoading,
error,
refetch
} = usePostMetrics({
apiKey: 'your-api-key',
postId,
refreshInterval: 30000
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<p>Total Likes: {analytics?.aggregated_metrics.total_likes}</p>
<p>Total Views: {analytics?.aggregated_metrics.total_views}</p>
</div>
);
}Options:
apiKey(required): Your API keypostId(required): Post IDbaseUrl(optional): API base URLrefreshInterval(optional): Auto-refresh interval in ms
Returns:
analytics: PostAnalytics object or nullisLoading: Loading stateerror: Error objectrefetch: Refetch function
useMediaUpload
Upload media files to Outstand.
import { useMediaUpload } from '@outstand-so/ui';
function UploadComponent() {
const {
uploadFile,
uploadFiles,
getUploadUrl,
isUploading,
uploadProgress
} = useMediaUpload({
apiKey: 'your-api-key'
});
const handleUpload = async (file: File) => {
const mediaFile = await uploadFile(file);
if (mediaFile) {
console.log('Uploaded:', mediaFile);
}
};
return (
<div>
<input
type="file"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) handleUpload(file);
}}
/>
{isUploading && <div>Uploading... {uploadProgress[file.name]}%</div>}
</div>
);
}Options:
apiKey(required): Your API keybaseUrl(optional): API base URL
Returns:
uploadFile: Upload single fileuploadFiles: Upload multiple filesgetUploadUrl: Get upload URLisUploading: Uploading stateuploadProgress: Progress by filename
useOAuthFlow
Manage OAuth flow for connecting accounts.
import { useOAuthFlow } from '@outstand-so/ui';
function OAuthComponent() {
const {
getAuthUrl,
getPendingConnection,
finalizeConnection,
isLoading
} = useOAuthFlow({
apiKey: 'your-api-key'
});
const handleConnect = async () => {
const response = await getAuthUrl('x', 'https://yourapp.com/callback');
if (response.success && response.data) {
window.location.href = response.data.auth_url;
}
};
return (
<button onClick={handleConnect} disabled={isLoading}>
Connect X Account
</button>
);
}Options:
apiKey(required): Your API keybaseUrl(optional): API base URL
Returns:
getAuthUrl: Get OAuth URLgetPendingConnection: Get pending connection detailsfinalizeConnection: Finalize connectionisLoading: Loading state
TypeScript Types
The package exports comprehensive TypeScript types:
import type {
SocialAccount,
SocialNetwork,
Post,
PostContainer,
PostSocialAccount,
MediaFile,
PostAnalytics,
PostMetricsData,
CreatePostRequest,
ApiResponse,
PaginatedResponse,
// ... and more
} from '@outstand-so/ui';Key Types:
SocialNetwork: Union type of supported networksSocialAccount: Account object structurePost: Post object structureMediaFile: Media file structurePostAnalytics: Analytics data structureCreatePostRequest: Post creation payloadApiResponse<T>: Standard API response wrapper
Examples
Complete Post Creation Flow
import {
OutstandProvider,
CreatePostForm,
AccountsList
} from '@outstand-so/ui';
function PostManager() {
return (
<OutstandProvider apiKey="your-api-key">
<div>
<h2>Connected Accounts</h2>
<AccountsList apiKey="your-api-key" />
<h2>Create Post</h2>
<CreatePostForm
apiKey="your-api-key"
enableScheduling={true}
onPostCreated={(post) => {
alert(`Post created: ${post.id}`);
}}
/>
</div>
</OutstandProvider>
);
}Custom Post Creation with Individual Components
import {
OutstandProvider,
PostComposer,
NetworkSelector,
MediaUploader,
PostScheduler,
NetworkConfigPanel,
useAccounts
} from '@outstand-so/ui';
function CustomPostCreator() {
const { accounts } = useAccounts({ apiKey: 'your-api-key' });
const [content, setContent] = useState('');
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const [media, setMedia] = useState<MediaFile[]>([]);
const [scheduledAt, setScheduledAt] = useState<Date | null>(null);
const handleSubmit = async () => {
// Use usePosts hook to create post
// ...
};
return (
<div>
<PostComposer
value={content}
onChange={setContent}
selectedAccounts={accounts.filter(a => selectedIds.includes(a.id))}
/>
<NetworkSelector
accounts={accounts}
selectedIds={selectedIds}
onChange={setSelectedIds}
/>
<MediaUploader
apiKey="your-api-key"
onUploadComplete={setMedia}
/>
<PostScheduler
value={scheduledAt}
onChange={setScheduledAt}
/>
<NetworkConfigPanel
networks={[...new Set(accounts.filter(a => selectedIds.includes(a.id)).map(a => a.network))]}
configs={{}}
onChange={() => {}}
/>
<button onClick={handleSubmit}>Create Post</button>
</div>
);
}View Post Analytics
import { PostMetrics, PostsWithMetrics } from '@outstand-so/ui';
function AnalyticsDashboard() {
const [selectedPostId, setSelectedPostId] = useState<string | null>(null);
return (
<div>
{selectedPostId ? (
<PostMetrics
apiKey="your-api-key"
postId={selectedPostId}
refreshInterval={30000}
/>
) : (
<PostsWithMetrics
apiKey="your-api-key"
pageSize={10}
/>
)}
</div>
);
}Learn More
- Check out the playground example to see all components in action
- View the package on npm