Implementation:Helicone Helicone UseFreeTierLimit
| Knowledge Sources | |
|---|---|
| Domains | Feature Access, Billing |
| Last Updated | 2026-02-14 06:32 GMT |
Overview
A React hook that checks feature usage against subscription plan limits, determining whether a user can create new items and computing remaining quota and upgrade messaging.
Description
The useFeatureLimit hook enforces subscription-based usage caps across the Helicone dashboard UI. It combines the access check from useHasAccess with the limit configuration from FREE_TIER_CONFIG to compute whether the user can create additional items for a given feature.
Resolution logic:
- Calls
useHasAccess(feature)to determine if the user has paid-tier access. - Looks up the limit configuration from
FREE_TIER_CONFIG.features[feature], checking either asubfeature-specific config or themainfeature config. - If no config is found, returns unlimited access (
remainingItems: Infinity,canCreate: true). - If config exists, computes:
freeLimit-- The maximum number of items allowed, fromconfig.getLimit().canCreate--trueif the user has paid access OR currentitemCountis belowfreeLimit.remainingItems--Math.max(0, freeLimit - itemCount).upgradeMessage-- A message from the config or a default upgrade prompt.
The return type is discriminated: FeatureLimitResult (with featureConfig) when no subfeature is specified, or SubfeatureLimitResult (with subfeatureConfig) when a subfeature is provided.
Usage
Use this hook in any UI component that creates feature-limited items (prompts, experiments, datasets, etc.) to check if the user has remaining quota before showing create actions, and to display appropriate upgrade messaging when limits are reached.
Code Reference
Source Location
- Repository: Helicone
- File: web/hooks/useFreeTierLimit.ts
Signature
export interface BaseLimitResult {
hasAccess: boolean;
remainingItems: number;
upgradeMessage: string;
freeLimit: number;
canCreate: boolean;
}
export interface FeatureLimitResult extends BaseLimitResult {
featureConfig: LimitConfig | null;
}
export interface SubfeatureLimitResult extends BaseLimitResult {
subfeatureConfig: LimitConfig | null;
}
export type LimitResult = FeatureLimitResult | SubfeatureLimitResult;
export function useFeatureLimit(
feature: FeatureId,
itemCount: number,
subfeature?: SubfeatureId | undefined
): LimitResult;
Import
import { useFeatureLimit, FeatureLimitResult } from "@/hooks/useFreeTierLimit";
I/O Contract
Input (Parameters)
| Parameter | Type | Description |
|---|---|---|
feature |
FeatureId |
The feature identifier to check limits for |
itemCount |
number |
Current number of items the user has created |
subfeature |
undefined | Optional subfeature for more granular limit checks |
Output (Return)
| Field | Type | Description |
|---|---|---|
hasAccess |
boolean |
Whether the user has paid-tier access (bypasses limits) |
remainingItems |
number |
Number of items the user can still create (Infinity if unlimited)
|
upgradeMessage |
string |
Message to display when prompting the user to upgrade |
freeLimit |
number |
Maximum items allowed on the free tier (Infinity if no limit)
|
canCreate |
boolean |
Whether the user can create another item (has access OR below limit) |
featureConfig / subfeatureConfig |
null | The resolved limit configuration, or null if none exists
|
Usage Examples
import { useFeatureLimit } from "@/hooks/useFreeTierLimit";
function PromptsList({ prompts }) {
const limit = useFeatureLimit("prompts", prompts.length);
return (
<div>
<h2>Prompts ({prompts.length} / {limit.freeLimit === Infinity ? "unlimited" : limit.freeLimit})</h2>
{!limit.canCreate && (
<div className="bg-muted p-4 rounded-lg">
<p>{limit.upgradeMessage}</p>
<UpgradeButton />
</div>
)}
<button disabled={!limit.canCreate}>
Create Prompt
</button>
{limit.remainingItems < 3 && limit.remainingItems > 0 && (
<p className="text-muted-foreground">
{limit.remainingItems} prompt(s) remaining on free tier
</p>
)}
</div>
);
}