Skip to content

AINativeKit/chatgpt-apps-sdk-devtools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

17 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

@ainativekit/devtools

Development tools for building and testing ChatGPT Apps using ChatGPT Apps SDK

npm version License: MIT

A powerful, zero-configuration development environment for building ChatGPT apps. Simulate the ChatGPT production environment locally with interactive controls for testing different states, themes, and device types.

โœจ Features

  • ๐ŸŽญ Mock ChatGPT Environment - Simulates window.openai API exactly like production
  • ๐ŸŽจ Theme Switching - Test light and dark themes instantly
  • ๐Ÿ“ฑ Device Simulation - Desktop (768px), Tablet (640px), Mobile (375px) viewports
  • ๐Ÿ”„ State Testing - Loading, data, and error states with customizable delays
  • ๐Ÿ› Debug Overlays - Visual boundary indicators for development
  • ๐Ÿš€ Zero Configuration - Works out of the box with sensible defaults
  • ๐Ÿ“ฆ Production Ready - Clean separation between dev tools and widget code
  • ๐Ÿ”Œ ChatGPT Apps SDK Compatible - Works with any ChatGPT Apps SDK implementation

๐Ÿ“‹ Requirements

  • React 18.0.0 or higher
  • Node.js 18.0.0 or higher
  • Modern browser with ES2020+ support
    • Chrome 80+, Firefox 75+, Safari 13.1+, Edge 80+

Optional Dependencies

  • @ainativekit/ui 0.10.0 or higher (optional, but recommended for enhanced theming)
    • DevTools includes basic theme support out of the box
    • For full design system integration, install @ainativekit/ui and use ThemeProvider
    • See usage examples below for both standalone and integrated approaches

๐Ÿ“ฆ Installation

npm install --save-dev @ainativekit/devtools

or with yarn:

yarn add -D @ainativekit/devtools

๐Ÿš€ Quick Start

Standalone Usage (No Dependencies)

DevTools works out of the box with built-in theme support:

import { DevContainer } from '@ainativekit/devtools';
import App from './App';

// Only use DevContainer in development
const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  import.meta.env.DEV ? (
    <DevContainer>
      <App />
    </DevContainer>
  ) : (
    <App />
  )
);

Enhanced Usage (with @ainativekit/ui)

For full design system integration and advanced theming:

import { DevContainer } from '@ainativekit/devtools';
import { ThemeProvider } from '@ainativekit/ui';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <ThemeProvider>
    {import.meta.env.DEV ? (
      <DevContainer>
        <App />
      </DevContainer>
    ) : (
      <App />
    )}
  </ThemeProvider>
);

With Custom Data Loader

<DevContainer
  dataLoader={async () => {
    // Return your widget-specific mock data
    const response = await fetch('/api/mock-data');
    return response.json();
  }}
  loadingDelay={3000} // Test loading states
  theme="dark" // Start with dark theme
>
  <YourWidget />
</DevContainer>

Multiple Widgets (v0.2.0+)

DevContainer automatically detects when you have multiple widgets and shows a selector:

import { DevContainer, createMockData } from '@ainativekit/devtools';
import CarouselWidget from './widgets/CarouselWidget';
import MapWidget from './widgets/MapWidget';
import SearchWidget from './widgets/SearchWidget';

// Create mock data with automatic empty states
const restaurantData = createMockData(
  { restaurants: [...], totalResults: 9 },
  {
    emptyTransform: (data) => ({
      ...data,
      restaurants: [],
      totalResults: 0
    })
  }
);

function App() {
  return (
    <DevContainer
      widgets={[
        { id: 'carousel', name: 'Restaurant Carousel', component: CarouselWidget },
        { id: 'map', name: 'Location Map', component: MapWidget },
        { id: 'search', name: 'Search Results', component: SearchWidget }
      ]}
      dataLoaders={{
        restaurants: () => restaurantData.full,
        locations: () => ({ lat: 40.7128, lng: -74.0060 })
      }}
      emptyDataLoaders={{
        restaurants: () => restaurantData.empty
      }}
      defaultWidget="carousel"
      loadingDelay={2000}
      theme="light"
    />
  );
}

Note: Wrap with <ThemeProvider> from @ainativekit/ui for enhanced theming support.

Features:

  • Single dev server for all widgets
  • Automatic widget selector (only shows when multiple widgets)
  • URL support (?widget=map) for deep linking
  • Persistent widget selection
  • Shared data loaders across widgets

๐Ÿ“– API Reference

DevContainer Props

Single Widget Mode

Prop Type Default Description
children React.ReactNode - Single widget component
dataLoader () => Promise<any> | any - Data loader function
emptyDataLoader () => Promise<any> | any - Empty state data loader

Multi-Widget Mode

Prop Type Default Description
widgets Widget[] - Array of widget configurations
dataLoaders Record<string, Function> {} Map of data loader functions
emptyDataLoaders Record<string, Function> {} Map of empty data loader functions
defaultDataLoader string - Key for default data loader
defaultWidget string - ID of default widget to show

Common Props

Prop Type Default Description
loadingDelay number 2000 Delay (ms) before loading data
theme 'light' | 'dark' 'light' Initial theme
autoLoad boolean true Auto-load data on mount
toolbarPosition 'top' | 'bottom' 'top' Toolbar position

createMockData

createMockData<T>(fullData: T, config?: MockDataConfig<T>): MockData<T>

Creates type-safe mock data with automatic empty state generation.

Config Options:

  • emptyData: Explicit empty state data
  • emptyTransform: Function to derive empty state from full data
  • If neither provided, generates empty object automatically

Mock OpenAI API

The DevContainer automatically mocks the window.openai API with these methods:

window.openai = {
  callTool: async (name, args) => { /* mocked */ },
  sendFollowUpMessage: async ({ prompt }) => { /* mocked */ },
  openExternal: ({ href }) => { /* mocked */ },
  setWidgetState: (state) => { /* mocked */ },
  // Plus all OpenAiGlobals properties
  theme: 'light' | 'dark',
  toolOutput: any,
  locale: string,
  maxHeight: number,
  userAgent: { device: { type }, capabilities: { hover, touch } }
}

๐ŸŽฎ Interactive Controls

Toolbar Features

  • State Controls: Switch between Loading, Instant Data, Delayed Data, Empty, and Error states
  • Theme Toggle: Switch between light and dark themes
  • Device Simulation: Test desktop, tablet, and mobile viewports
  • Debug Border: Toggle visual boundary indicators
  • Collapsible UI: Hide/show dev tools with a single click

๐Ÿ’ก Common Patterns

Testing Loading States

<DevContainer
  loadingDelay={5000} // 5 second delay
  dataLoader={async () => {
    // Simulate slow API
    await new Promise(resolve => setTimeout(resolve, 2000));
    return { data: 'loaded' };
  }}
>
  <App />
</DevContainer>

Testing Empty States

<DevContainer
  emptyDataLoader={() => {
    // Return widget-specific empty state
    return {
      type: 'search-results',
      properties: [],
      searchInfo: { totalResults: 0, location: 'Sydney, NSW' }
    };
  }}
  dataLoader={async () => {
    // Regular data when not in empty state
    return await fetchMockData();
  }}
>
  <SearchWidget />
</DevContainer>

Testing Error States

<DevContainer
  dataLoader={() => {
    // Return error data
    return { error: 'Something went wrong' };
  }}
>
  <App />
</DevContainer>

Custom Mock Data

// mockData.ts
export const mockSearchResults = {
  type: 'search-results',
  items: [
    { id: 1, title: 'Result 1' },
    { id: 2, title: 'Result 2' }
  ]
};

// App.tsx
import { mockSearchResults } from './mockData';

<DevContainer
  dataLoader={() => mockSearchResults}
>
  <SearchWidget />
</DevContainer>

๐Ÿ— Architecture

The DevContainer follows these principles:

  1. Zero Widget Contamination - Your widget code contains no dev-specific logic
  2. Production Parity - Uses the same APIs as production ChatGPT Apps
  3. External Debugging - All debug overlays are applied from outside the widget
  4. Type Safety - Full TypeScript support with AINativeKit types
  5. Clean Separation - Dev tools are never included in production builds

๐Ÿ”ง Development

Building the Package

npm run build

Development Mode

npm run dev

Type Checking

npm run type-check

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

๐Ÿ“„ License

MIT ยฉ Jake Lin

๐Ÿ”— Links

๐Ÿ™ Acknowledgments

Built with โค๏ธ for the ChatGPT app developer community. This tool helps developers build and test ChatGPT Apps using the ChatGPT Apps SDK, making development faster and more enjoyable.