Overview

ChatGPT App Template

A clone-and-go Next.js starter for building OpenAI Apps SDK apps: the kind that render a real UI *inside* ChatGPT. It bundles the parts nobody warns you about: an MCP server with the right OpenAI widget metadata, a Next.js widget that renders in ChatGPT's iframe, and the CORS, asset-prefix, and browser-patching plumbing that otherwise costs you a day of cryptic 404s and hydration errors. Ships with a working Doctor Finder example so the whole pattern is concrete.

TypeScriptReactNext.jsMCPApps SDK
Tailwind CSS
ChatGPT App Template

A ChatGPT app isn’t a normal web app. It’s a Next.js application that ChatGPT calls over MCP and renders inside its own iframe, which means the distance between “hello world” and “a widget that actually displays in ChatGPT” is a minefield of undocumented browser quirks. Your static assets 404 because Next.js resolves them against the wrong origin. Client-side navigation breaks on cross-origin preflight. The ChatGPT host mutates your HTML before React hydrates, so you get hydration errors. None of this is in a tidy guide; you find it the hard way.

I found it the hard way. OpenAI’s widget sandbox is fragile and rule-bound, and a lot of my time went to CORS, asset-prefix, and fetch-origin-rewriting issues that have no obvious fix. This template is that knowledge solidified into a repo you can clone and have a working ChatGPT app running in minutes, instead of spending a day fighting the host environment before you write a single line of your actual product. I didn’t extract it from a shipped app. I built it deliberately as a public, reusable base so that the day I do want a ChatGPT app, the painful part is already done. It’s open for anyone to clone.

What it actually solves

The value isn’t the example app; it’s the plumbing around it, every piece of which exists because it was a problem the first time:

  • An MCP server with the right OpenAI metadata. app/mcp/route.ts registers tools and widget resources with the OpenAI-specific fields ChatGPT looks for (openai/outputTemplate, the toolInvocation loading/loaded states, resultCanProduceWidget) and cross-links a tool to its widget via templateUri so a tool call can actually produce a rendered UI.
  • A widget that lives inside ChatGPT. The root page reads structured tool output through the Apps SDK hooks and renders it as interactive cards, supports fullscreen mode, and degrades to a helpful banner when someone opens it outside ChatGPT.
  • The asset-prefix fix. A one-line assetPrefix config that stops Next.js from trying to load /_next/ assets from the iframe URL: the difference between a styled widget and a wall of 404s. This was the single biggest time-sink for me; CSS just silently refused to load until I tracked down that the assets were resolving against the wrong origin.
  • CORS for React Server Components. Middleware that answers the preflight requests RSC fires during client-side navigation, which otherwise silently break.
  • A browser bootstrap for the iframe. <NextChatSDKBootstrap> patches the quirks of running inside the ChatGPT host: history.pushState/replaceState, fetch origin rewriting, and the <html> attribute mutations the host injects before hydration.
  • Vercel-aware base URLs. baseUrl.ts auto-detects Vercel’s production and preview environment variables so assets and runtime fetches resolve correctly across every deployment.

Why Next.js, when OpenAI recommends plain React

A ChatGPT app doesn’t have to be a Next.js app; OpenAI’s own starter leans toward plain React. I went Next.js on purpose, for a reason that’s really the whole thesis of the project: a ChatGPT app is a web app that happens to live inside ChatGPT, and I wanted it to be able to leave. Building on the framework I use for everything means this isn’t a dead-end widget; it’s the seed of a proper Next.js application. The same codebase can grow real pages and routes, deploy to Vercel as a standalone site, and let a user expand out of the ChatGPT iframe to the actual website. Most templates get you a widget; this one gets you a widget that can become a product.

A concrete example, not abstract SDK code

Rather than ship empty scaffolding, the template includes a small Doctor Finder app: a find_doctor MCP tool searches mock data by symptom or specialty, returns structured output plus the widget templateUri, and ChatGPT renders the results as doctor cards in the iframe. It makes the end-to-end flow from tool call to structured result to rendered widget legible at a glance, and it’s built to be torn out: swap the sample domain model and UI for your own tools, whether that’s commerce, scheduling, an ops dashboard, or an internal assistant.

It’s Next.js 15 and React 19 on Bun, Tailwind CSS 4, Apache-2.0 licensed, and deploys cleanly to Vercel. Connect the /mcp URL as a ChatGPT connector and you’re live. It’s also the practical companion to my deeper Apps SDK work in Agentbox, where I reverse-engineered the same SDK’s file model to move data out of ChatGPT.

Use and to navigate