react-chatgpt-apps
v1.0.3
Published
Hooks and tools about ChatGPT Apps, with React
Readme
react-chatgpt-apps
React hooks and utilities for building ChatGPT Apps with ease
A lightweight React library that provides hooks and TypeScript types for building interactive ChatGPT Apps. This library simplifies the integration with the ChatGPT Apps runtime API, making it easier to create responsive and type-safe applications.
Features
- 🪝 React Hooks - Easy-to-use hooks for accessing ChatGPT runtime data
- 📘 TypeScript First - Full TypeScript support with comprehensive type definitions
- 🎨 Theme Aware - Access theme, display mode, and layout information
- 🔧 Tool Integration - Built-in support for tool inputs, outputs, and refresh
- 📱 Responsive - Access device type and capabilities information
- 🌍 Internationalization - Access user locale information
- ⚡ Lightweight - Minimal dependencies, only requires React
Installation
npm install react-chatgpt-appsor with yarn:
yarn add react-chatgpt-appsor with pnpm:
pnpm add react-chatgpt-appsQuick Start
import {
useToolInput,
useToolOutput,
useOpenAiGlobal,
} from "react-chatgpt-apps";
function MyChatGPTApp() {
// Access tool input and output
const toolInput = useToolInput<{ query: string }>();
const toolOutput = useToolOutput<{ result: string }>();
// Access theme and display mode
const theme = useOpenAiGlobal("theme");
const displayMode = useOpenAiGlobal("displayMode");
return (
<div className={`app-${theme}`}>
<h1>Query: {toolInput?.query}</h1>
{toolOutput && <p>Result: {toolOutput.result}</p>}
<p>Display Mode: {displayMode}</p>
</div>
);
}API Reference
Hooks
useOpenAiGlobal<K>(key)
Access any global value from the ChatGPT runtime environment.
Parameters:
key- The key of the global value to access (seeOpenAiGlobalstype)
Returns: The value associated with the specified key
Example:
const theme = useOpenAiGlobal("theme"); // 'light' | 'dark'
const locale = useOpenAiGlobal("locale"); // e.g., 'en-US'
const maxHeight = useOpenAiGlobal("maxHeight"); // number
const safeArea = useOpenAiGlobal("safeArea"); // SafeArea
const userAgent = useOpenAiGlobal("userAgent"); // UserAgent
const displayMode = useOpenAiGlobal("displayMode"); // 'pip' | 'inline' | 'fullscreen'useToolInput<T>()
Access the input data passed to the current tool.
Type Parameter:
T- The expected type of the tool input
Returns: The tool input data of type T
Example:
interface MyToolInput {
query: string;
options?: {
limit: number;
};
}
const input = useToolInput<MyToolInput>();
console.log(input.query);useToolOutput<T>()
Access the output data from the current tool.
Type Parameter:
T- The expected type of the tool output
Returns: The tool output data of type T | null
Example:
interface MyToolOutput {
results: Array<{ id: string; name: string }>;
total: number;
}
const output = useToolOutput<MyToolOutput>();
if (output) {
console.log(`Found ${output.total} results`);
}useToolResponseMetadata()
Access metadata about the tool response.
Returns: Tool response metadata object or null
Example:
const metadata = useToolResponseMetadata();
console.log(metadata);Functions
refreshTool(name, args)
Refresh a tool by calling it with new arguments.
Parameters:
name- The name of the tool to callargs- Arguments to pass to the tool
Returns: Promise<void>
Example:
import { refreshTool } from "react-chatgpt-apps";
async function handleRefresh() {
await refreshTool("my-tool", { query: "updated query" });
}Types
OpenAiGlobals
The global state available from the ChatGPT runtime.
type OpenAiGlobals<
ToolInput = UnknownObject,
ToolOutput = UnknownObject,
ToolResponseMetadata = UnknownObject,
WidgetState = UnknownObject,
> = {
theme: Theme; // 'light' | 'dark'
userAgent: UserAgent;
locale: string;
// Layout
maxHeight: number;
displayMode: DisplayMode; // 'pip' | 'inline' | 'fullscreen'
safeArea: SafeArea;
// State
toolInput: ToolInput;
toolOutput: ToolOutput | null;
toolResponseMetadata: ToolResponseMetadata | null;
widgetState: WidgetState | null;
};Theme
type Theme = "light" | "dark";DisplayMode
type DisplayMode = "pip" | "inline" | "fullscreen";UserAgent
type UserAgent = {
device: {
type: "mobile" | "tablet" | "desktop" | "unknown";
};
capabilities: {
hover: boolean;
touch: boolean;
};
};SafeArea
type SafeArea = {
insets: {
top: number;
bottom: number;
left: number;
right: number;
};
};Global API
The library extends the window.openai object with the following methods:
window.openai.callTool(name, args)
Call a tool on your MCP (Model Context Protocol).
Parameters:
name- Tool nameargs- Tool arguments
Returns: Promise<{ result: string }>
window.openai.sendFollowUpMessage({ prompt })
Trigger a follow-up turn in the ChatGPT conversation.
Parameters:
prompt- The follow-up message prompt
Returns: Promise<void>
window.openai.openExternal({ href })
Open an external link (redirects web page or mobile app).
Parameters:
href- The URL to open
Returns: void
window.openai.requestDisplayMode({ mode })
Request a display mode change (inline to fullscreen or PiP).
Parameters:
mode- The requested display mode
Returns: Promise<{ mode: DisplayMode }> - The granted mode (may differ from requested)
Note: On mobile, PiP is always coerced to fullscreen.
window.openai.setWidgetState(state)
Set the widget state.
Parameters:
state- The new widget state
Returns: Promise<void>
Usage Examples
Theme-Aware Component
import { useOpenAiGlobal } from "react-chatgpt-apps";
function ThemedComponent() {
const theme = useOpenAiGlobal("theme");
return (
<div
style={{
backgroundColor: theme === "dark" ? "#1a1a1a" : "#ffffff",
color: theme === "dark" ? "#ffffff" : "#000000",
}}
>
<h1>Current theme: {theme}</h1>
</div>
);
}Responsive Layout
import { useOpenAiGlobal } from "react-chatgpt-apps";
function ResponsiveLayout() {
const userAgent = useOpenAiGlobal("userAgent");
const displayMode = useOpenAiGlobal("displayMode");
const isMobile = userAgent.device.type === "mobile";
const isFullscreen = displayMode === "fullscreen";
return (
<div className={`layout ${isMobile ? "mobile" : "desktop"}`}>
{isFullscreen ? <FullscreenView /> : <CompactView />}
</div>
);
}Safe Area Handling
import { useOpenAiGlobal } from "react-chatgpt-apps";
function SafeAreaComponent() {
const safeArea = useOpenAiGlobal("safeArea");
return (
<div
style={{
paddingTop: safeArea.insets.top,
paddingBottom: safeArea.insets.bottom,
paddingLeft: safeArea.insets.left,
paddingRight: safeArea.insets.right,
}}
>
Content respects safe areas
</div>
);
}Tool Integration
import { useToolInput, useToolOutput, refreshTool } from "react-chatgpt-apps";
interface SearchInput {
query: string;
filters?: {
category: string;
};
}
interface SearchOutput {
results: Array<{
id: string;
title: string;
description: string;
}>;
total: number;
}
function SearchTool() {
const input = useToolInput<SearchInput>();
const output = useToolOutput<SearchOutput>();
const handleRefresh = async () => {
await refreshTool("search", {
query: input.query,
filters: input.filters,
});
};
return (
<div>
<h2>Search: {input.query}</h2>
{input.filters && <p>Category: {input.filters.category}</p>}
<button onClick={handleRefresh}>Refresh</button>
{output && (
<div>
<p>Found {output.total} results</p>
<ul>
{output.results.map((result) => (
<li key={result.id}>
<h3>{result.title}</h3>
<p>{result.description}</p>
</li>
))}
</ul>
</div>
)}
</div>
);
}Display Mode Management
function DisplayModeToggle() {
const displayMode = useOpenAiGlobal("displayMode");
const handleToggleFullscreen = async () => {
const newMode = displayMode === "fullscreen" ? "inline" : "fullscreen";
const result = await window.openai.requestDisplayMode({ mode: newMode });
console.log("Granted mode:", result.mode);
};
return (
<button onClick={handleToggleFullscreen}>
{displayMode === "fullscreen" ? "Exit Fullscreen" : "Go Fullscreen"}
</button>
);
}Follow-Up Messages
function FollowUpButton() {
const handleSendFollowUp = async () => {
await window.openai.sendFollowUpMessage({
prompt: "Can you explain this in more detail?",
});
};
return <button onClick={handleSendFollowUp}>Ask for more details</button>;
}TypeScript Support
This library is written in TypeScript and provides comprehensive type definitions out of the box. All hooks and utilities are fully typed, providing excellent IDE autocomplete and type checking.
Type Safety with Generics
// Define your tool's input/output types
interface MyToolInput {
query: string;
limit: number;
}
interface MyToolOutput {
items: string[];
count: number;
}
// Get full type safety and autocomplete
const input = useToolInput<MyToolInput>();
const output = useToolOutput<MyToolOutput>();
// TypeScript knows the exact structure
console.log(input.query); // ✅ Type-safe
console.log(input.unknown); // ❌ TypeScript errorBrowser Compatibility
This library requires a modern browser environment with support for:
- ES2020 features
- React 18 or later
- CustomEvents API
- Window object
Contributing
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run the build (
npm run build) - Format your code (
npm run format) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Clone the repository
git clone https://github.com/tiste/react-chatgpt-apps.git
cd react-chatgpt-apps
# Install dependencies
npm install
# Build the project
npm run build
# Watch mode for development
npm run dev
# Format code
npm run formatProject Structure
react-chatgpt-apps/
├── src/
│ ├── hooks.ts # React hooks implementation
│ ├── types.ts # TypeScript type definitions
│ └── index.ts # Public API exports
├── scripts/
│ └── build.mjs # Build script
├── dist/ # Compiled output
├── package.json # Package configuration
└── tsconfig.json # TypeScript configurationLicense
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Baptiste Lecocq
- Website: https://tiste.io
- Email: [email protected]
Support
If you encounter any issues or have questions:
Acknowledgments
Built with ❤️ for the ChatGPT Apps community.
Note: This library is designed to work within the ChatGPT Apps runtime environment. Make sure you're developing a ChatGPT App to use these utilities effectively.
