React Components
The HiveForge SDK includes optional React components and hooks for building entitlement-aware UIs. These are tree-shaken out if React is not used.
React is an optional peer dependency. Install it separately if not already in your project: npm install react.
Provider Setup
Wrap your application with HiveForgeProvider or EntitlementWrapper to make HiveForge state available to all child components.
HiveForgeProvider
The base provider that supplies HiveForge context. You manage initialization and state display yourself.
import { HiveForgeClient, HiveForgeProvider } from '@producthacker/hiveforge-sdk';
const hiveforge = new HiveForgeClient({
deploymentId: process.env.NEXT_PUBLIC_HIVEFORGE_DEPLOYMENT_ID!,
deploymentSecret: process.env.HIVEFORGE_DEPLOYMENT_SECRET!,
});
function App() {
return (
<HiveForgeProvider client={hiveforge}>
<YourApp />
</HiveForgeProvider>
);
}Props:
| Prop | Type | Required | Description |
|---|---|---|---|
client | HiveForgeClient | Yes | An initialized (or to-be-initialized) client instance |
children | ReactNode | Yes | Child components |
The provider automatically calls initialize() if the client has not been initialized yet, and subscribes to entitlements:updated and entitlements:error events.
EntitlementWrapper
A higher-level wrapper that includes HiveForgeProvider and automatically handles suspended and grace period states with built-in UI.
import { HiveForgeClient, EntitlementWrapper } from '@producthacker/hiveforge-sdk';
const hiveforge = new HiveForgeClient({
deploymentId: process.env.NEXT_PUBLIC_HIVEFORGE_DEPLOYMENT_ID!,
deploymentSecret: process.env.HIVEFORGE_DEPLOYMENT_SECRET!,
});
function App() {
return (
<EntitlementWrapper client={hiveforge} upgradeUrl="/pricing">
<YourApp />
</EntitlementWrapper>
);
}Props:
| Prop | Type | Required | Description |
|---|---|---|---|
client | HiveForgeClient | Yes | Client instance |
children | ReactNode | Yes | Child components |
upgradeUrl | string | No | URL for the upgrade/renew subscription link |
Built-in behavior:
- Shows a loading state while entitlements are being fetched
- Renders
SuspendedPageif the subscription status issuspended - Shows
GracePeriodBannerabove your app content duringgrace_periodstatus - Renders your app normally for
active,trialing, and other statuses
Hooks
All hooks must be used inside a HiveForgeProvider or EntitlementWrapper.
useHiveForge()
Access the full HiveForge context including the client, entitlements, loading state, and refresh function.
import { useHiveForge } from '@producthacker/hiveforge-sdk';
function Dashboard() {
const { client, entitlements, isLoading, error, refresh } = useHiveForge();
if (isLoading) return <div>Loading entitlements...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<p>Tier: {entitlements?.tier}</p>
<p>Status: {entitlements?.status}</p>
<button onClick={refresh}>Refresh Entitlements</button>
</div>
);
}Returns (HiveForgeContextValue):
| Field | Type | Description |
|---|---|---|
client | HiveForgeClient | The SDK client instance |
entitlements | Entitlements | null | Current entitlements (null while loading) |
isLoading | boolean | Whether entitlements are being fetched |
error | Error | null | Most recent error, if any |
refresh | () => Promise<void> | Manually refresh entitlements |
useEntitlements()
Get the current entitlements object directly.
import { useEntitlements } from '@producthacker/hiveforge-sdk';
function PlanInfo() {
const entitlements = useEntitlements();
if (!entitlements) return null;
return (
<div>
<p>Tier: {entitlements.tier}</p>
<p>AI limit: {entitlements.features.ai_monthly_limit ?? 'Unlimited'}</p>
</div>
);
}Returns: Entitlements | null
useFeature(feature)
Check if a specific feature flag is enabled. Returns false while entitlements are loading.
import { useFeature } from '@producthacker/hiveforge-sdk';
function AIButton() {
const aiEnabled = useFeature('ai_enabled');
if (!aiEnabled) {
return <button disabled>AI (Upgrade Required)</button>;
}
return <button onClick={handleAI}>Ask AI</button>;
}Parameters:
| Name | Type | Description |
|---|---|---|
feature | keyof FeatureFlags | Feature flag to check |
Returns: boolean
useSubscriptionStatus()
Get the current subscription status string.
import { useSubscriptionStatus } from '@producthacker/hiveforge-sdk';
function StatusBadge() {
const status = useSubscriptionStatus();
const colors: Record<string, string> = {
active: 'green',
trialing: 'blue',
past_due: 'orange',
grace_period: 'yellow',
suspended: 'red',
canceled: 'gray',
};
return (
<span style={{ color: colors[status] }}>
{status.replace('_', ' ').toUpperCase()}
</span>
);
}Returns: SubscriptionStatus -- one of 'active', 'trialing', 'past_due', 'grace_period', 'suspended', 'canceled'.
useTier()
Get the current subscription tier.
import { useTier } from '@producthacker/hiveforge-sdk';
function TierDisplay() {
const tier = useTier();
return <span>Current plan: {tier}</span>;
}Returns: string -- e.g., 'sandbox', 'trial', 'launch', 'growth', 'enterprise'.
useMessage()
Get the user-facing message from entitlements (e.g., trial expiration warnings).
import { useMessage } from '@producthacker/hiveforge-sdk';
function TrialBanner() {
const message = useMessage();
if (!message) return null;
return (
<div style={{ background: '#FEF3C7', padding: '0.75rem', textAlign: 'center' }}>
{message}
</div>
);
}Returns: string | null
Components
EntitlementGate
Conditionally render children based on whether a feature flag is enabled. Renders the fallback (or nothing) when the feature is disabled.
import { EntitlementGate } from '@producthacker/hiveforge-sdk';
function FeaturePage() {
return (
<div>
<h1>Dashboard</h1>
<EntitlementGate feature="ai_enabled" fallback={<UpgradePrompt feature="AI" />}>
<AIAssistantPanel />
</EntitlementGate>
<EntitlementGate feature="billing_enabled">
<BillingSection />
</EntitlementGate>
<EntitlementGate
feature="white_label"
fallback={<p>White labeling is available on Growth and Enterprise plans.</p>}
>
<WhiteLabelSettings />
</EntitlementGate>
</div>
);
}
function UpgradePrompt({ feature }: { feature: string }) {
return (
<div style={{ padding: '2rem', textAlign: 'center', background: '#f5f5f5' }}>
<p>{feature} is not available on your current plan.</p>
<a href="/pricing">Upgrade to unlock {feature}</a>
</div>
);
}Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
feature | keyof FeatureFlags | Yes | -- | Feature flag to check |
fallback | ReactNode | No | null | What to render when feature is disabled |
children | ReactNode | Yes | -- | What to render when feature is enabled |
SuspendedPage
A full-page component displayed when the subscription is suspended. Used internally by EntitlementWrapper but can be used standalone.
import { SuspendedPage } from '@producthacker/hiveforge-sdk';
function CustomSuspendedHandler() {
const status = useSubscriptionStatus();
if (status === 'suspended') {
return (
<SuspendedPage
message="Your subscription has expired. Renew to regain access."
upgradeUrl="/pricing"
/>
);
}
return <AppContent />;
}Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
message | string | No | Generic suspension message | Custom message to display |
upgradeUrl | string | No | -- | URL for the renewal button |
GracePeriodBanner
A banner displayed at the top of the page during a grace period. Used internally by EntitlementWrapper but can be used standalone.
import { GracePeriodBanner, useHiveForge } from '@producthacker/hiveforge-sdk';
function AppLayout({ children }: { children: React.ReactNode }) {
const { entitlements } = useHiveForge();
return (
<div>
{entitlements?.status === 'grace_period' && (
<GracePeriodBanner
message={entitlements.message ?? undefined}
upgradeUrl="/pricing"
/>
)}
<main>{children}</main>
</div>
);
}Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
message | string | No | Generic grace period message | Custom message to display |
upgradeUrl | string | No | -- | URL for the renewal button |
Full Example: Next.js App
// app/providers.tsx
'use client';
import { HiveForgeClient, EntitlementWrapper } from '@producthacker/hiveforge-sdk';
import { useMemo } from 'react';
export function Providers({ children }: { children: React.ReactNode }) {
const hiveforge = useMemo(() => new HiveForgeClient({
deploymentId: process.env.NEXT_PUBLIC_HIVEFORGE_DEPLOYMENT_ID!,
deploymentSecret: process.env.NEXT_PUBLIC_HIVEFORGE_DEPLOYMENT_SECRET!,
}), []);
return (
<EntitlementWrapper client={hiveforge} upgradeUrl="/pricing">
{children}
</EntitlementWrapper>
);
}// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}// app/dashboard/page.tsx
'use client';
import {
useHiveForge,
useFeature,
useTier,
useMessage,
EntitlementGate,
} from '@producthacker/hiveforge-sdk';
export default function DashboardPage() {
const { isLoading, error } = useHiveForge();
const tier = useTier();
const message = useMessage();
const aiEnabled = useFeature('ai_enabled');
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Dashboard</h1>
<p>Plan: {tier}</p>
{message && <p style={{ color: '#b45309' }}>{message}</p>}
<EntitlementGate feature="ai_enabled" fallback={<p>Upgrade to use AI features.</p>}>
<section>
<h2>AI Assistant</h2>
{/* AI-powered features here */}
</section>
</EntitlementGate>
</div>
);
}