<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zach Park</title>
    <description>The latest articles on DEV Community by Zach Park (@zach_park_8558d8374a08a58).</description>
    <link>https://dev.to/zach_park_8558d8374a08a58</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3514570%2F7e10e47a-124f-431f-8ca0-97a3e4d4bace.png</url>
      <title>DEV Community: Zach Park</title>
      <link>https://dev.to/zach_park_8558d8374a08a58</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zach_park_8558d8374a08a58"/>
    <language>en</language>
    <item>
      <title>Build Your First Apps in ChatGPT | A step-by-step guide building with the Apps SDK</title>
      <dc:creator>Zach Park</dc:creator>
      <pubDate>Wed, 05 Nov 2025 08:31:47 +0000</pubDate>
      <link>https://dev.to/zach_park_8558d8374a08a58/build-your-first-apps-in-chatgpt-a-step-by-step-guide-building-with-the-apps-sdk-400m</link>
      <guid>https://dev.to/zach_park_8558d8374a08a58/build-your-first-apps-in-chatgpt-a-step-by-step-guide-building-with-the-apps-sdk-400m</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;As AI becomes a core part of everyday workflows, ChatGPT has become second nature for billions of people. But until now, ChatGPT was mostly about conversation, not interaction.&lt;/p&gt;

&lt;p&gt;What if you could chat with apps directly inside ChatGPT, from booking hotels to designing slides, all in one place?&lt;/p&gt;

&lt;p&gt;That's exactly what Apps in ChatGPT bring to the table. Powered by the new Apps SDK, developers can now build interactive, context-aware apps that live inside ChatGPT.&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn how to build your own ChatGPT app with using &lt;a href="https://www.fastapps.org/" rel="noopener noreferrer"&gt;FastApps framework&lt;/a&gt;. We'll walk through each part of the code and I'll explain how it works.&lt;/p&gt;

&lt;p&gt;By the end, you'll have a running ChatGPT app that can dynamically show widgets directly in your ChatGPT environment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 0. How does apps in ChatGPT work?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wxtglqk4xomlcimi5en.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wxtglqk4xomlcimi5en.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A ChatGPT app is basically a mcp server that serves widgets.&lt;/p&gt;

&lt;h2&gt;
  
  
  How ChatGPT Apps Work
&lt;/h2&gt;

&lt;p&gt;As you can see from the picture above, it all starts by ChatGPT triggering our app based on the user’s message. The user’s message is sent to our app.&lt;/p&gt;

&lt;p&gt;Our app then chooses a mcp tool that best matches the user’s message. For example when the user asks “I want to buy clothes”, our app will choose a mcp tool like “ShowClothes”.&lt;/p&gt;

&lt;p&gt;Then, the tool returns widgets and data. A widget is the component that’s shown at ChatGPT, and the data is the response that ChatGPT could use.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 1. Install FastApps
&lt;/h1&gt;

&lt;p&gt;Now as you know how ChatGPT apps work, we will dive into building it. We will be using FastApps, which is the open-source framework for building ChatGPT apps.&lt;/p&gt;

&lt;p&gt;First, install FastApps with uv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;fastapps
uv tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; fastapps &lt;span class="c"&gt;# Update to the latest version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 2. Initialize a New App
&lt;/h1&gt;

&lt;p&gt;Once installed, you can quickly start by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fastapps init my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
fastapps dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkp190iladx208eouowc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkp190iladx208eouowc.png" alt=" " width="800" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it. You’ll see an image with a public URL automatically generated via Cloudflare Tunnel.&lt;/p&gt;

&lt;p&gt;Your MCP server will be available at the /mcp endpoint.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-public-url.trycloudflare.com/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 3. Test Your App
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Option A: Test with MCPJam Inspector
&lt;/h2&gt;

&lt;p&gt;Use the MCPJam Inspector to connect and test your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @mcpjam/inspector@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, enter your public URL + /mcp.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option B: Test in ChatGPT
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fix3kbti3dw96abqfdn00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fix3kbti3dw96abqfdn00.png" alt=" " width="690" height="903"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In ChatGPT, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Settings → Connectors&lt;/li&gt;
&lt;li&gt;Add your 'public URL + /mcp'&lt;/li&gt;
&lt;li&gt;Select 'No authentication'&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Step 4. Create More Widgets
&lt;/h1&gt;

&lt;p&gt;You can add new widgets anytime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fastapps create additional-widget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 5. Edit Your Widget
&lt;/h1&gt;

&lt;p&gt;You only need to modify two folders:&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣ &lt;code&gt;server/tools/&lt;/code&gt; — MCP tool
&lt;/h2&gt;

&lt;p&gt;Define your app logic and interaction schema.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# server/tools/my_widget_tool.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapps&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConfigDict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyWidgetInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConfigDict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;populate_by_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyWidgetTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-widget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My Widget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;input_schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyWidgetInput&lt;/span&gt;
    &lt;span class="n"&gt;invoking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;invoked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;widget_csp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;connect_domains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resource_domains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MyWidgetInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each MCP tools contain various attributes that identifies the property of the tool. Looking at the graph below, you could figure out what each attributes mean.&lt;/p&gt;

&lt;p&gt;For a more detailed explanation, you could check out the Fastapps docs&lt;/p&gt;




&lt;h3&gt;
  
  
  Required Class Attributes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;identifier&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;Unique widget identifier. Must match the widget folder name in widgets/. Used as the resource URI identifier&lt;/td&gt;
&lt;td&gt;"greeting" for widgets/greeting/&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;Human-readable tool name displayed in ChatGPT interface. Shown when the model considers calling this tool&lt;/td&gt;
&lt;td&gt;"Show Greeting Widget"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;input_schema&lt;/td&gt;
&lt;td&gt;Type[BaseModel]&lt;/td&gt;
&lt;td&gt;Pydantic model defining the tool’s input parameters. ChatGPT uses this JSON schema to understand when and how to call your tool&lt;/td&gt;
&lt;td&gt;GreetingInput&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invoking&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;Short, localized status message shown to users while the tool is being executed. Maps to openai/toolInvocation/invoking&lt;/td&gt;
&lt;td&gt;"Preparing your greeting…"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invoked&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;Short, localized status message shown to users after the tool completes. Maps to openai/toolInvocation/invoked&lt;/td&gt;
&lt;td&gt;"Greeting ready!"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Optional Class Attributes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;Optional tool description. Helps the model understand when to use this tool&lt;/td&gt;
&lt;td&gt;"Display a personalized greeting widget"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;widget_accessible&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Whether the widget can initiate tool calls from its React component&lt;/td&gt;
&lt;td&gt;True for interactive widgets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  2️⃣ &lt;code&gt;widgets/&lt;/code&gt; — Frontend UI (React)
&lt;/h2&gt;

&lt;p&gt;This folder contains UI components shown in ChatGPT.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// widgets/my-widget/index.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWidgetProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fastapps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyWidget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWidgetProps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;40px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#4A90E2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Widgets are React components with additional hooks that interact with ChatGPT.&lt;/p&gt;

&lt;p&gt;For a more detailed explanation, you could check out the FastApps docs.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 6. Deploy your ChatGPT app for public use
&lt;/h1&gt;

&lt;p&gt;You can directly deploy your ChatGPT app from your CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fastapps cloud deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow step-by-step instructions from the CLI.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Working with FastApps turned out to be much easier than I expected. Spinning up an MCP server, adding tools, and seeing widgets appear inside ChatGPT felt surprisingly quick and smooth. With just a bit of Python and a simple React UI, you can have a real, interactive app running in minutes.&lt;/p&gt;

&lt;p&gt;If you’ve been curious about building for ChatGPT, this the fastest way to start. I hope this walkthrough helps you try it yourself. It's lightweight, fun, and genuinely useful.&lt;/p&gt;

</description>
      <category>appsinchatgpt</category>
      <category>appssdk</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Create Your First ChatGPT App</title>
      <dc:creator>Zach Park</dc:creator>
      <pubDate>Tue, 04 Nov 2025 07:41:30 +0000</pubDate>
      <link>https://dev.to/zach_park_8558d8374a08a58/create-your-first-chatgpt-app-eda</link>
      <guid>https://dev.to/zach_park_8558d8374a08a58/create-your-first-chatgpt-app-eda</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;ChatGPT has become second nature for billions of people. But historically, it has mainly focused on conversation, not interaction.&lt;/p&gt;

&lt;p&gt;What if you could chat with apps directly inside ChatGPT such as booking hotels, designing slides, and more without ever leaving the conversation?&lt;/p&gt;

&lt;p&gt;That’s now possible with ChatGPT Apps.&lt;/p&gt;

&lt;p&gt;Powered by the new Apps SDK, developers can build interactive, context-aware apps that run natively inside ChatGPT.&lt;/p&gt;

&lt;p&gt;In this tutorial, you’ll learn how to build your first ChatGPT app using FastApps.&lt;br&gt;
We’ll walk through setup → development → deployment.&lt;br&gt;
By the end, you’ll have an app that shows widgets directly inside ChatGPT.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Do ChatGPT Apps Work?
&lt;/h2&gt;

&lt;p&gt;A ChatGPT app is essentially an MCP server that serves widgets.&lt;/p&gt;

&lt;p&gt;[High-level flow]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ChatGPT triggers your app based on user input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user message is forwarded to your app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The app selects an MCP tool based on context.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: When a user asks, “I want to buy clothes,” your app may call a tool like ShowClothes.&lt;/p&gt;

&lt;p&gt;The tool returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Widgets → UI components displayed in ChatGPT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data → used in the response logic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets you create rich interfaces + logic without leaving the conversation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Install FastApps
&lt;/h2&gt;

&lt;p&gt;Install FastApps with uv:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;uv tool install fastapps&lt;br&gt;
uv tool install --upgrade fastapps&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Initialize a New App
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fastapps init my-app&lt;br&gt;
cd my-app&lt;br&gt;
fastapps dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You’ll get a public URL via Cloudflare Tunnel.&lt;br&gt;
Your MCP server lives at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://your-public-url.trycloudflare.com/mcp" rel="noopener noreferrer"&gt;https://your-public-url.trycloudflare.com/mcp&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Test Your App
&lt;/h2&gt;

&lt;p&gt;✅ Option A — MCPJam Inspector&lt;br&gt;
&lt;code&gt;npx @mcpjam/inspector@latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then enter:&lt;/p&gt;

&lt;p&gt;/mcp&lt;/p&gt;

&lt;p&gt;✅ Option B — Inside ChatGPT&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to Settings → Connectors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your public MCP endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select No authentication&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 4: Create More Widgets
&lt;/h2&gt;

&lt;p&gt;Add new widgets anytime:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fastapps create additional-widget&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Edit Your Widget
&lt;/h2&gt;

&lt;p&gt;You’ll mainly work inside two folders:&lt;/p&gt;

&lt;p&gt;server/tools/&lt;br&gt;
widgets/&lt;/p&gt;

&lt;p&gt;1) MCP Tool — server/tools/&lt;/p&gt;

&lt;p&gt;Defines backend logic + input schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# server/tools/my_widget_tool.py
from fastapps import BaseWidget, Field, ConfigDict
from pydantic import BaseModel
from typing import Dict, Any

class MyWidgetInput(BaseModel):
    model_config = ConfigDict(populate_by_name=True)
    name: str = Field(default="World")

class MyWidgetTool(BaseWidget):
    identifier = "my-widget"
    title = "My Widget"
    input_schema = MyWidgetInput
    invoking = "Processing..."
    invoked = "Done!"

    widget_csp = {
        "connect_domains": [],
        "resource_domains": []
    }

    async def execute(self, input_data: MyWidgetInput) -&amp;gt; Dict[str, Any]:
        return {
            "name": input_data.name,
            "message": f"Hello, {input_data.name}!"
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Widget UI — widgets/&lt;/p&gt;

&lt;p&gt;React UI displayed inside ChatGPT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// widgets/my-widget/index.jsx
import React from 'react';
import { useWidgetProps } from 'fastapps';

export default function MyWidget() {
  const props = useWidgetProps();

  return (
    &amp;lt;div style={{
      padding: '40px',
      textAlign: 'center',
      background: '#4A90E2',
      color: 'white',
      borderRadius: '12px'
    }}&amp;gt;
      &amp;lt;h1&amp;gt;{props.message}&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;Welcome, {props.name}!&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Widgets support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;React + hooks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tool interaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rich chat-native UI&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Deploy Your App
&lt;/h2&gt;

&lt;p&gt;Deploy via CLI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;fastapps cloud deploy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s a &lt;a href="https://www.fastapps.org/blog/build-your-first-chatgpt-app" rel="noopener noreferrer"&gt;detailed guide&lt;/a&gt; on how to build ChatGPT apps.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>How ChatGPT Apps Really Work: Inside the OpenAI Apps SDK</title>
      <dc:creator>Zach Park</dc:creator>
      <pubDate>Fri, 24 Oct 2025 02:12:00 +0000</pubDate>
      <link>https://dev.to/zach_park_8558d8374a08a58/how-chatgpt-apps-really-work-inside-the-openai-apps-sdk-2k83</link>
      <guid>https://dev.to/zach_park_8558d8374a08a58/how-chatgpt-apps-really-work-inside-the-openai-apps-sdk-2k83</guid>
      <description>&lt;h2&gt;
  
  
  What Are ChatGPT Apps?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://developers.openai.com/apps-sdk/" rel="noopener noreferrer"&gt;OpenAI Apps SDK&lt;/a&gt; lets developers build interactive experiences that live directly inside ChatGPT.&lt;br&gt;
Instead of opening a separate site, your app appears inline, as part of the chat itself.&lt;/p&gt;

&lt;p&gt;Each app is essentially a mini web app running in a sandboxed iframe. Its frontend communicates with ChatGPT through the window.openai bridge, syncing data with your backend MCP server and the model’s reasoning in real time.&lt;/p&gt;
&lt;h2&gt;
  
  
  MCP and Widgets
&lt;/h2&gt;

&lt;p&gt;Every ChatGPT app has two main parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP server: hosts your tools and handles logic&lt;/li&gt;
&lt;li&gt;Widgets: the visual layer rendered inside ChatGPT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Model Context Protocol (MCP) connects models to external data and tools, ensuring the UI, server, and model stay in sync.&lt;br&gt;
Widgets are fetched from the MCP server and displayed inline — charts, tables, forms, anything interactive — all while staying inside the chat interface.&lt;/p&gt;

&lt;p&gt;Because MCP supports streaming and SSE, Apps SDK experiences feel fast, real-time, and deeply conversational.&lt;/p&gt;
&lt;h2&gt;
  
  
  High-Level Workflow
&lt;/h2&gt;

&lt;p&gt;Here’s the flow when a user says something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Show my recently played songs on Spotify.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model triggers a tool&lt;/strong&gt; → ChatGPT calls your MCP server (e.g., getRecentTracks).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MCP executes + returns metadata&lt;/strong&gt; → Data + widget identifier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Widget loads&lt;/strong&gt; → React-based component is fetched.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ChatGPT renders it inline&lt;/strong&gt; → Runs securely in a sandboxed iframe.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Through this sequence, model reasoning, backend logic, and frontend rendering work together seamlessly.&lt;/p&gt;
&lt;h2&gt;
  
  
  The window.openai Bridge
&lt;/h2&gt;

&lt;p&gt;window.openai is what connects your widget (React component) to ChatGPT.&lt;br&gt;
It gives your app access to theme, language, state, and even lets you invoke tools or send messages.&lt;/p&gt;

&lt;p&gt;It’s a two-way bridge:&lt;br&gt;
Your widget doesn’t just display data - it can also act inside the conversation.&lt;br&gt;
This is what makes ChatGPT apps feel native rather than embedded.&lt;/p&gt;
&lt;h2&gt;
  
  
  User Experience Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;*&lt;em&gt;Discovery *&lt;/em&gt;- ChatGPT suggests or surfaces your app contextually (e.g., “Spotify, show my playlist”).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inline interaction&lt;/strong&gt; - The widget renders right in chat, matching ChatGPT’s layout and theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context continuity&lt;/strong&gt; - The app stays active across turns, preserving state and conversational flow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Building Apps in Minutes with FastApps
&lt;/h2&gt;

&lt;p&gt;The OpenAI Apps SDK provides the foundation, but you don’t have to start from scratch.&lt;br&gt;
&lt;a href="https://github.com/DooiLabs/FastApps" rel="noopener noreferrer"&gt;FastApps&lt;/a&gt; wraps the MCP server and SDK into a single Python-first framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fastapps
fastapps init my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This spins up a ready-to-run ChatGPT app with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server: Preconfigured MCP backend + auto-discovery&lt;/li&gt;
&lt;li&gt;Widgets: React components wired to window.openai&lt;/li&gt;
&lt;li&gt;Build &amp;amp; Dev: Live reload + ngrok tunnel built in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then define your tool and UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# server/tools/my_widget_tool.py
class HelloTool(BaseWidget):
    async def execute(self, input):
        return {"message": f"Hello, {input.name}!"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// widgets/my-widget/index.jsx
export default function HelloWidget() {
  const props = useWidgetProps();
  return &amp;lt;h1&amp;gt;{props.message}&amp;lt;/h1&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
fastapps dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantly live in ChatGPT. No config, no boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The OpenAI Apps SDK feels like the early architecture of an agentic internet where models, tools, and humans coexist in one continuous conversational ecosystem. You can see the full article &lt;a href="https://www.fastapps.org/blog/inside-the-chatgpt-apps-sdk-how-it-actually-works" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to build ChatGPT apps fast, FastApps makes it effortless.&lt;br&gt;
Start today and deploy your first widget in minutes.&lt;/p&gt;

</description>
      <category>openai</category>
      <category>chatgptapps</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>Why Apps in ChatGPT Are the Future</title>
      <dc:creator>Zach Park</dc:creator>
      <pubDate>Sat, 11 Oct 2025 04:54:53 +0000</pubDate>
      <link>https://dev.to/zach_park_8558d8374a08a58/why-apps-in-chatgpt-are-the-future-2pen</link>
      <guid>https://dev.to/zach_park_8558d8374a08a58/why-apps-in-chatgpt-are-the-future-2pen</guid>
      <description>&lt;p&gt;When Apple launched the App Store in 2008, it changed the way we thought about software: instead of heavy installations, we had lightweight apps that followed us everywhere. Today we stand on the brink of another inflection point. ChatGPT apps aren’t just a novelty bolted onto a chatbot. &lt;strong&gt;They signal a new way of interacting with software, one that revolves around conversation rather than screens.&lt;/strong&gt; These apps still run on servers and devices, but the experience now sits beyond the GUI layer, in the intelligence that understands and responds to what we say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the App Store Moment
&lt;/h2&gt;

&lt;p&gt;ChatGPT apps arrive at a moment when computing is ripe for reinvention. For decades, software depended on tapping and swiping; now, natural language is becoming the primary interface. In practice, ChatGPT apps still rely on a back‑end server and a front‑end component that runs in an iframe inside ChatGPT. But from the user’s perspective, the interaction flows through conversation rather than a discrete user interface. OpenAI has released the Apps SDK in preview and plans to open app submissions later this year. &lt;strong&gt;The promise is that, just as the App Store democratized mobile software, the ChatGPT ecosystem could democratize software that lives in dialogue.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  From Prompts to Agents — The Inversion of the Software Stack
&lt;/h2&gt;

&lt;p&gt;Traditional apps integrate AI as a feature: voice search or predictive text sits inside an app that is otherwise built on a standard operating system. ChatGPT apps invert that relationship. Developers define tools and UI components, but the intelligence layer, the GPT mode, becomes the primary runtime. Each app is anchored by an MCP server that exposes tools the model can call, enforces authentication, and packages structured data with an HTML template for the client to render. Instead of simply returning text, the app can trigger actions, display interactive widgets, and update its state via window.openai calls. In this sense, the AI isn’t just augmenting an app; it orchestrates the workflow itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unified Conversational UX — Multimodality, Memory and Natural Language
&lt;/h2&gt;

&lt;p&gt;Because ChatGPT understands language, images and even voice inputs, apps can span modalities. A single component can display a card with search results, accept follow‑up questions, call an external API via the MCP tool and return a refreshed dataset. Combined with ChatGPT’s built‑in memory, this creates experiences that feel continuous: the app remembers context across turns and adapts its output accordingly. &lt;/p&gt;

&lt;p&gt;Each GPT App still has its own interface, built through the Apps SDK’s component system, but it lives inside the conversation instead of outside it. That makes it lightweight, contextual, and instantly actionable. Today, users still need to connect or explicitly trigger a GPT App, but the direction is unmistakable. Over time, apps will feel less like separate tools and more like natural extensions of the dialogue itself. &lt;strong&gt;The interface becomes conversational, living inside the dialogue rather than outside it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Unprecedented Distribution for Developers
&lt;/h2&gt;

&lt;p&gt;One of the most compelling aspects of ChatGPT apps is the distribution potential. ChatGPT counts hundreds of millions of weekly users globally, giving developers a large audience from day one. While getting into the ecosystem does require building an MCP server, hosting it on a secure HTTPS endpoint and registering a connector via ChatGPT’s developer mode, the friction is lower than traditional app stores. &lt;strong&gt;A single integration can instantly reach a global user base already inside ChatGPT.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT as the Agentic Ecosystem for Apps
&lt;/h2&gt;

&lt;p&gt;What makes the ecosystem truly novel is how apps cooperate. Each app defines one or more tools, functions the model can call, plus a corresponding UI component. ChatGPT orchestrates when to call which tool in MCP and merges the results into the conversation. Developers don’t need to worry about drawing windows or implementing navigation; they focus on the task their tool performs and the data it returns. The best apps are conversational, time‑bound and visually succinct; they extend ChatGPT rather than replicate existing web workflows. Think booking a flight, ordering food or summarizing the morning’s calendar — tasks that can be completed in a few turns and presented in a clear card. &lt;strong&gt;This agentic model turns ChatGPT into more than a host; it becomes the mediator that connects intent to action.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Monetization
&lt;/h2&gt;

&lt;p&gt;Every platform needs an economic model, and ChatGPT apps are no exception. OpenAI already offers subscription plans for ChatGPT, and the company has signaled that monetization policies for apps will be announced when the submission process opens. Although details are still forthcoming, it is easy to see the potential: usage‑based billing, revenue sharing and premium features could create a marketplace akin to the App Store, but oriented around actions rather than downloads. For developers, the allure is clear: &lt;strong&gt;a single integration could reach millions of users and generate revenue without the overhead of mobile app development.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why OpenAI Won’t Walk Away
&lt;/h2&gt;

&lt;p&gt;OpenAI collaborating with Jony Ive on a new hardware device hint at where this ecosystem could go. Imagine a voice‑first device whose primary interface is conversation; instead of launching apps via icons, you call on GPT‑powered tools. In such a scenario, the Apps SDK would be the application layer, GPT the operating system, and the device the input/output surface. While no official device has been announced, the direction is logical: to deliver seamless, multimodal experiences across phones, laptops and dedicated hardware, OpenAI needs an app platform tightly integrated with its models. That is why it’s investing in MCP servers, design guidelines and developer policies now, because the apps created today will populate the devices of tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Intelligence Platform Era
&lt;/h2&gt;

&lt;p&gt;We’re moving from a world where software lives on devices to one where software lives inside intelligence. ChatGPT apps still rely on web servers, SDKs and deployment pipelines, but the user experience is shifting into dialogue. For developers, the platform offers global reach and a chance to build on top of one of the most capable AI models. For users, it promises smarter, more integrated workflows that happen naturally in conversation. &lt;strong&gt;Just as the App Store defined the smartphone era, GPT‑powered apps are poised to define the intelligence era and OpenAI’s early moves suggest it intends to lead the way.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Still Missing And What We’re Building Next
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;As exciting as this ecosystem is, building ChatGPT Apps today still isn’t easy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developers have to wire up MCP servers, handle authentication, define tools, and manually decide how each app is triggered within a conversation. &lt;strong&gt;There’s no simple framework for routing intent, managing context, or connecting multiple GPT Apps smoothly which makes rapid experimentation difficult even for experienced developers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s the gap we’re working to close.&lt;/p&gt;

&lt;p&gt;We released &lt;strong&gt;&lt;a href="https://github.com/DooiLabs/FastApps" rel="noopener noreferrer"&gt;FastApps&lt;/a&gt;, an open source, zero-boilerplate framework for building ChatGPT apps&lt;/strong&gt; powered by OpenAI’s Apps SDK and FastMCP.&lt;/p&gt;

&lt;p&gt;You can start building ChatGPT apps with a single line input.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>ux</category>
      <category>ai</category>
      <category>ui</category>
    </item>
    <item>
      <title>We couldn’t stand generic AI websites anymore.</title>
      <dc:creator>Zach Park</dc:creator>
      <pubDate>Fri, 03 Oct 2025 09:02:30 +0000</pubDate>
      <link>https://dev.to/zach_park_8558d8374a08a58/we-couldnt-stand-generic-ai-websites-anymore-28dl</link>
      <guid>https://dev.to/zach_park_8558d8374a08a58/we-couldnt-stand-generic-ai-websites-anymore-28dl</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;Every AI web builder we tried gave us the same problem: the sites looked cookie-cutter, stiff, and far from what a professional designer would make. Templates everywhere, zero personality. If this continues, we’ll drown in a sea of copy-paste, ugly websites.&lt;/p&gt;

&lt;p&gt;So we built Moov, the first coding agent that builds designer-level websites. With a single prompt, Moov generates sites with the right tone, imagery, and motion. It’s like Lovable + Framer, but with a true design sensibility baked in.&lt;/p&gt;

&lt;p&gt;Editing is seamless. Hover over any element and Moov suggests tailored design tweaks you can instantly apply. Images can be transformed into videos, and your own Figma components can be locked into the design. When you’re ready, everything exports as clean, production-ready code straight to GitHub.&lt;/p&gt;

&lt;p&gt;Moov is now in beta. You can see the demo video through the link below.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>ai</category>
      <category>design</category>
    </item>
  </channel>
</rss>
