Your First App
Get up and running with PancakeJS in under 5 minutes. This guide will walk you through creating your first universal tool that works across all AI hosts.
Prerequisites
Before you begin, make sure you have:
- Node.js 18+ installed
- pnpm, npm, or yarn package manager
- Basic familiarity with TypeScript
Create a New Project
The fastest way to get started is with our CLI:
pnpm create universal-app my-app
cd my-app
pnpm install
pnpm devIf you prefer to set up manually:
mkdir my-universal-app
cd my-universal-app
pnpm init
# Install core dependencies
pnpm add @pancakeapps/core @pancakeapps/server @pancakeapps/react
pnpm add @pancakeapps/adapter-mcp-apps @pancakeapps/adapter-chatgpt-apps
pnpm add @pancakeapps/cli zod react react-dom
# Install dev dependencies
pnpm add -D typescript @types/react @types/react-domYour First Tool
Create the Server
Create a server.ts file in your project root:
import { z } from 'zod';
import { createUniversalServerApp, textResult } from '@pancakeapps/server';
import { createMcpAppsServerAdapter } from '@pancakeapps/adapter-mcp-apps';
import { createChatGptServerAdapter } from '@pancakeapps/adapter-chatgpt-apps';
const app = createUniversalServerApp({
name: 'my-app',
version: '1.0.0',
});
// Define a simple tool
app.tool(
{
name: 'greet',
description: 'Greet someone by name',
inputSchema: z.object({
name: z.string().describe('Name to greet'),
}),
},
async (input) => {
return textResult(`Hello, ${input.name}! 🥞`);
},
);
// Register adapters for both hosts
app.adapter(createMcpAppsServerAdapter());
app.adapter(createChatGptServerAdapter());
// Start the server
app.listen({ port: 3000, dev: true });Run the Development Server
pnpm universal-apps devThis starts the development server with:
- Hot module reloading
- Built-in inspector at
http://localhost:3000/_inspector - Automatic adapter detection
Test in the Inspector
Open http://localhost:3000/_inspector in your browser. You'll see:
- A list of all your tools
- Options to test with both MCP and ChatGPT harnesses
- Real-time logs and debugging info
Try calling your greet tool with different names!
Your First Widget
Widgets are tools with a UI. Let's create one:
Define the Widget Tool
Add this to your server.ts:
import { renderWidget } from '@pancakeapps/server';
app.widget(
{
name: 'hello-widget',
description: 'A friendly greeting widget',
inputSchema: z.object({
name: z.string(),
}),
ui: {
entry: 'src/widgets/hello.tsx',
},
},
async (input) => {
return renderWidget('hello-widget', {
data: { greeting: `Hello, ${input.name}!` },
});
},
);Create the Widget UI
Create src/widgets/hello.tsx:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { UniversalAppProvider, useToolInvocation } from '@pancakeapps/react';
function HelloWidget() {
const { data } = useToolInvocation();
return (
<div style={{
padding: '2rem',
background: 'linear-gradient(135deg, #1C1917 0%, #292524 100%)',
borderRadius: '12px',
color: '#FAFAF9',
fontFamily: 'system-ui',
}}>
<h1 style={{
background: 'linear-gradient(135deg, #FCD34D 0%, #D97706 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}>
{data?.greeting ?? 'Hello!'}
</h1>
<p>This widget works in any AI host! 🥞</p>
</div>
);
}
function App() {
return (
<UniversalAppProvider>
<HelloWidget />
</UniversalAppProvider>
);
}
createRoot(document.getElementById('root')!).render(<App />);Test the Widget
Refresh the inspector and select "hello-widget" from the widgets list. You can test it in both MCP and ChatGPT harnesses to verify it works everywhere!
Project Structure
After setup, your project should look like this:
my-app/
├── server.ts # Server entry point
├── src/
│ └── widgets/
│ └── hello.tsx # Widget UI
├── dist/
│ └── widgets/
│ └── hello.html # Built widget (auto-generated)
├── universal-apps.config.ts # Configuration (optional)
├── package.json
└── tsconfig.jsonNext Steps
You've just created your first universal AI tool! Here's what to explore next:
- Tools vs Widgets — Understand when to use each
- Capabilities Model — Handle feature differences across hosts
- Deploy to Cloudflare — Ship to production
- Examples — Learn from working code