chatgpt-app-builder
GEO / AI searchalpic-ai/skybridgeskills.sh ↗
Installs
4,276
deduplicated, at the last sync
Since we started
+0.4%
14 readings, about 4 hours apart. Not a live curve.
Our category
GEO / AI search
ours
Last read
Sep 3, 2026
from the directory
Our brief
oursThis skill guides developers through the full lifecycle of creating ChatGPT apps using the Skybridge framework. It covers idea discovery, project scaffolding, implementing type-safe tools and React views, local development, deployment to Alpic, and publishing to the ChatGPT directory. The skill provides reference documentation for architecture patterns, CSP configuration, OAuth integration, and ecommerce templates.
- SPEC.md design document
- Skybridge project scaffold
- MCP server with tools
- React view components
- Alpic deployment config
- app idea or requirements
- package manager (npm/pnpm/yarn/bun/deno)
- Alpic account for deployment
- Shopify credentials for ecommerce
- OAuth credentials for auth
optional
The skill references optional paid services: Shopify Storefront API for ecommerce template (evidence 7), Stripe for payments (evidence 11), and Alpic platform for deployment (evidence 4), but core framework usage appears free.
optional
An Alpic account is required only for deployment (evidence 4); local development and scaffolding do not require registration (evidence 2, 3).
The skill cannot automatically generate UX flows without user validation (evidence 5). It cannot verify external API integrations or guarantee ChatGPT directory approval (evidence 4). It does not decide product scope or replace user design decisions (evidence 1, 5).
Evidencestatic findingsskills/chatgpt-app-builder/references/architecture.md:1-76skills/chatgpt-app-builder/references/copy-template.md:1-28skills/chatgpt-app-builder/references/csp.md:1-34+7
[{"code":"oauth","match":"OAuth","path":"SKILL.md"},{"code":"oauth","match":"oauth","path":"SKILL.md"},{"code":"payment","match":"Stripe","path":"references/architecture.md"},{"code":"oauth","match":"OAuth2","path":"references/discover.md"},{"code":"payment","match":"pricing","path":"references/discover.md"},{"code":"oauth","match":"access token","path":"references/ecommerce.md"}]# Architecture Workflow ## Concepts A **tool** is a backend action with no UI. It takes input and returns structured output. It can CRUD data and perform operations (checkout, submit, etc.). A **view** is a tool with a UI. It renders the tool output visually. The UI is a React app that can: - navigate multiple views (search → detail → confirmation) - manage its own state - call other tools to fetch data absent from the view output schema or trigger actions. ## Step 1: Identify the UX Flows A **flow** is an end-to-end user journey that accomplishes one goal (e.g., "book a flight" = search → select → checkout). Extract flows from the SPEC's value proposition. **Stick to the spec**: don't invent flows or infer intermediate steps. **Example:** Input (SPEC): > Book flights by destination and dates, and cancel existing bookings by booking ID. ✅ Good output: ``` Book flight: 1. Search flights 2. Select flight 3. Checkout Cancel booking: 1. Cancel booking ``` ❌ Bad output: ``` Search flights: 1. Search flights 2. View results Book flight: ← wrong: split booking into separate flow 1. Select flight 2. Enter passenger details 3. Checkout Cancel booking: 1. List bookings ← wrong: inve
# Start From Template
Scaffold a project by setting up the Skybridge template starter. Skybridge is a TypeScript framework for building MCP servers with type-safe APIs and React views.
## Workflow
1. Ask: "Which package manager?" (npm / pnpm / yarn / bun / deno)
2. Run (do not `rm` beforehand—create handles conflicts):
```bash
{pm} create skybridge@latest {target-dir}
# deno
deno init --npm skybridge {target-dir}
```
Template flags: `--blank` (minimal, no tools), `--ecom` (ecommerce starter) or `--example <name>` (a copy of `examples/<name>` from the Skybridge repo, downloaded from GitHub). With npm, separate flags: `npm create skybridge@latest {target-dir} -- --ecom`.
Scaffolding with `--ecom`? → follow [ecommerce.md](ecommerce.md) to fill it.
3. [Start the dev server](run-locally.md). Read logs to assess readiness/health; fix any errors (TypeScript, etc.) before proceeding.
4. Start implementing your app using these core concepts:
- Server handlers and view components → [fetch-and-render-data.md](fetch-and-render-data.md)
- View state and LLM context → [state-and-context.md](state-and-context.md)
- Display modes → [ui-guidelines.md](ui-guidelines.md)
5. Delete unused vie# Content Security Policy
Views run in sandboxed iframes with strict CSP. Whitelist external domains under the tool's `view.csp`:
| Property | Purpose |
|----------|---------|
| `connectDomains` | Fetch/XHR requests to external APIs |
| `resourceDomains` | Static assets (images, fonts, scripts, styles) |
| `redirectDomains` | (optional) `openExternal` destinations without safe-link modal |
| `frameDomains` | (optional) Iframe embeds — triggers stricter review |
```typescript
server.registerTool(
{
name: "search-flights",
description: "Search flights",
inputSchema: { ... },
view: {
component: "search-flights",
description: "Flight results",
csp: {
connectDomains: ["https://api.example.com"],
resourceDomains: ["https://cdn.example.com"],
frameDomains: ["https://maps.example.com"],
redirectDomains: ["https://checkout.example.com"],
},
},
},
async (input) => ({ ... })
);
```
Skybridge auto-includes the server's domain. Only add external domains.
# Deploy
Deploy to Alpic using Alpic CLI.
## Parameters
- {path-to-project} is the path to the project directory. It is relative to the current working directory.
- When executing a command requiring `{path-to-project}`, check that you provided the correct path to the project.
## Steps
1. **Make sure the user is logged in to Alpic**
Execute `npx alpic@latest login` to login to Alpic.
2. **Deploy to Alpic**
If it's a first time deployment (absence of `.alpic/` folder in the project directory), **ask the user for the project name**.
Then, execute `npx alpic@latest deploy --yes --project-name {project-name} {path-to-project}`.
3. **Subsequent deployments**
For subsequent deployments (presence of `.alpic/` folder in the project directory), execute `npx alpic@latest deploy --yes {path-to-project}`.
4. **Setup GitHub integration**
If it's a new project, ask the user first if they want to setup git.
If yes:
- **Push to GitHub** — Commit and push code
- **Link to Alpic project** - Use `npx alpic@latest git connect --yes {path-to-project}`
Full docs: [docs.alpic.ai/quickstart](https://docs.alpic.ai/quickstart)
# Discovery Workflow **Goal: Idea maturation, not speed.** **Proceed in phases.** Even if the user provides details, complete each phase through conversation. Do not infer or assume but discuss and validate with user. Proceed one phase at a time—do not write SPEC.md nor proceed to implementation until all phases are validated. --- ## Phase 1: Value Proposition 1. **Problem + User**: What problem? For whom? 2. **Pain**: How solved today? What's painful? 3. **Core actions**: 1-3 focused actions (not a full app port) --- ## Phase 2: Why LLM? 1. **Conversational win**: Where does "just say it" beat clicking? 2. **LLM adds**: What does the LLM contribute? (intent, generation, reasoning) 3. **What LLM lacks**: Your data? APIs? Ability to take real actions? **Fail patterns** (stop if any match): - Long-form or static content better suited for a website - Complex multi-step workflows that exceed display modes - Dashboards (use tables, lists, or short paragraphs instead) - Full app ports instead of focused atomic actions - No clear answer to "why inside an AI assistant vs standalone?" → If fails: explain gap, suggest different interface or narrower scope. --- ## Phase 3: UI Over
# Download file
Save content to the user's filesystem → `useDownload`
Views run in sandboxed iframes where `<a download>` and `URL.createObjectURL` are blocked. `useDownload` asks the host to perform the save; the host shows a confirmation dialog first.
> MCP Apps only. On ChatGPT (Apps SDK), use `useFiles` to work with attachments instead.
## Inline text (CSV, JSON, markdown)
```tsx
import { useDownload } from "skybridge/web";
function ExportButton({ rows }: { rows: Row[] }) {
const download = useDownload();
const handleClick = async () => {
const csv = rows.map((r) => `${r.id},${r.name}`).join("\n");
const { isError } = await download({
contents: [
{
type: "resource",
resource: {
uri: "file:///orders.csv", // filename hint
mimeType: "text/csv",
text: csv,
},
},
],
});
if (isError) {
// user cancelled or host denied — soft fail, not an exception
}
};
return <button onClick={handleClick}>Export CSV</button>;
}
```
## Inline binary
```tsx
await download({
contents: [
{
type: "resource",
resource: {
uri: "file:///chart.png# Fill the template
The `ecom` template is a skeleton: the wiring is in place, the data is not. Two tools: `search-products` (keyword + filters in, matching products out as model-facing structured output, no view) and `render-carousel` (curated product/variant ids in, an inline carousel out). A vanilla-extract design system under `src/design/` styles everything. This reference connects the tools to a real catalog and the design system to the brand.
Not in a scaffolded `ecom` project (no `src/tools/`)? Scaffold it first with the `--ecom` flag: [copy-template.md](copy-template.md). Then return here.
## The path
Six phases, each ending at a gate. Do not start a phase before the previous gate passes. Phases 4 and 5 are independent of each other (5 needs only phase 1's brand assets); phase 6 needs both.
```
1 Gather ──► 2 Explore data ──► 3 Decide UX ──► 4 Server ──┐
└────────────────────────────────────► 5 Design ──────┴──► 6 Components ──► Final gate
```
Ground rules for every phase:
- Never invent a schema, endpoint, or credential. Everything comes from the user or the live data source.
- `grep -rn "@todo" src` is the master worklist. Resolving a marker means making the d# Fetch and render data - Fetch structured data and render with custom UI → `view` - Fetch textual data or trigger actions → `tool` - Tool can be triggered by user interaction within a view UI ## Project Structure ``` my-app/ ├── src/ │ ├── server.ts # Skybridge app: tool + view registration in `handler` │ ├── index.ts # runs the app │ ├── helpers.ts # Type-safe hooks via generateHelpers │ ├── index.css # Global CSS, must be imported in every view │ └── views/ # React components (filename = view component name) │ └── search-flights.tsx └── package.json ``` **Naming convention**: View filename must match the `view.component` name using kebab-case. `search_flights` → register with `view.component: "search-flights"` → file `views/search-flights.tsx` ## Server Handlers Output: - **`structuredContent`**: concise JSON the view uses and the model reads. Include only what the model should see. - **`content`** (optional): concise narration (Markdown or plaintext) shown to the LLM. - **`_meta`** (optional): additional details or display-only content kept out of the model's direct context, such as large payloads or image URLs. T
# Migrate an existing app to Skybridge v1
Use this when upgrading from Skybridge `< 0.36.x`. The breaking changes first landed in [v0.36.0](https://github.com/alpic-ai/skybridge/releases/tag/v0.36.0) and were restated in [v1.0.0](https://github.com/alpic-ai/skybridge/releases/tag/v1.0.0); users might refer to `0.36.x+` as "v1". A greenfield app scaffolded from the current example apps already has everything below correct; these gotchas apply to migrators who carry over their own config.
Read the release notes first: they are the fastest source. Use this guide for the parts the notes get wrong or leave out. When a note is imprecise, defer to this document and verify against the installed package instead of guessing: grep its dist types (`node_modules/skybridge/dist/web/index.d.ts`, `dist/server/server.d.ts`, `dist/web/plugin/scan-views.js`), or run `npm pack skybridge@<version>` to read them before installing.
## Step 1 — Mechanical renames (the notes are to be trusted here)
These are exactly as documented. Apply them verbatim:
| v0 | v1 |
|----|----|
| `registerWidget("name", viewMeta, toolDef, handler)` | `registerTool({ name, ...toolDef, view: {...} }, handler)` |
| `mountWi--- name: chatgpt-app-builder description: | Guide developers through creating and updating ChatGPT apps. Covers the full lifecycle: brainstorming ideas against UX guidelines, bootstrapping projects, implementing tools/views, debugging, running dev servers, deploying and connecting apps to ChatGPT. Use when a user wants to create or update a ChatGPT app / MCP server for ChatGPT, or use the Skybridge framework. --- # Creating Apps For LLMs ChatGPT apps are conversational experiences that extend ChatGPT through tools and custom UI views. They're built as MCP servers invoked during conversations. ⚠️ The app is consumed by two users at once: the **human** and the **ChatGPT LLM**. They collaborate through the view—the human interacts with it, the LLM sees its state. Internalize this before writing code: the view is your shared surface. SPEC.md keeps track of the app's requirements and design decisions. Keep it up to date as you work on the app. **Building an ecommerce app?** → Read [ecommerce.md](references/ecommerce.md) first. **No SPEC.md?** → Read [discover.md](references/discover.md) first. Nothing else until SPEC.md exists. **SPEC.md exists?** → Read SPEC.md, then foll
Read 11 of 11 text files in the skill.
Installfrom the directory
npx skills add https://github.com/alpic-ai/skybridgeInstalling happens there, not here. We are an index with an opinion, not a mirror.
What is inside itfrom the directory
27 files — names only. The directory does not report sizes.
What the auditors foundfrom the directory
A skill is instructions your agent will follow and scripts it may run, so who checked it matters as much as how many people installed it.
Installs, reading by readingours
Axis starts at 4.3k, not zero — the range is 4.3k to 4.3k.