Skip to main content

Overview

If you already have a React project and want to use sunpeak for runtime APIs or testing, you can integrate the sunpeak library directly without using the framework.
Starting from scratch? Use Quickstart for the recommended ChatGPT App creation experience.

Prerequisites

Your existing project needs:

React

Version 19

Node.js

Version 20 or higher

Build Tool

Vite recommended

Installation Steps

1

Install sunpeak

Add sunpeak to your project dependencies:
pnpm add sunpeak
If you only want to use sunpeak simulation and testing functionality (without the runtime APIs), you can add sunpeak to devDependencies instead.
2

Install styles (Tailwind)

sunpeak requires Tailwind CSS 4. If you don’t have it installed:
pnpm add -D tailwindcss@next @tailwindcss/vite@next
Configure Tailwind in your build config, if it isn’t set up already:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [react(), tailwindcss()],
});
Import Tailwind and ChatGPT styles to your CSS entrypoint:
@import "tailwindcss";
@import "@openai/apps-sdk-ui/css";

/* Scan simulator source files for Tailwind classes */
@source "./**/*.{ts,tsx}";

/* Required for Tailwind to find class references in Apps SDK UI components. */
@source "../node_modules/@openai/apps-sdk-ui";

/* Configure dark mode to use data-theme attribute (OpenAI SDK standard) */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
3

Create simulation files

Create a resource metadata JSON file:
// src/resources/example-resource.json
{
  "name": "example",
  "title": "Example",
  "description": "My example component",
  "mimeType": "text/html+skybridge",
  "_meta": {
    "openai/widgetDomain": "https://example.com",
    "openai/widgetCSP": {
      "connect_domains": [],
      "resource_domains": []
    }
  }
}
Create a simulation JSON file:
// src/simulations/example-show-simulation.json
{
  "userMessage": "Show me an example",
  "tool": {
    "name": "show-example",
    "description": "Show an example widget",
    "inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
    "title": "Show Example",
    "annotations": { "readOnlyHint": true },
    "_meta": {
      "openai/widgetAccessible": true,
      "openai/resultCanProduceWidget": true
    }
  },
  "callToolResult": {
    "structuredContent": { "message": "Hello from simulation!" },
    "_meta": {}
  }
}
4

Wire up the simulator

Create an entrypoint file (like dev/main.tsx) where you want to run your simulator:
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { ChatGPTSimulator } from 'sunpeak';
import { MyComponent } from '../src/components/MyComponent';
import exampleResource from '../src/resources/example-resource.json';
import exampleSimulation from '../src/simulations/example-show-simulation.json';
import '../src/styles/globals.css';

// Combine simulation with resource and component
const simulations = [{
  ...exampleSimulation,
  resource: exampleResource,
  resourceComponent: MyComponent,
}];

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ChatGPTSimulator
      simulations={simulations}
      appName="My App"
      appIcon="🌄"
    />
  </StrictMode>
);
Add a script to run your simulation dev server (package.json):
"scripts": {
  "dev": "vite --port 6767"
}
Run your local development server:
pnpm dev
Only use the simulator in development. For production, export your component directly.
5

Wire up the MCP server

Create an MCP server file (like mcp/server.ts) to serve your built widgets to ChatGPT:
import { runMCPServer } from 'sunpeak/mcp';
import path from 'path';
import { fileURLToPath } from 'url';
import exampleResource from '../src/resources/example-resource.json';
import exampleSimulation from '../src/simulations/example-show-simulation.json';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Combine simulation with resource and distPath for MCP server
const simulations = [{
  ...exampleSimulation,
  resource: exampleResource,
  distPath: path.resolve(__dirname, '../dist/example.js'),
}];

runMCPServer({
  name: 'My App',
  version: '0.1.0',
  simulations,
  port: 6766,
});
Add scripts to build and run your MCP server (package.json):
"scripts": {
  "build": "vite build",
  "mcp": "tsx mcp/server.ts"
}
Build your app and start the MCP server:
pnpm build
pnpm mcp
See runMCPServer API Reference for configuration options and connecting to ChatGPT via tunnel.

Need the Full Framework?

Often, it’s easier to just copy your existing components into a new project initiated with the sunpeak framework. The framework comes pre-configured for local and platform testing with pre-built components and automatic discovery of simulations and resources. See Quickstart to get started.