npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@gadgetinc/react-chatgpt-apps

v0.3.1

Published

<div align="center"> <p> <img alt="Gadget logo" src="https://raw.githubusercontent.com/gadget-inc/js-clients/main/docs/assets/gadget-logo.png" /> </p> <p> <a href=""> <img alt="GitHub CI status" src="https://badgen.net/github/checks/ga

Readme

@gadgetinc/react-chatgpt-apps is a React library for connecting ChatGPT Apps to Gadget backend applications. It provides:

  1. A <Provider> component that automatically authenticates your ChatGPT App with your Gadget backend
  2. Easy integration with @gadgetinc/react hooks for reading and writing data
  3. Automatic token management using OpenAI's and Gadget's authentication system

When building a ChatGPT App that needs to interact with a Gadget backend, this library handles all the authentication complexity for you, allowing your React components to focus on building great user experiences.

Installation

@gadgetinc/react-chatgpt-apps is a companion package to your Gadget app's JavaScript client and @gadgetinc/react, so you need to install all three packages.

First, set up the Gadget NPM registry and install your app's client:

npm config set @gadget-client:registry https://registry.gadget.dev/npm

# then install your app's client
npm install @gadget-client/your-chatgpt-app-slug

Full installation instructions for your app's client can be found in the Gadget docs at https://docs.gadget.dev/api/<your-app-slug>/external-api-calls/installing.

Then, install the React libraries:

npm install @gadgetinc/react @gadgetinc/react-chatgpt-apps react
# or
yarn add @gadgetinc/react @gadgetinc/react-chatgpt-apps react

Setup

To use this library, wrap your ChatGPT App's React components in the Provider component from this package. The Provider automatically handles authentication with your Gadget backend using OpenAI's authentication system.

// in web/chatgpt-widgets/root.tsx
import { Provider } from "@gadgetinc/react-chatgpt-apps";
import { api } from "../api";

function App() {
  return (
    <Provider api={api}>
      <YourChatGPTAppComponents />
    </Provider>
  );
}

export default App;

That's it! The Provider component will:

  1. Automatically fetch an authentication token from OpenAI when your app loads
  2. Configure your Gadget API client to use this token for all requests
  3. Ensure all API calls wait for authentication to be ready before proceeding

Example usage

Once you've wrapped your app in the Provider, you can use all the hooks from @gadgetinc/react to interact with your Gadget backend:

import { useAction, useFindMany } from "@gadgetinc/react";
import { api } from "../../api";

function TaskList() {
  // Fetch tasks from your Gadget backend - authentication is handled automatically
  const [{ data: tasks, fetching, error }] = useFindMany(api.task, {
    select: {
      id: true,
      title: true,
      completed: true,
    },
  });

  // Set up an action to mark tasks as complete
  const [_, completeTask] = useAction(api.task.complete);

  if (fetching) return <div>Loading tasks...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {tasks.map((task) => (
        <li key={task.id}>
          <input type="checkbox" checked={task.completed} onChange={() => completeTask({ id: task.id })} />
          {task.title}
        </li>
      ))}
    </ul>
  );
}

Authentication

When a user installs your ChatGPT App, they will authenticate themselves with your Gadget backend, and establish some kind of user identity in your session model, user model, or similar. When you use this provider, API calls made from your Widgets will act with that same identity by re-using the same JWT token that your Gadget backend provisioned at install time.

Using without authentication

If you don't need authentication for your ChatGPT widgets such that they are safe to be world readable, you can disable authentication in the provider by setting the authenticate prop to false:

// in web/chatgpt-widgets/root.tsx
import { Provider } from "@gadgetinc/react-chatgpt-apps";
import { api } from "../api";

function App() {
  return (
    <Provider api={api} authenticate={false}>
      <YourChatGPTAppComponents />
    </Provider>
  );
}

export default App;

How it works

ChatGPT Apps use a special authentication mechanism provided by OpenAI. When your app loads in ChatGPT, it can request an authentication token from OpenAI that identifies the current user and conversation. This library:

  1. Calls OpenAI's callTool function with the special __getGadgetAuthTokenV1 tool to retrieve an authentication token
  2. Configures your Gadget API client to include this token in all HTTP requests as a Bearer token
  3. Ensures that any API calls made before the token is fetched will wait for authentication to be ready

This all happens automatically when you wrap your app in the Provider component. Your Gadget backend will receive the authenticated requests and can use the token to identify the user and enforce permissions.

API Documentation

<Provider api={api}>

The Provider component must wrap your ChatGPT App to enable authenticated communication with your Gadget backend.

Props:

  • api (required): An instance of your Gadget application's API client. Example: new Client() where Client is imported from @gadget-client/your-app-slug.
  • children (required): Your React components that will use the Gadget API.

Example:

import { Client } from "@gadget-client/my-chatgpt-app";
import { Provider } from "@gadgetinc/react-chatgpt-apps";

const api = new Client();

export function App() {
  return (
    <Provider api={api}>
      <YourComponents />
    </Provider>
  );
}

The Provider component:

  • Automatically fetches an authentication token from OpenAI when mounted
  • Configures your API client to use this token for all requests
  • Handles token management transparently - you don't need to manually pass tokens around
  • Ensures all API calls wait for authentication to be ready

Using with @gadgetinc/react hooks

Once your app is wrapped in the Provider, you can use all the hooks from @gadgetinc/react to interact with your Gadget backend. All requests will automatically include the authentication token.

See the @gadgetinc/react documentation for the full list of available hooks including:

  • useFindOne - Fetch a single record by ID
  • useFindMany - Fetch a list of records with filtering, sorting, and pagination
  • useAction - Run actions on your Gadget models
  • useGlobalAction - Run global actions
  • useFetch - Make custom HTTP requests to your Gadget backend

All of these hooks will work seamlessly with the ChatGPT Apps authentication provided by this package.

ChatGPT-Specific Hooks

This package also provides hooks for interacting with the ChatGPT environment and OpenAI APIs. These hooks enable your app to respond to the ChatGPT context and provide a native experience.

useDisplayMode()

Access the current display mode of your ChatGPT app.

import { useDisplayMode } from "@gadgetinc/react-chatgpt-apps";

function MyWidget() {
  const displayMode = useDisplayMode();

  return <div>{displayMode === "fullscreen" ? <FullScreenView /> : <CompactView />}</div>;
}

Returns one of:

  • "pip" - Picture-in-picture mode (small floating window)
  • "inline" - Inline mode (embedded in the chat)
  • "fullscreen" - Fullscreen mode (takes up the entire screen)
  • null - If not available

useMaxHeight()

Get the maximum height available for your app in pixels.

import { useMaxHeight } from "@gadgetinc/react-chatgpt-apps";

function MyWidget() {
  const maxHeight = useMaxHeight();

  return <div style={{ maxHeight }}>Content that respects viewport limits</div>;
}

This value updates dynamically as the display mode or window size changes.

useRequestDisplayMode()

Request a change to the app's display mode.

import { useRequestDisplayMode } from "@gadgetinc/react-chatgpt-apps";

function MyWidget() {
  const requestDisplayMode = useRequestDisplayMode();

  const goFullscreen = async () => {
    const result = await requestDisplayMode("fullscreen");
    console.log("Granted mode:", result.mode);
  };

  return <button onClick={goFullscreen}>Go Fullscreen</button>;
}

Note: The host may reject or modify the request (e.g., on mobile, PiP is always coerced to fullscreen).

useWidgetState(defaultState)

Manage persistent widget state that syncs with ChatGPT's storage system.

import { useWidgetState } from "@gadgetinc/react-chatgpt-apps";

function Counter() {
  const [state, setState] = useWidgetState({ count: 0 });

  return <button onClick={() => setState({ count: (state?.count ?? 0) + 1 })}>Count: {state?.count ?? 0}</button>;
}

Similar to React's useState, but state persists across re-renders and display mode changes.

useWidgetProps(defaultProps)

Access the tool output props passed to your ChatGPT app.

import { useWidgetProps } from "@gadgetinc/react-chatgpt-apps";

function MyWidget() {
  const props = useWidgetProps({ userId: "unknown", theme: "light" });

  return <div>User ID: {props.userId}</div>;
}

When ChatGPT invokes your app, it may provide initial data through the toolOutput property. This hook retrieves that data with optional defaults.

useSendMessage()

Send follow-up messages to the ChatGPT conversation programmatically.

import { useSendMessage } from "@gadgetinc/react-chatgpt-apps";

function QuickActions() {
  const sendMessage = useSendMessage();

  return <button onClick={() => sendMessage("Tell me more about this")}>Ask for more details</button>;
}

Useful for creating interactive experiences that guide the conversation.

useOpenExternal()

Open external URLs in a way that respects the ChatGPT environment.

import { useOpenExternal } from "@gadgetinc/react-chatgpt-apps";

function LinkButton() {
  const openExternal = useOpenExternal();

  return <button onClick={() => openExternal("https://example.com")}>Visit Example</button>;
}

Attempts to use ChatGPT's native link handler, falling back to window.open if unavailable.

useCallTool()

Call external tools/APIs that have been configured in your ChatGPT app.

import { useCallTool } from "@gadgetinc/react-chatgpt-apps";

function WeatherWidget() {
  const callTool = useCallTool();

  const fetchWeather = async () => {
    const response = await callTool("weatherApi", { city: "San Francisco" });
    console.log(response?.result);
  };

  return <button onClick={fetchWeather}>Get Weather</button>;
}

useOpenAiGlobal(key)

Low-level hook for accessing OpenAI global values by key.

import { useOpenAiGlobal } from "@gadgetinc/react-chatgpt-apps";

function ThemeAwareComponent() {
  const theme = useOpenAiGlobal("theme");
  const locale = useOpenAiGlobal("locale");

  return <div className={theme}>Content in {locale}</div>;
}

Most apps should use the more specific hooks like useDisplayMode, useMaxHeight, etc. instead of using this hook directly.

Authentication Flow

When your ChatGPT App loads, the following happens automatically:

  1. The Provider component calls OpenAI's callTool function with the __getGadgetAuthTokenV1 tool name
  2. OpenAI returns an authentication token specific to the current user and conversation
  3. The Provider configures your Gadget API client to include this token as a Bearer token in the Authorization header of all HTTP requests
  4. Your Gadget backend receives the token and can use it to identify the user and enforce permissions

If the token fetch fails (for example, if the app is not running in a ChatGPT environment), an error will be thrown. This ensures your app doesn't make unauthenticated requests by mistake.