Skip to content

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/ui

Or with yarn:

yarn add @outstand-so/ui

Or with pnpm:

pnpm add @outstand-so/ui

Getting Started

Provider Setup

Wrap your application (or the part that uses Outstand components) with the OutstandProvider:

tsx
import { OutstandProvider } from '@outstand-so/ui';

function App() {
	return (
		<OutstandProvider apiKey="your-api-key" baseUrl="
			{/* Your app components */}
		</OutstandProvider>
	);
}

Props:

  • apiKey (required): Your Outstand API key
  • baseUrl (optional): Base URL for API requests. Defaults to `
  • tenantId (optional): Tenant ID for multi-tenant applications
  • initialAccounts (optional): Pre-populate accounts without fetching

Components

Account Management

ConnectAccountButton

A button component that initiates OAuth flow for connecting a social media account.

tsx
import { ConnectAccountButton } from '@outstand-so/ui';

<ConnectAccountButton
	network="x"
	redirectUri="
	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 flow
  • apiKey (required): Your API key
  • tenantId (optional): Tenant ID for multi-tenant apps
  • baseUrl (optional): API base URL
  • onSuccess (optional): Callback when auth URL is obtained
  • onError (optional): Error handler
  • className (optional): Additional CSS classes
  • children (optional): Custom button content
  • variant (optional): Button style ("default" | "outline" | "ghost")
  • size (optional): Button size ("sm" | "md" | "lg")

ConnectAccountButtonGroup

Display multiple connection buttons in a group layout.

tsx
import { ConnectAccountButtonGroup } from '@outstand-so/ui';

<ConnectAccountButtonGroup
	networks={['x', 'linkedin', 'instagram', 'facebook']}
	redirectUri="
	apiKey="your-api-key"
	layout="grid"
	variant="outline"
/>

Props:

  • networks (required): Array of social networks to show
  • redirectUri (required): OAuth callback URL
  • apiKey (required): Your API key
  • layout (optional): Layout style ("horizontal" | "vertical" | "grid")
  • Other props same as ConnectAccountButton

AccountsList

Display a paginated list of connected social accounts with management options.

tsx
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 key
  • baseUrl (optional): API base URL
  • tenantId (optional): Tenant ID
  • onAccountSelect (optional): Callback when account is selected
  • onAccountDisconnect (optional): Callback when account is disconnected
  • className (optional): Additional CSS classes
  • pageSize (optional): Number of accounts per page (default: 20)

AccountCard

Display a single social account card.

tsx
import { AccountCard } from '@outstand-so/ui';

<AccountCard
	account={account}
	onSelect={() => handleSelect(account)}
	onDisconnect={() => handleDisconnect(account.id)}
/>

Props:

  • account (required): SocialAccount object
  • onSelect (optional): Selection handler
  • onDisconnect (optional): Disconnect handler
  • className (optional): Additional CSS classes

Post Creation

CreatePostForm

A complete form component for creating and scheduling posts.

tsx
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 key
  • baseUrl (optional): API base URL
  • accounts (optional): Pre-selected accounts
  • onPostCreated (optional): Callback when post is created
  • onError (optional): Error handler
  • className (optional): Additional CSS classes
  • enableScheduling (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.

tsx
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 content
  • onChange (required): Content change handler
  • selectedAccounts (optional): Selected accounts for validation
  • placeholder (optional): Placeholder text
  • maxLength (optional): Maximum character length
  • className (optional): Additional CSS classes

NetworkSelector

Component for selecting which social accounts to post to.

tsx
import { NetworkSelector } from '@outstand-so/ui';

<NetworkSelector
	accounts={accounts}
	selectedIds={selectedAccountIds}
	onChange={setSelectedAccountIds}
/>

Props:

  • accounts (required): Array of SocialAccount objects
  • selectedIds (required): Array of selected account IDs
  • onChange (required): Selection change handler
  • className (optional): Additional CSS classes

PostScheduler

Date and time picker for scheduling posts.

tsx
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 handler
  • className (optional): Additional CSS classes
  • minDate (optional): Minimum selectable date
  • maxDays (optional): Maximum days in the future

NetworkConfigPanel

Configure platform-specific options for selected networks.

tsx
import { NetworkConfigPanel } from '@outstand-so/ui';

<NetworkConfigPanel
	networks={['instagram', 'youtube', 'tiktok']}
	configs={networkConfigs}
	onChange={setNetworkConfigs}
/>

Props:

  • networks (required): Array of network names
  • configs (required): Configuration object
  • onChange (required): Config change handler
  • className (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.

tsx
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 key
  • baseUrl (optional): API base URL
  • onUploadComplete (optional): Callback with uploaded media files
  • onUploadError (optional): Error handler
  • maxFiles (optional): Maximum number of files (default: unlimited)
  • acceptedTypes (optional): MIME types to accept
  • className (optional): Additional CSS classes

MediaPreview

Preview a single media file with optional remove action.

tsx
import { MediaPreview } from '@outstand-so/ui';

<MediaPreview
	media={mediaFile}
	onRemove={() => handleRemove(mediaFile.id)}
	progress={uploadProgress}
/>

Props:

  • media (required): MediaFile object
  • onRemove (optional): Remove handler
  • progress (optional): Upload progress (0-100)
  • className (optional): Additional CSS classes

MediaGallery

Display multiple media files in a grid layout.

tsx
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 objects
  • onRemove (optional): Remove handler with index
  • className (optional): Additional CSS classes
  • columns (optional): Grid columns (2 | 3 | 4, default: 3)

Analytics

PostMetrics

Display analytics for a specific post.

tsx
import { PostMetrics } from '@outstand-so/ui';

<PostMetrics
	apiKey="your-api-key"
	postId="post-id"
	refreshInterval={30000}
/>

Props:

  • apiKey (required): Your API key
  • postId (required): Post ID to display metrics for
  • baseUrl (optional): API base URL
  • className (optional): Additional CSS classes
  • refreshInterval (optional): Auto-refresh interval in milliseconds

PostMetricsCard

Display metrics for a single account's post.

tsx
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, username
  • metrics (required): PostMetricsData object
  • platformPostId (optional): Platform-specific post ID
  • publishedAt (optional): Publication timestamp
  • className (optional): Additional CSS classes

PostsWithMetrics

Display a paginated list of posts with their metrics.

tsx
import { PostsWithMetrics } from '@outstand-so/ui';

<PostsWithMetrics
	apiKey="your-api-key"
	socialAccountId="account-id"
	pageSize={10}
/>

Props:

  • apiKey (required): Your API key
  • baseUrl (optional): API base URL
  • socialAccountId (optional): Filter by account ID
  • pageSize (optional): Posts per page (default: 10)
  • className (optional): Additional CSS classes

OAuth Flow

OAuthCallback

Handle OAuth callback and finalize account connections.

tsx
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 key
  • baseUrl (optional): API base URL
  • onSuccess (optional): Callback with connected accounts
  • onError (optional): Error handler
  • className (optional): Additional CSS classes

PageSelector

Select pages to connect (for networks like Facebook that have multiple pages).

tsx
import { PageSelector } from '@outstand-so/ui';

<PageSelector
	network="facebook"
	pages={availablePages}
	onSelect={(selectedIds) => {
		console.log('Selected pages:', selectedIds);
	}}
	isLoading={false}
/>

Props:

  • network (required): Network name
  • pages (required): Array of available pages
  • onSelect (required): Selection handler
  • isLoading (optional): Loading state
  • className (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 key
  • baseUrl: Base URL
  • tenantId: Tenant ID
  • accounts: Array of SocialAccount
  • setAccounts: Update accounts
  • selectedAccounts: Array of selected account IDs
  • setSelectedAccounts: Update selected accounts
  • isLoading: Loading state
  • setIsLoading: 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 request
  • post<T>(endpoint, body): POST request
  • patch<T>(endpoint, body): PATCH request
  • delete<T>(endpoint): DELETE request
  • request<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 (
		&lt;div>
			{accounts.map(account => (
				&lt;div key={account.id}>
					{account.username}
					&lt;button onClick={() => disconnectAccount(account.id)}>
						Disconnect
					&lt;/button>
				&lt;/div>
			))}
		&lt;/div>
	);
}

Options:

  • apiKey (required): Your API key
  • baseUrl (optional): API base URL
  • tenantId (optional): Tenant ID
  • limit (optional): Page size
  • offset (optional): Pagination offset

Returns:

  • accounts: Array of SocialAccount
  • total: Total count
  • isLoading: Loading state
  • error: Error object
  • refetch: Refetch function
  • disconnectAccount: Disconnect function
  • hasNextPage: Boolean
  • hasPrevPage: 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 (
		&lt;div>
			&lt;button onClick={handleCreate}>Create Post&lt;/button>
			{posts.map(post => (
				&lt;div key={post.id}>
					{post.containers[0]?.content}
					&lt;button onClick={() => deletePost(post.id)}>Delete&lt;/button>
				&lt;/div>
			))}
		&lt;/div>
	);
}

Options:

  • apiKey (required): Your API key
  • baseUrl (optional): API base URL
  • socialAccountId (optional): Filter by account
  • limit (optional): Page size
  • offset (optional): Pagination offset

Returns:

  • posts: Array of Post
  • total: Total count
  • isLoading: Loading state
  • error: Error object
  • refetch: Refetch function
  • createPost: Create post function
  • deletePost: Delete post function
  • hasNextPage: Boolean
  • hasPrevPage: 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 &lt;div>Loading...&lt;/div>;
	if (error) return &lt;div>Error: {error.message}&lt;/div>;

	return (
		&lt;div>
			&lt;p>Total Likes: {analytics?.aggregated_metrics.total_likes}&lt;/p>
			&lt;p>Total Views: {analytics?.aggregated_metrics.total_views}&lt;/p>
		&lt;/div>
	);
}

Options:

  • apiKey (required): Your API key
  • postId (required): Post ID
  • baseUrl (optional): API base URL
  • refreshInterval (optional): Auto-refresh interval in ms

Returns:

  • analytics: PostAnalytics object or null
  • isLoading: Loading state
  • error: Error object
  • refetch: 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 (
		&lt;div>
			&lt;input
				type="file"
				onChange={(e) => {
					const file = e.target.files?.[0];
					if (file) handleUpload(file);
				}}
			/>
			{isUploading && &lt;div>Uploading... {uploadProgress[file.name]}%&lt;/div>}
		&lt;/div>
	);
}

Options:

  • apiKey (required): Your API key
  • baseUrl (optional): API base URL

Returns:

  • uploadFile: Upload single file
  • uploadFiles: Upload multiple files
  • getUploadUrl: Get upload URL
  • isUploading: Uploading state
  • uploadProgress: 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', '
		if (response.success && response.data) {
			window.location.href = response.data.auth_url;
		}
	};

	return (
		&lt;button onClick={handleConnect} disabled={isLoading}>
			Connect X Account
		&lt;/button>
	);
}

Options:

  • apiKey (required): Your API key
  • baseUrl (optional): API base URL

Returns:

  • getAuthUrl: Get OAuth URL
  • getPendingConnection: Get pending connection details
  • finalizeConnection: Finalize connection
  • isLoading: 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 networks
  • SocialAccount: Account object structure
  • Post: Post object structure
  • MediaFile: Media file structure
  • PostAnalytics: Analytics data structure
  • CreatePostRequest: Post creation payload
  • ApiResponse<T>``: Standard API response wrapper

Examples

Complete Post Creation Flow

tsx
import {
	OutstandProvider,
	CreatePostForm,
	AccountsList
} from '@outstand-so/ui';

function PostManager() {
	return (
		&lt;OutstandProvider apiKey="your-api-key">
			&lt;div>
				&lt;h2>Connected Accounts&lt;/h2>
				&lt;AccountsList apiKey="your-api-key" />

				&lt;h2>Create Post&lt;/h2>
				&lt;CreatePostForm
					apiKey="your-api-key"
					enableScheduling={true}
					onPostCreated={(post) => {
						alert(`Post created: ${post.id}`);
					}}
				/>
			&lt;/div>
		&lt;/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&lt;string[]>([]);
	const [media, setMedia] = useState&lt;MediaFile[]>([]);
	const [scheduledAt, setScheduledAt] = useState&lt;Date | null>(null);

	const handleSubmit = async () => {
		// Use usePosts hook to create post
		// ...
	};

	return (
		&lt;div>
			&lt;PostComposer
				value={content}
				onChange={setContent}
				selectedAccounts={accounts.filter(a => selectedIds.includes(a.id))}
			/>
			&lt;NetworkSelector
				accounts={accounts}
				selectedIds={selectedIds}
				onChange={setSelectedIds}
			/>
			&lt;MediaUploader
				apiKey="your-api-key"
				onUploadComplete={setMedia}
			/>
			&lt;PostScheduler
				value={scheduledAt}
				onChange={setScheduledAt}
			/>
			&lt;NetworkConfigPanel
				networks={[...new Set(accounts.filter(a => selectedIds.includes(a.id)).map(a => a.network))]}
				configs={{}}
				onChange={() => {}}
			/>
			&lt;button onClick={handleSubmit}>Create Post&lt;/button>
		&lt;/div>
	);
}

View Post Analytics

tsx
import { PostMetrics, PostsWithMetrics } from '@outstand-so/ui';

function AnalyticsDashboard() {
	const [selectedPostId, setSelectedPostId] = useState&lt;string | null>(null);

	return (
		&lt;div>
			{selectedPostId ? (
				&lt;PostMetrics
					apiKey="your-api-key"
					postId={selectedPostId}
					refreshInterval={30000}
				/>
			) : (
				&lt;PostsWithMetrics
					apiKey="your-api-key"
					pageSize={10}
				/>
			)}
		&lt;/div>
	);
}

Learn More

  • Check out the playground example to see all components in action
  • View the package on npm

Tool Reference\ \ Previous Page X (Twitter) — Token Refresh Failures\ \ Next Page

On this page

Installation Getting Started Provider Setup Components Account Management ConnectAccountButton ConnectAccountButtonGroup AccountsList AccountCard Post Creation CreatePostForm PostComposer NetworkSelector PostScheduler NetworkConfigPanel Media Management MediaUploader MediaPreview MediaGallery Analytics PostMetrics PostMetricsCard PostsWithMetrics OAuth Flow OAuthCallback PageSelector Hooks useOutstand useOutstandApi useAccounts usePosts usePostMetrics useMediaUpload useOAuthFlow TypeScript Types Examples Complete Post Creation Flow Custom Post Creation with Individual Components View Post Analytics Learn More