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.
- 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
npm install beehiiv-reactIf 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.
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."
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
Re-running init prompts before overwriting any file you may have customized.
Security note: the generated
GET /api/beehiiv/subscriberoute looks up subscriptions by email and, as scaffolded, is publicly accessible. Before production, add an auth check or rate limiting (the generated file includes a TODO with an example guard) so visitors can't enumerate your subscribers.
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).
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.
Print the installed version:
npx beehiiv-react -v
# or
npx beehiiv-react --version
# beehiiv-react/0.4.2Wrap 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>
);
}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>
);
}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>
);
}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>
);
}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"
/>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>
)}
/>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.
import { usePosts, usePost } from 'beehiiv-react';
// List posts — filter by audience and status
const { posts, isLoading, hasMore, loadMore } = usePosts({
audience: 'free', // 'free' | 'premium' | 'both' | 'all'
status: 'confirmed',
});
// Single post
const { post, isLoading } = usePost({ id: 'post_abc123' });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)}
/>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',
});The canViewContent(tier, status, audience) utility resolves subscriber access:
'all'audience: always accessible (SDK-only alias for public content — the beehiiv API never returns it)'free'audience: requires active subscription (any tier)'both'audience: sent to both free and premium audiences — requires active subscription (any tier)'premium'audience: requires active premium subscription
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.
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>
);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();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'} />
)}
/>Manage subscription tiers (free and premium) for your publication.
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>
);
}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>;
}import { TierBadge } from 'beehiiv-react';
<TierBadge tier={tier} />
{/* Headless mode */}
<TierBadge tier={tier} renderBadge={({ name, type }) => (
<span className={type === 'premium' ? 'gold' : 'gray'}>{name}</span>
)} />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;
}import { BeehiivClient } from 'beehiiv-react/server';
const client = new BeehiivClient({ apiKey: '...', publicationId: '...' });
// The API responds with { message, import_id }
const { import_id } = await client.bulkSubscriptions.create({
subscriptions: [
{ email: '[email protected]', utm_source: 'import' },
{ email: '[email protected]' },
],
});// Update subscriptions in bulk — responds with { data: { subscription_update_id } }
await client.bulkSubscriptionUpdates.bulkUpdateFields({
subscriptions: [
{ subscription_id: 'sub_1', custom_fields: [{ name: 'plan', value: 'enterprise' }] },
{ subscription_id: 'sub_2', tier: 'premium' },
],
});
// Update subscription status in bulk — the API responds with 204 No Content
await client.bulkSubscriptionUpdates.bulkUpdateStatus({
subscription_ids: ['sub_1', 'sub_2'],
new_status: 'active',
});import { useBulkUpdateJob } from 'beehiiv-react';
function JobTracker({ jobId }: { jobId: string }) {
// Polls until the job status is 'complete' or 'failed'
const { job, isPolling, error } = useBulkUpdateJob('pub_abc', jobId, {
pollInterval: 2000,
});
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<p>Status: {job?.status}</p>
{job?.failure_reason && <p>Failed: {job.failure_reason}</p>}
{isPolling && <p>Still processing…</p>}
</div>
);
}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>
);
}These hooks provide React-friendly wrappers for resources that previously only had server-side clients.
import { useAutomations } from 'beehiiv-react';
const { automations, isLoading } = useAutomations({ status: 'active' });import { useWebhooks } from 'beehiiv-react';
const { webhooks, isLoading } = useWebhooks();import { useSegments } from 'beehiiv-react';
const { segments, isLoading } = useSegments();import { useReferrals } from 'beehiiv-react';
const { program, subscriberStats } = useReferrals({ subscriberId: 'sub_123' });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
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
- 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
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
- Defensive guards in
usePostshook for API responses missingdataorpaginationfields - Prevents runtime crashes when the beehiiv API returns incomplete responses
- 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
- 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)
- Republish of v0.3.10 with the v0.3.6–v0.3.10 changelog entries now included in the tarball
- 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
- Generated
actions.tstemplate now includes the missingenrichSubscriptionActionserver action
- Reverted the ESM CLI build that broke
__dirnameresolution; CLI is back on CJS with the version injected at build time via tsupdefine
- CLI reads its version dynamically from
package.jsoninstead of a hardcoded string
- Split server and client exports so the package no longer crosses Next.js RSC boundaries (fixes "Server Components cannot import client components" error)
- 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)
- Build pipeline injects
"use client"directives via tsuponSuccesshook (resolves Rollup stripping issue)
- Added
"use client"directives to all client-facing source files
README.mdandCLAUDE.mdincluded in npm package files- Peer dependency install documentation improved
- 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 delivers full beehiiv API v2 coverage, two new React hooks, a first-class TanStack Query adapter, and React Server Component utilities.
The BeehiivClient now exposes 8 endpoint namespaces (up from 4 in v0.2.x):
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);// 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');// 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');// 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');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>
);
}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.
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.
| 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 |
| 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 |
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';- 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.
Released under the MIT License.