Introducing Socket Firewall: Free, Proactive Protection for Your Software Supply Chain.Learn More
Socket
Book a DemoInstallSign in
Socket

@subscribe.dev/react

Package Overview
Dependencies
Maintainers
1
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@subscribe.dev/react

React hooks and components for SubscribeDev - provides context and hooks for managing AI predictions with billing and rate limiting

Source
npmnpm
Version
0.0.75
Version published
Weekly downloads
638
-89.48%
Maintainers
1
Weekly downloads
 
Created
Source

@subscribe.dev/react

React hooks and provider for Subscribe.dev - Build AI-powered applications with integrated authentication, billing, storage, and 100+ curated AI models.

Subscribe.dev provides a secure, production-ready platform that leverages industry-standard services: Stripe handles all payment processing (ensuring zero exposure of payment data), Clerk provides authentication infrastructure, and our platform manages AI model access and usage tracking.

Installation

npm install @subscribe.dev/react
# or
yarn add @subscribe.dev/react
# or
bun add @subscribe.dev/react

Provider Usage

The SubscribeDevProvider is a React context provider that wraps your application. It provides the necessary context for the useSubscribeDev hook to function correctly.

To use it, simply wrap it at the root level around your React application:

import { SubscribeDevProvider } from '@subscribe.dev/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

export default function Root() {
    return (
        <SubscribeDevProvider projectId={/*optional*/}>
            <App />
        </SubscribeDevProvider>
    );
}

and call the useSubscribeDev hook somewhere:

import {SubscribeDevProvider, useSubscribeDev} from '@subscribe.dev/react';
import {useState} from 'react';

export default function App() {
    const {
        isSignedIn, // indicates auth status
        signIn, // a function to authenticate
        client, // an instance of the SubscribeDevClient
        user, // the signed in user or null
        usage, // an object showing the consumed credits and balance for the user
        subscribe, // a function to trigger the subscription flow
        subscriptionStatus, // an object indicating subscription status
        useStorage, // a React hook to store key-value data for the user
    } = useSubscribeDev();
    const [email, setEmail] = useState('');

    // ... your component logic
}

Hook Return Values

When you call useSubscribeDev(), you get the following values:

  • isSignedIn: boolean - indicates whether the user is authenticated
  • signIn: () => void - function to trigger the authentication flow
  • client: SubscribeDevClient - instance with a run() method for executing AI models
  • user: UserObject | null - the current user object, or null if not authenticated
  • usage: UsageInfo - credits used and remaining for the user (updates automatically)
  • subscribe: () => void - triggers the subscription flow in an iframe
  • subscriptionStatus: SubscriptionStatus - indicates subscription tier and status
  • useStorage: <T>(key: string) => [T, (value: T) => void] - hook for persisting user data across sessions

The hook provides the following types: <TYPE_EXAMPLES>

export type RunParameters = {
    input: {
        width?: number; // for image models only -- defaults to 1024
        height?: number  // for image models only -- defaults to 1024,
        image?: string // base64 encoded or a URL to an image
    } & ({
        prompt?: string // for image models and text completion models
    } | {
        messages: Array<{ role: string, content: string } | {
            type: 'text' | 'image_url' // for multimodal message contnt
            text?: string
            image_url?: {
                url: string
                detail?: 'low' | 'high' | 'auto'
            }
		}> // for text completion models only
    }),
    response_format: { // for text completion models only
        type: 'json_object' // to request any JSON back
    } | {
        type: 'json_schema' // to request an OpenAPI JSON Schema-compliant object
        json_schema: {
            name: string
            strict?: boolean
            schema: Record<string, unknown>
        }
    } | ZodObject // Also accept native Zod schemas directly as the `response_format`
}

type RunOutput = {
    output: Array<string | Record<string, any>> // for text completion models, only one element representing the completed text or JSON.  For image models, generally a URL, sometimes many URLs if there are multiple images generated.
}

type UserObject = {
    id: string
    email: string
    name: string | null
}

type SubscriptionStatus = {
    hasActiveSubscription: boolean
    plan?: {
        id: string
        name: string
        price: number
    }
    status: 'active' | 'inactive' | 'cancelled' | 'expired' | 'none'
}

type UsageInfo = {
    allocatedCredits: number
    usedCredits: number
    remainingCredits: number
}

</TYPE_EXAMPLES>

The client.run() method signature:

run: async (model: string, input: RunParameters) => Promise<{ output: RunOutput }>

Usage Guidance

  • Do not wrap your application in another Clerk provider, instead, using the one from SubscribeDev
  • We should make sure that the user isSignedIn before using SubscribeDev functions-- if they aren't, call signIn
  • Do not use the useSubscribeDev hook outside of the SubscribeDevProvider context, as it will throw an error.
  • You do not need to supply a projectId, but this will result in using a demo project, which is for development.

Client

Generally the client is mostly just used for its function run which executes AI requests against your project and users' allocated credits.

The client has lower-level functions, but the React hooks mostly fill the role of calling these, and use the client under the hood. There is generally no need to use the client, but it exposed from the provider in cases of specialized use. The documentation for the client is available here.

Authentication

We embed a Clerk provider in the SubscribeDevProvider, utilizing the open-source Clerk authentication infrastructure. We have not rolled our own authentication system - instead, we wrap and extend Clerk's proven functionality to integrate seamlessly with Subscribe.dev services.

The authentication flow can sense its own token and embeds it as the Bearer ... token for our client requests. Beyond triggering the sign-in flow, you do not need to implement anything special to authenticate users. Clerk handles all authentication security, session management, and user identity verification.

Security & Privacy FAQ

Q: Does Subscribe.dev ever see my users' credit card information?
A: No. All payment processing is handled directly by Stripe. Subscribe.dev never receives or stores payment data.

Q: Do you manage user passwords or authentication data?
A: No. All authentication is handled by Clerk's infrastructure. Subscribe.dev only receives authenticated user tokens.

Q: What happens if Stripe or Clerk services are down?
A: Payment and authentication flows would be temporarily unavailable, but your AI model usage would continue to work for already-authenticated users with existing credits.

Error Handling

All Subscribe.dev functions can throw errors, which you can catch using standard JavaScript error handling:

import { useSubscribeDev } from '@subscribe.dev/react';

function MyComponent() {
    const { client } = useSubscribeDev();
    
    const handleAIRequest = async () => {
        try {
            const result = await client.run('openai/gpt-4o', {
                input: { prompt: "Hello, world!" }
            });
            console.log(result.output[0]);
        } catch (error) {
            // Errors include type, message, and relevant details
            if (error.type === 'insufficient_credits') {
                console.error('Not enough credits:', error.message);
                // Handle insufficient credits (e.g., prompt user to subscribe)
            } else if (error.type === 'rate_limit_exceeded') {
                console.error('Rate limited:', error.retryAfter);
                // Handle rate limiting (e.g., show retry timer)
            } else {
                console.error('AI request failed:', error.message);
            }
        }
    };
    
    return <button onClick={handleAIRequest}>Run AI Model</button>;
}

For detailed error types and handling strategies, refer to the error documentation.

Development & Debugging

Subscribe.dev is designed to work seamlessly with your existing development workflow:

  • Console Logging: Use your normal browser dev tools to see logs, network requests, and debug information
  • Network Tab: Monitor API calls to Subscribe.dev services in your browser's network inspector
  • React DevTools: The provider and hooks work naturally with React DevTools for state inspection
  • Error Boundaries: Wrap components using Subscribe.dev hooks in React Error Boundaries for graceful error handling

Observability & Platform Dashboard

For production applications, comprehensive observability is available through the Subscribe.dev platform dashboard:

  • Visit platform.subscribe.dev to access detailed analytics
  • Metrics & Usage: View generation counts, model usage patterns, and performance data
  • Cost Analysis: Track spending across models and users with detailed breakdowns
  • Real-time Monitoring: Monitor your application's AI usage in real-time
  • Error Tracking: Investigate and debug issues with comprehensive error logs

The React client is designed for embedding in user-facing applications and only exposes public information and developer-friendly errors. For administrative access, team management, and detailed platform insights, use the web dashboard.

Credits and Usage

The usage object from the provider will update when you run requests through the SubscribeDevClient. If we listen to the value from the provider hook, it should update automatically, but it may need to be present in e.g. the dependency array of a useEffect.

Subscribing / Managing Subscription

Calling subscribe() is a magic function that will guide the user through a subscription flow powered by Stripe and allow them to manage their current subscription. All payment processing is handled securely by Stripe - Subscribe.dev has zero exposure to payment data, ensuring maximum security and compliance.

The subscription status will automatically update when changed, and we can trust the value from the provider.

User Object

We can use the user object to show the user's name, or profile badge, etc. On signing in, this will update to populated value, but may be empty before authentication.

Storage

The useStorage hook should be called when we want to persist data at a component-level or application-level for users beyond their current session. This data is saved on the backend of subscribe.dev and will persist across devices if the same authentication method is used.

Usage Example:

type AppState = {
    lastState: string,
    counter: number
};

export function ServerPersistedCounter(props) {
    const [storedObject, setStoredObject] = useStorage<AppState>('app-state');

    const updateCounter = () => {
        setStoredObject({
            ...storedObject,
            counter: (storedObject?.counter || 0) + 1
        })
    }

    return (
        <div>
            <p>Counter: {storedObject?.counter || 0}</p>
            <button onClick={updateCounter}>Click Me To Count</button>
        </div>
    );
}

Different Model Example Requests:

// Standard usage, text completion:
const result = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    }
});
console.log("Output Joke: ", result.output[0]);

// Standard usage, JSON completion:
const {output} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI that has a property `setup` and `punchline`"
    },
    response_format: {
        type: 'json_object'
    }
});
console.log("Output Joke JSON: ", output[0]);

// JSON Schema completion:
const {output: [jokeResponseJson]} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    },
    response_format: {
        type: 'json_schema',
        json_schema: {
            name: 'Joke',
            strict: true,
            schema: {
                type: 'object',
                properties: {
                    setup: {type: 'string'},
                    punchline: {type: 'string'}
                },
                required: ['setup', 'punchline']
            }
        }
    }
});

// Zod Usage
const jokeSchema = z.object({
    setup: z.string(),
    punchline: z.string()
});

const {output: [jokeResponseZodJson]} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    },
    response_format: jokeSchema // directly passing a Zod schema
});

console.log("Output Joke JSON Schema: ", jokeResponseZodJson);

// multimodal usage:
const {output: [multimodalResponse]} = await client.run('openai/gpt-4o', {
    input: {
        messages: [
            {role: "system", content: "You identify stuff."},
            {role: 'user', content: 'What is this image?'},
            {type: 'image_url', image_url: {url: 'https://example.com/image.jpg'}}
        ]
    }
});
console.log("Multimodal Response: ", multimodalResponse);

// generate an image of a dog:
const {output: [cuteDog]} = await cli# @subscribe.dev/react

React hooks and provider for Subscribe.dev - Build AI-powered applications with integrated authentication, billing, storage, and 100+ curated AI models.

Subscribe.dev provides a secure, production-ready platform that leverages industry-standard services: **Stripe** handles all payment processing (ensuring zero exposure of payment data), **Clerk** provides authentication infrastructure, and our platform manages AI model access and usage tracking.

## Installation

```bash
npm install @subscribe.dev/react
# or
yarn add @subscribe.dev/react
# or
bun add @subscribe.dev/react

Provider Usage

The SubscribeDevProvider is a React context provider that wraps your application. It provides the necessary context for the useSubscribeDev hook to function correctly.

To use it, simply wrap it at the root level around your React application:

import { SubscribeDevProvider } from '@subscribe.dev/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

export default function Root() {
    return (
        <SubscribeDevProvider projectId={/*optional*/}>
            <App />
        </SubscribeDevProvider>
    );
}

and call the useSubscribeDev hook somewhere:

import {SubscribeDevProvider, useSubscribeDev} from '@subscribe.dev/react';
import {useState} from 'react';

export default function App() {
    const {
        isSignedIn, // indicates auth status
        signIn, // a function to authenticate
        client, // an instance of the SubscribeDevClient
        user, // the signed in user or null
        usage, // an object showing the consumed credits and balance for the user
        subscribe, // a function to trigger the subscription flow
        subscriptionStatus, // an object indicating subscription status
        useStorage, // a React hook to store key-value data for the user
    } = useSubscribeDev();
    const [email, setEmail] = useState('');

    // ... your component logic
}

Hook Return Values

When you call useSubscribeDev(), you get the following values:

  • isSignedIn: boolean - indicates whether the user is authenticated
  • signIn: () => void - function to trigger the authentication flow
  • client: SubscribeDevClient - instance with a run() method for executing AI models
  • user: UserObject | null - the current user object, or null if not authenticated
  • usage: UsageInfo - credits used and remaining for the user (updates automatically)
  • subscribe: () => void - triggers the subscription flow in an iframe
  • subscriptionStatus: SubscriptionStatus - indicates subscription tier and status
  • useStorage: <T>(key: string) => [T, (value: T) => void] - hook for persisting user data across sessions

The hook provides the following types: <TYPE_EXAMPLES>

export type RunParameters = {
    input: {
        width?: number; // for image models only -- defaults to 1024
        height?: number  // for image models only -- defaults to 1024,
        image?: string // base64 encoded or a URL to an image
    } & ({
        prompt?: string // for image models and text completion models
    } | {
        messages: Array<{ role: string, content: string } | {
            type: 'text' | 'image_url' // for multimodal message contnt
            text?: string
            image_url?: {
                url: string
                detail?: 'low' | 'high' | 'auto'
            }
		}> // for text completion models only
    }),
    response_format: { // for text completion models only
        type: 'json_object' // to request any JSON back
    } | {
        type: 'json_schema' // to request an OpenAPI JSON Schema-compliant object
        json_schema: {
            name: string
            strict?: boolean
            schema: Record<string, unknown>
        }
    } | ZodObject // Also accept native Zod schemas directly as the `response_format`
}

type RunOutput = {
    output: Array<string | Record<string, any>> // for text completion models, only one element representing the completed text or JSON.  For image models, generally a URL, sometimes many URLs if there are multiple images generated.
}

type UserObject = {
    id: string
    email: string
    name: string | null
}

type SubscriptionStatus = {
    hasActiveSubscription: boolean
    plan?: {
        id: string
        name: string
        price: number
    }
    status: 'active' | 'inactive' | 'cancelled' | 'expired' | 'none'
}

type UsageInfo = {
    allocatedCredits: number
    usedCredits: number
    remainingCredits: number
}

</TYPE_EXAMPLES>

The client.run() method signature:

run: async (model: string, input: RunParameters) => Promise<{ output: RunOutput }>

Usage Guidance

  • Do not wrap your application in another Clerk provider, instead, using the one from SubscribeDev
  • We should make sure that the user isSignedIn before using SubscribeDev functions-- if they aren't, call signIn
  • Do not use the useSubscribeDev hook outside of the SubscribeDevProvider context, as it will throw an error.
  • You do not need to supply a projectId, but this will result in using a demo project, which is for development.

Client

Generally the client is mostly just used for its function run which executes AI requests against your project and users' allocated credits.

The client has lower-level functions, but the React hooks mostly fill the role of calling these, and use the client under the hood. There is generally no need to use the client, but it exposed from the provider in cases of specialized use. The documentation for the client is available here.

Authentication

We embed a Clerk provider in the SubscribeDevProvider, utilizing the open-source Clerk authentication infrastructure. We have not rolled our own authentication system - instead, we wrap and extend Clerk's proven functionality to integrate seamlessly with Subscribe.dev services.

The authentication flow can sense its own token and embeds it as the Bearer ... token for our client requests. Beyond triggering the sign-in flow, you do not need to implement anything special to authenticate users. Clerk handles all authentication security, session management, and user identity verification.

Security & Privacy FAQ

Q: Does Subscribe.dev ever see my users' credit card information?
A: No. All payment processing is handled directly by Stripe. Subscribe.dev never receives or stores payment data.

Q: Do you manage user passwords or authentication data?
A: No. All authentication is handled by Clerk's infrastructure. Subscribe.dev only receives authenticated user tokens.

Q: What happens if Stripe or Clerk services are down?
A: Payment and authentication flows would be temporarily unavailable, but your AI model usage would continue to work for already-authenticated users with existing credits.

Error Handling

All Subscribe.dev functions can throw errors, which you can catch using standard JavaScript error handling:

import { useSubscribeDev } from '@subscribe.dev/react';

function MyComponent() {
    const { client } = useSubscribeDev();
    
    const handleAIRequest = async () => {
        try {
            const result = await client.run('openai/gpt-4o', {
                input: { prompt: "Hello, world!" }
            });
            console.log(result.output[0]);
        } catch (error) {
            // Errors include type, message, and relevant details
            if (error.type === 'insufficient_credits') {
                console.error('Not enough credits:', error.message);
                // Handle insufficient credits (e.g., prompt user to subscribe)
            } else if (error.type === 'rate_limit_exceeded') {
                console.error('Rate limited:', error.retryAfter);
                // Handle rate limiting (e.g., show retry timer)
            } else {
                console.error('AI request failed:', error.message);
            }
        }
    };
    
    return <button onClick={handleAIRequest}>Run AI Model</button>;
}

For detailed error types and handling strategies, refer to the error documentation.

Development & Debugging

Subscribe.dev is designed to work seamlessly with your existing development workflow:

  • Console Logging: Use your normal browser dev tools to see logs, network requests, and debug information
  • Network Tab: Monitor API calls to Subscribe.dev services in your browser's network inspector
  • React DevTools: The provider and hooks work naturally with React DevTools for state inspection
  • Error Boundaries: Wrap components using Subscribe.dev hooks in React Error Boundaries for graceful error handling

Observability & Platform Dashboard

For production applications, comprehensive observability is available through the Subscribe.dev platform dashboard:

  • Visit platform.subscribe.dev to access detailed analytics
  • Metrics & Usage: View generation counts, model usage patterns, and performance data
  • Cost Analysis: Track spending across models and users with detailed breakdowns
  • Real-time Monitoring: Monitor your application's AI usage in real-time
  • Error Tracking: Investigate and debug issues with comprehensive error logs

The React client is designed for embedding in user-facing applications and only exposes public information and developer-friendly errors. For administrative access, team management, and detailed platform insights, use the web dashboard.

Credits and Usage

The usage object from the provider will update when you run requests through the SubscribeDevClient. If we listen to the value from the provider hook, it should update automatically, but it may need to be present in e.g. the dependency array of a useEffect.

Subscribing / Managing Subscription

Calling subscribe() is a magic function that will guide the user through a subscription flow powered by Stripe and allow them to manage their current subscription. All payment processing is handled securely by Stripe - Subscribe.dev has zero exposure to payment data, ensuring maximum security and compliance.

The subscription status will automatically update when changed, and we can trust the value from the provider.

User Object

We can use the user object to show the user's name, or profile badge, etc. On signing in, this will update to populated value, but may be empty before authentication.

Storage

The useStorage hook should be called when we want to persist data at a component-level or application-level for users beyond their current session. This data is saved on the backend of subscribe.dev and will persist across devices if the same authentication method is used.

Usage Example:

type AppState = {
    lastState: string,
    counter: number
};

export function ServerPersistedCounter(props) {
    const [storedObject, setStoredObject] = useStorage<AppState>('app-state');

    const updateCounter = () => {
        setStoredObject({
            ...storedObject,
            counter: (storedObject?.counter || 0) + 1
        })
    }

    return (
        <div>
            <p>Counter: {storedObject?.counter || 0}</p>
            <button onClick={updateCounter}>Click Me To Count</button>
        </div>
    );
}

Different Model Example Requests:

// Standard usage, text completion:
const result = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    }
});
console.log("Output Joke: ", result.output[0]);

// Standard usage, JSON completion:
const {output} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI that has a property `setup` and `punchline`"
    },
    response_format: {
        type: 'json_object'
    }
});
console.log("Output Joke JSON: ", output[0]);

// JSON Schema completion:
const {output: [jokeResponseJson]} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    },
    response_format: {
        type: 'json_schema',
        json_schema: {
            name: 'Joke',
            strict: true,
            schema: {
                type: 'object',
                properties: {
                    setup: {type: 'string'},
                    punchline: {type: 'string'}
                },
                required: ['setup', 'punchline']
            }
        }
    }
});

// Zod Usage
const jokeSchema = z.object({
    setup: z.string(),
    punchline: z.string()
});

const {output: [jokeResponseZodJson]} = await client.run('openai/gpt-4o', {
    input: {
        prompt: "Tell me a joke about AI"
    },
    response_format: jokeSchema // directly passing a Zod schema
});

console.log("Output Joke JSON Schema: ", jokeResponseZodJson);

// multimodal usage:
const {output: [multimodalResponse]} = await client.run('openai/gpt-4o', {
    input: {
        messages: [
            {role: "system", content: "You identify stuff."},
            {role: 'user', content: 'What is this image?'},
            {type: 'image_url', image_url: {url: 'https://example.com/image.jpg'}}
        ]
    }
});
console.log("Multimodal Response: ", multimodalResponse);

// generate an image of a dog:
const {output: [cuteDog]} = await client.run('black-forest-labs/flux-schnell', {
    input: {
        prompt: 'a cute dog',
        width: 512,
        height: 512
    }
});
console.log("Generated Dog Image URL: ", cuteDog);

// generate an image with a reference image (only supported by some image-to-image models):
const {output: [dogTwin]} = await client.run('black-forest-labs/flux-schnell', {
    input: {
        prompt: 'another cute dog that looks like this dog',
        image: "https://example.com/dog.jpg" // can be base64 encoded as well
    }
});
console.log("Generated Dog Twin Image URL: ", dogTwin);
```ent.run('black-forest-labs/flux-schnell', {
    input: {
        prompt: 'a cute dog',
        width: 512,
        height: 512
    }
});
console.log("Generated Dog Image URL: ", cuteDog);

// generate an image with a reference image (only supported by some image-to-image models):
const {output: [dogTwin]} = await client.run('black-forest-labs/flux-schnell', {
    input: {
        prompt: 'another cute dog that looks like this dog',
        image: "https://example.com/dog.jpg" // can be base64 encoded as well
    }
});
console.log("Generated Dog Twin Image URL: ", dogTwin);

Keywords

react

FAQs

Package last updated on 17 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts