beehiiv-react
v0.6.0
Published
Connect a beehiiv account to your React/Next.js project — typed API client, React hooks, subscription form component, and CLI scaffolding tool.
Maintainers
Readme
beehiiv-react
A typed React SDK and CLI for integrating beehiiv newsletters into Next.js applications.
Scaffolds configuration, generates TypeScript types from your publication's custom fields, and provides React hooks and components for subscription management. Supports server-side usage via BeehiivClient, TanStack Query integration, and React Server Components.
Table of Contents
- Installation
- Quick Start
- CLI
- BeehiivProvider
- Hooks
- Components
- BeehiivClient
- Posts & Content Visibility
- Subscriber Profiles
- Tiers
- Authors
- Bulk Subscriptions & Updates
- Engagements
- Hook Infill
- Release Notes
- API Reference
- Contributing
- License
Installation
npm install beehiiv-reactOptional peer dependencies
If you use the beehiiv-react/query TanStack Query adapter, install the peer dependency too:
npm install @tanstack/react-query
@tanstack/react-queryv5+ is required only when importing frombeehiiv-react/query. If you don't use that sub-path, skip this step.
Import Paths
beehiiv-react ships two entry points to support Next.js App Router's server/client module boundary:
| Entry Point | Directive | Use In | Exports |
|---|---|---|---|
| beehiiv-react | "use client" | Client Components | Hooks, UI components, utilities |
| beehiiv-react/server | (none) | Server Components, API routes, Server Actions | BeehiivClient, endpoint classes, data fetchers |
// Client Components
import { useSubscribe, SubscriptionForm } from 'beehiiv-react';
// Server Components / API Routes / Server Actions
import { BeehiivClient, createBeehiivClient } from 'beehiiv-react/server';Why two entry points? Next.js enforces a strict boundary between server and client modules. The root
beehiiv-reactentry has a"use client"directive so React hooks and components work in Client Components. Server-only code likeBeehiivClientmust live in a separate entry point without that directive — otherwise Next.js throws "Cannot access BeehiivClient.prototype on the server."
Quick Start
Initialize beehiiv-react in your Next.js project:
npx beehiiv-react initThis interactive wizard will:
- Prompt for your beehiiv API key
- Let you select a publication
- Fetch custom fields and generate TypeScript types
- Scaffold a
beehiiv.config.ts, API routes, and server actions
CLI
Syncing Custom Fields
After adding or modifying custom fields in the beehiiv dashboard, regenerate your TypeScript types:
npx beehiiv-react syncThis re-fetches the custom field definitions from the beehiiv API and updates types/beehiiv.generated.ts with the latest fields and types.
Upgrading to v0.5.0? Run
npx beehiiv-react syncto scaffold routes for the new resources (authors, tiers, engagements, bulk-subscriptions).
OAuth2 Support
For OAuth2 PKCE-based authentication (instead of API keys):
npx beehiiv-react init --oauthThis starts a local callback server and opens the beehiiv authorization page in your browser. OAuth2 requires a registered client ID with beehiiv. Contact beehiiv to register your application for OAuth2 access.
Version
Print the installed version:
npx beehiiv-react -v
# or
npx beehiiv-react --version
# beehiiv-react/0.4.2BeehiivProvider
Wrap your application with the BeehiivProvider to make beehiiv context available to all hooks and components. In a Next.js App Router project, add it to your root layout:
// app/layout.tsx
import { BeehiivProvider } from 'beehiiv-react';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<BeehiivProvider
publicationId={process.env.NEXT_PUBLIC_BEEHIIV_PUBLICATION_ID!}
apiUrl="/api/beehiiv"
>
{children}
</BeehiivProvider>
</body>
</html>
);
}Hooks
useSubscribe
Subscribe new emails with fully typed custom fields:
'use client';
import { useSubscribe } from 'beehiiv-react';
import type { BeehiivCustomFields } from '@/types/beehiiv.generated';
export function NewsletterSignup() {
const { subscribe, isLoading, isSuccess, error } = useSubscribe<BeehiivCustomFields>({
onSuccess: (subscription) => {
console.log('Subscribed:', subscription.email);
},
onError: (err) => {
console.error('Failed:', err.message);
},
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
subscribe({
email: formData.get('email') as string,
customFields: {
firstName: formData.get('firstName') as string,
},
utmSource: 'website',
});
};
if (isSuccess) return <p>Thanks for subscribing!</p>;
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" placeholder="[email protected]" required />
<input name="firstName" type="text" placeholder="First name" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'Subscribing...' : 'Subscribe'}
</button>
{error && <p>{error.message}</p>}
</form>
);
}useSubscribers
Fetch and paginate through subscribers:
'use client';
import { useSubscribers } from 'beehiiv-react';
export function SubscriberList() {
const { data, loading, error, page, nextPage, prevPage } = useSubscribers({
limit: 20,
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<ul>
{data?.map((sub) => (
<li key={sub.id}>{sub.email}</li>
))}
</ul>
<button onClick={prevPage} disabled={page === 1}>Previous</button>
<button onClick={nextPage}>Next</button>
</div>
);
}usePublications
Fetch all publications accessible with the current API key:
'use client';
import { usePublications } from 'beehiiv-react';
export function PublicationPicker() {
const { data: publications, loading } = usePublications();
if (loading) return <p>Loading publications...</p>;
return (
<select>
{publications?.map((pub) => (
<option key={pub.id} value={pub.id}>{pub.name}</option>
))}
</select>
);
}Components
SubscriptionForm
A pre-built, drop-in subscription form:
import { SubscriptionForm } from 'beehiiv-react';
// Default mode
<SubscriptionForm
submitLabel="Join Newsletter"
emailPlaceholder="Enter your email"
successMessage="Welcome aboard!"
utmSource="homepage"
/>Headless Mode
For full control over rendering, use the renderForm prop:
<SubscriptionForm
renderForm={({ email, setEmail, handleSubmit, isLoading, isSuccess, error }) => (
<form onSubmit={handleSubmit}>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Loading...' : 'Subscribe'}
</button>
{error && <span>{error.message}</span>}
{isSuccess && <span>Subscribed!</span>}
</form>
)}
/>BeehiivClient (Server-Side)
Use the BeehiivClient directly in server-side code (API routes, server actions, scripts).
Important: Always import server-side classes from
beehiiv-react/server— not the package root. The root entry point (beehiiv-react) carries a"use client"directive and is reserved for React components and hooks. ImportingBeehiivClientfrom the root in a Server Component or API route will cause a Next.js error: "Cannot access BeehiivClient.prototype on the server."
import { BeehiivClient } from 'beehiiv-react/server';
const client = new BeehiivClient({
apiKey: process.env.BEEHIIV_API_KEY!,
publicationId: process.env.BEEHIIV_PUBLICATION_ID!,
});
// Create a subscription
const subscription = await client.subscriptions.create({
email: '[email protected]',
customFields: [{ name: 'First Name', value: 'Jane' }],
utmSource: 'api',
});
// List subscribers
const { data: subscribers } = await client.subscriptions.list({ limit: 10 });
// Get custom field definitions
const { data: fields } = await client.customFields.list();Tip: When
publicationIdis set in the client config, you can omit it from individual method calls — the client injects it automatically.
The client includes built-in rate limiting (180 requests/minute) matching beehiiv's API limits.
Posts & Content Visibility
Fetching Posts
import { usePosts, usePost } from 'beehiiv-react';
// List posts — filter by audience and status
const { posts, isLoading, hasMore, loadMore } = usePosts({
audience: 'free', // 'free' | 'premium' | 'all'
status: 'confirmed',
});
// Single post
const { post, isLoading } = usePost({ id: 'post_abc123' });Rendering Posts
import { PostList, PostCard, PostContentRenderer } from 'beehiiv-react';
// Full list with pagination
<PostList
posts={posts}
hasMore={hasMore}
onLoadMore={loadMore}
isLoading={isLoading}
/>
// Single card
<PostCard post={post} showAudienceBadge showPublishDate />
// Post body (provide your own sanitizer)
import DOMPurify from 'dompurify';
<PostContentRenderer
content={post.content}
sanitizeHtml={(html) => DOMPurify.sanitize(html)}
/>Content Gating
import { GatedContent, PremiumContent, useSubscriberAccess } from 'beehiiv-react';
// Declarative gating
<GatedContent
audience="premium"
subscriberEmail={userEmail}
fallback={<p>Upgrade to read this.</p>}
>
<ArticleBody />
</GatedContent>
// Opinionated premium wrapper with upgrade prompt
<PremiumContent
subscriberEmail={userEmail}
upgradePrompt={(tier, status) => (
<UpgradeBanner currentTier={tier} />
)}
>
<ExclusiveContent />
</PremiumContent>
// Programmatic access check
const { canView, tier, isActive, isLoading } = useSubscriberAccess({
email: userEmail,
audience: 'premium',
});Access Logic
The canViewContent(tier, status, audience) utility resolves subscriber access:
'all'audience: always accessible'free'audience: requires active subscription (any tier)'premium'audience: requires active premium subscription
Subscriber Profiles
Resolve a subscriber's identity, tier, and access flags independently of any content or post. Use these hooks to decorate user profiles, gate non-beehiiv features, or render subscriber badges.
Hooks
useSubscriberProfile
Returns the full subscription record alongside pre-computed isPremium and isActive flags.
import { useSubscriberProfile } from 'beehiiv-react';
const { isPremium, tier, isActive, subscription, isLoading } = useSubscriberProfile({
email: user.email, // or id: 'sub_abc123'
});
// Decorate a profile
return (
<UserProfile>
{isPremium && <PremiumBadge />}
</UserProfile>
);useSubscriberTier
Lightweight alternative when you only need the tier flags -- no full subscription record returned.
import { useSubscriberTier } from 'beehiiv-react';
const { isPremium, isActive, isLoading } = useSubscriberTier({ email: user.email });
if (isPremium) enablePremiumFeature();Component
SubscriberBadge
Renders a "Premium" or "Free" badge based on the subscriber's resolved tier.
Supports headless mode via renderBadge for fully custom rendering.
import { SubscriberBadge } from 'beehiiv-react';
// Default badge UI
<SubscriberBadge subscriberEmail={user.email} />
// Headless — bring your own UI
<SubscriberBadge
subscriberEmail={user.email}
renderBadge={({ isPremium, tier }) => (
<MyCustomBadge premium={isPremium} label={tier ?? 'Free'} />
)}
/>Tiers
Manage subscription tiers (free and premium) for your publication.
Hooks
useTiers
import { useTiers } from 'beehiiv-react';
function TierList() {
const { tiers, isLoading } = useTiers({ type: 'premium' });
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{tiers.map((tier) => (
<li key={tier.id}>{tier.name} -- ${tier.price / 100}/mo</li>
))}
</ul>
);
}useTier
import { useTier } from 'beehiiv-react';
function TierDetail({ tierId }: { tierId: string }) {
const { tier, isLoading } = useTier({ tierId });
if (isLoading || !tier) return null;
return <h2>{tier.name}</h2>;
}Component
TierBadge
import { TierBadge } from 'beehiiv-react';
<TierBadge tier={tier} />
{/* Headless mode */}
<TierBadge tier={tier} renderBadge={({ name, type }) => (
<span className={type === 'premium' ? 'gold' : 'gray'}>{name}</span>
)} />Authors
Retrieve author information for your publication.
import { useAuthors, useAuthor } from 'beehiiv-react';
function AuthorList() {
const { authors, isLoading } = useAuthors();
if (isLoading) return null;
return authors.map((a) => <span key={a.id}>{a.name}</span>);
}
function AuthorDetail({ authorId }: { authorId: string }) {
const { author } = useAuthor({ authorId });
return author ? <p>{author.bio}</p> : null;
}Bulk Subscriptions & Updates
Bulk Create Subscriptions (Server-Side)
import { BeehiivClient } from 'beehiiv-react/server';
const client = new BeehiivClient({ apiKey: '...', publicationId: '...' });
const { data } = await client.bulkSubscriptions.create({
subscriptions: [
{ email: '[email protected]', utm_source: 'import' },
{ email: '[email protected]' },
],
});Bulk Update Fields / Status (Server-Side)
// Update custom fields in bulk
await client.bulkSubscriptionUpdates.updateFields({
subscriber_ids: ['sub_1', 'sub_2'],
custom_fields: [{ name: 'plan', value: 'enterprise' }],
});
// Update subscription status in bulk
await client.bulkSubscriptionUpdates.updateStatus({
subscriber_ids: ['sub_1', 'sub_2'],
status: 'active',
});Track Bulk Update Jobs
import { useBulkUpdateJob } from 'beehiiv-react';
function JobTracker({ jobId }: { jobId: string }) {
const { job, isComplete, progress } = useBulkUpdateJob({
jobId,
pollInterval: 2000,
});
return (
<div>
<p>Status: {job?.status}</p>
<p>Progress: {Math.round(progress * 100)}%</p>
</div>
);
}Engagements
Retrieve engagement metrics (opens, clicks, etc.) for a date range.
import { useEngagements } from 'beehiiv-react';
function EngagementDashboard() {
const { metrics, isLoading } = useEngagements({
startDate: '2025-01-01',
endDate: '2025-01-31',
});
if (isLoading || !metrics) return null;
return (
<dl>
<dt>Opens</dt><dd>{metrics.total_opened}</dd>
<dt>Clicks</dt><dd>{metrics.total_clicked}</dd>
</dl>
);
}Hook Infill -- Automations, Webhooks, Segments, Referrals
These hooks provide React-friendly wrappers for resources that previously only had server-side clients.
useAutomations
import { useAutomations } from 'beehiiv-react';
const { automations, isLoading } = useAutomations({ status: 'active' });useWebhooks
import { useWebhooks } from 'beehiiv-react';
const { webhooks, isLoading } = useWebhooks();useSegments
import { useSegments } from 'beehiiv-react';
const { segments, isLoading } = useSegments();useReferrals
import { useReferrals } from 'beehiiv-react';
const { program, subscriberStats } = useReferrals({ subscriberId: 'sub_123' });Release Notes
v0.5.0
Tiers, Authors, Bulk Subscriptions, Engagements, and Hook Infill
- 5 new client namespaces:
tiers(list, get, create, update),authors(list, get),bulkSubscriptions(create),bulkSubscriptionUpdates(list, get, updateFields, updateStatus),engagements(get) - 10 new React hooks:
useTiers,useTier,useAuthors,useAuthor,useBulkUpdateJob,useEngagements,useAutomations,useWebhooks,useSegments,useReferrals - 1 new component:
TierBadge-- renders a tier badge with free/premium styling and headless mode - 27 new TanStack Query adapters added to
beehiiv-react/query - 5 new server fetchers added to
beehiiv-react/server - Modified endpoints:
subscriptions.addTags(),segments.listIds() - API coverage: ~50/72 beehiiv API v2 endpoints
v0.4.2
PostInfonow carries an optionaltags?: string[]fieldPostCardrenders tags with accessible list markup (role="list"/role="listitem") and exposesshowTags/tagsClassNameprops plus tags on the headlessrenderPostrender prop- Server-side
fetchPostexpands bothfree_web_contentandtagsby default
v0.4.1
- Accessibility: aria attributes (
aria-required,aria-invalid,aria-describedby) andautocompletetokens added acrossSubscriptionFormand the generated subscribe templates (subscribe-cta,subscribe-step-two) expandonusePosts/usePostsQuery: list-sideexpandparameter forwarded to the beehiiv API on every paginated load-more, so post content stays populated across all pages- SubscribeCTA template fix: accesses unwrapped
SubscriptionInfofields directly (result?.publication_id) to match the unwrappedsubscribeActionresponse shape
v0.4.0
defaultPublicationIddual-signature pattern extended to all 9 endpoint classes- Every method now supports
method(data)(uses default) ormethod(pubId, data)(explicit override) - Endpoints: segments, automations, webhooks, posts, custom-fields, referrals, subscriptions, automation-journeys
- Every method now supports
- New endpoint:
AutomationJourneysEndpointwithcreate()andget()methods - New methods:
PostsEndpoint.aggregateStats(),SegmentsEndpoint.create(),AutomationsEndpoint.get(),AutomationsEndpoint.listEmails() GetPostOptions:PostsEndpoint.get()now accepts anexpandarray to request expanded content fields- New types:
AutomationJourneyInfo,PostAggregateStats,AutomationEmailInfo, and more - Merged all v0.3.7--v0.3.14 fixes into the v0.4.0 codebase
- 467 tests passing across 42 test files
v0.3.14
- Defensive guards in
usePostshook for API responses missingdataorpaginationfields - Prevents runtime crashes when the beehiiv API returns incomplete responses
v0.3.13
- BeehiivClient import path fix: All CLI-generated templates now import
BeehiivClientfrombeehiiv-react/server(wasbeehiiv-react) - UTM fields in subscribeAction: Generated server actions now accept and pass through
utmSource,utmMedium,utmChannel,utmCampaign,referringSite,reactivateExisting utm_channeltype: Added toSubscriptionInfoandCreateSubscriptionRequest
v0.3.12
- Fixed 5 scaffold template bugs surfaced in generated projects:
publicationIdnow wired through correctly in generated server actions and API routes- Generated
BeehiivCustomFieldsimport path matches the custom-fields generator output expandparameter properly passed through to the posts list/get endpointsPostContenttype is exported and aligned acrossPostContent/PostContentRenderercomponents and thepostsendpointusePostscursor pagination fixed (load-more no longer clobbers prior pages)
v0.3.11
- Republish of v0.3.10 with the v0.3.6–v0.3.10 changelog entries now included in the tarball
v0.3.10
- New CLI-generated subscribe flow with persistence and analytics
- Two-step subscribe component (
SubscribeCTA+SubscribeStepTwo) with a sharedSubscribeWrapper - Subscriber identity persisted to cookies and
localStorageso returning visitors skip the form useSubscriberStatushook generated alongside the components for status-aware UI- Auto-hides CTAs once a visitor is subscribed
- Emits
dataLayerevents (subscribe_view,subscribe_step_one,subscribe_complete) for GTM/analytics integration
- Two-step subscribe component (
- New generated
analytics.tshelper andposts-route.tsAPI route templates PostListaccepts anonSubscribeClickprop for inline subscribe entry points
v0.3.9
- Generated
actions.tstemplate now includes the missingenrichSubscriptionActionserver action
v0.3.8
- Reverted the ESM CLI build that broke
__dirnameresolution; CLI is back on CJS with the version injected at build time via tsupdefine
v0.3.7
- CLI reads its version dynamically from
package.jsoninstead of a hardcoded string
v0.3.6
- Split server and client exports so the package no longer crosses Next.js RSC boundaries (fixes "Server Components cannot import client components" error)
v0.3.5
- Fixed 7 TypeScript errors in generated API route templates
SubscriptionsEndpointnow accepts an optionaldefaultPublicationIdfrom client config; all methods support calling without an explicit publication ID argument- Added
get()alias onSubscriptionsEndpoint(maps togetById) - Added
emailfilter toListSubscriptionsOptions - Custom fields generator now writes to
lib/beehiiv/beehiiv-custom-fields.ts(fixes TS2307 import path mismatch in generated server actions)
- Added
-v/--versionCLI flag (see CLI) - Added
SKILL.mdand AI coding tool context files (Cursor, Copilot, Windsurf, Cline, Aider, AGENTS.md)
v0.3.4
- Build pipeline injects
"use client"directives via tsuponSuccesshook (resolves Rollup stripping issue)
v0.3.3
- Added
"use client"directives to all client-facing source files
v0.3.2
README.mdandCLAUDE.mdincluded in npm package files- Peer dependency install documentation improved
v0.3.1
- Fixed ENOENT crash on
npx beehiiv-react init(CLI template path resolution) - Fixed default import for
beehiiv.config - Fixed Next.js 15 compatibility: async
paramsin generated API route handlers
v0.3.0
v0.3.0 delivers full beehiiv API v2 coverage, two new React hooks, a first-class TanStack Query adapter, and React Server Component utilities.
4 New Server-Side Endpoints
The BeehiivClient now exposes 8 endpoint namespaces (up from 4 in v0.2.x):
Webhooks
import { BeehiivClient } from 'beehiiv-react/server';
const client = new BeehiivClient({ apiKey: process.env.BEEHIIV_API_KEY! });
// List all webhooks
const { data: webhooks } = await client.webhooks.list('pub_abc');
// Create a webhook
const { data: webhook } = await client.webhooks.create('pub_abc', {
url: 'https://example.com/webhook',
events: ['subscription.created', 'post.published'],
});
// Send a test event
await client.webhooks.test('pub_abc', webhook.id);Segments
// List segments
const { data: segments } = await client.segments.list('pub_abc');
// List members of a segment
const { data: members } = await client.segments.listMembers('pub_abc', 'seg_123');Automations
// List automations
const { data: automations } = await client.automations.list('pub_abc');
// List journeys for an automation
const { data: journeys } = await client.automations.listJourneys('pub_abc', 'auto_456');Referrals
// Get the referral program
const { data: program } = await client.referrals.getProgram('pub_abc');
// Get a subscriber's referral stats
const { data: stats } = await client.referrals.getSubscriberStats('pub_abc', 'sub_789');beehiiv-react/query -- TanStack Query Adapter
Prerequisites: Install
@tanstack/react-querybefore using this sub-path:npm install @tanstack/react-query
A dedicated sub-path export that wraps every beehiiv API call in TanStack Query v5 hooks for automatic caching, deduplication, and background re-fetching.
Setup:
// app/providers.tsx
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BeehiivProvider } from 'beehiiv-react';
const queryClient = new QueryClient();
export function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<BeehiivProvider
publicationId={process.env.NEXT_PUBLIC_BEEHIIV_PUBLICATION_ID!}
apiUrl="/api/beehiiv"
>
{children}
</BeehiivProvider>
</QueryClientProvider>
);
}Usage:
'use client';
import { usePostsQuery, useSubscribeMutation } from 'beehiiv-react/query';
export function PostsFeed() {
const { data, isLoading } = usePostsQuery({ status: 'confirmed', limit: 10 });
const subscribe = useSubscribeMutation();
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{data?.data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}beehiiv-react/server -- React Server Component Utilities
A sub-path export providing RSC-compatible helpers. No hooks, no client-side state -- just plain async functions safe for Server Components, Route Handlers, and Server Actions.
// app/posts/page.tsx (Next.js Server Component)
import { createBeehiivClient, fetchPosts } from 'beehiiv-react/server';
export default async function PostsPage() {
const client = createBeehiivClient(); // reads BEEHIIV_API_KEY from env
const posts = await fetchPosts(client, process.env.BEEHIIV_PUB_ID!, {
status: 'confirmed',
limit: 20,
});
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}Additional server fetchers: fetchPost, fetchSubscribers, fetchSubscription, fetchPublications, fetchCustomFields, fetchWebhooks, fetchSegments.
Migration from v0.2.x
All v0.2.x APIs remain stable and unchanged. v0.3.0 is a purely additive release:
- Existing hooks (
useSubscribe,useSubscription,useCustomFields,usePosts,usePost, etc.) are unchanged. - Existing client endpoints (
subscriptions,customFields,publications,posts) are unchanged. - The main
beehiiv-reactimport path works exactly as before. - New features are available via the main import path (new endpoints and hooks) or the new sub-path imports (
beehiiv-react/query,beehiiv-react/server). @tanstack/react-query(>=5.0.0) is an optional peer dependency -- only needed if you import frombeehiiv-react/query.
API Reference
Hooks
| Hook | Description |
|------|-------------|
| useBeehiiv() | Access the beehiiv context (publication ID, API URL) |
| useSubscribe() | Subscribe an email with custom fields and UTM tracking |
| useSubscription() | Fetch and manage an existing subscription |
| useCustomFields() | Retrieve custom field definitions |
| usePosts() | Paginated post list with audience/status filters |
| usePost() | Fetch a single post by ID |
| useSubscriberAccess() | Resolve subscriber tier + status into an access result |
| usePostAccess() | Fetch post + subscriber, returns combined { post, canView } |
| useSubscribers() | Fetch and paginate through subscribers |
| usePublications() | Fetch all accessible publications |
| useSubscriberProfile() | Full subscription record with isPremium and isActive flags |
| useSubscriberTier() | Lightweight tier flags without the full subscription record |
| useTiers() | Paginated tier list with type/active filtering |
| useTier() | Single tier by ID |
| useAuthors() | Paginated author list |
| useAuthor() | Single author by ID |
| useBulkUpdateJob() | Track bulk update job with polling |
| useEngagements() | Engagement metrics by date range |
| useAutomations() | Automation list and detail |
| useWebhooks() | Webhook list and detail |
| useSegments() | Segment list and detail |
| useReferrals() | Referral program and subscriber stats |
Components
| Component | Description |
|-----------|-------------|
| <BeehiivProvider> | Context provider for beehiiv configuration |
| <SubscriptionForm> | Pre-built subscription form with headless mode |
| <PostCard> | Displays a single post with thumbnail, badge, title, subtitle, date |
| <PostList> | Paginated list of posts with load-more, skeleton loading, empty state |
| <PostContentRenderer> | Renders HTML or JSON post content with sanitizer hook |
| <GatedContent> | Declarative wrapper for subscriber-gated content |
| <PremiumContent> | Opinionated premium gate with upgradePrompt render prop |
| <SubscriberBadge> | Renders a tier badge with optional headless mode |
| <TierBadge> | Renders a tier name badge with free/premium styling |
Types
All types are exported from the package root:
import type {
SubscriptionInfo,
PublicationInfo,
CustomFieldInfo,
PostInfo,
PostContent,
PostAudience,
AccessResult,
WebhookInfo,
BeehiivApiConfig,
BeehiivConfig,
Tier,
TierType,
Author,
BulkSubscriptionUpdateJob,
EngagementMetrics,
} from 'beehiiv-react';Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Write tests for your changes
- Ensure all tests pass (
npm test) - Commit your changes (
git commit -am 'Add my feature') - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
Please follow the existing code style and include tests for any new functionality.
License
Released under the MIT License.
