DEV Community

Cover image for Build Your Own ChatGPT App (Run It Locally)
Julien Avezou
Julien Avezou

Posted on

Build Your Own ChatGPT App (Run It Locally)

ChatGPT recently opened submissions for their Apps feature to developers, which is a way to display interactive widgets from third-party apps directly into conversations. This opens up interesting opportunities to enhance user experience directly within ChatGPT by offering more than just text interactions.

In this article, I will share my experience exploring this feature so you can easily test and create your own ChatGPT App locally to get started.

I will start by outlining the basics of what a ChatGPT App is and how it works. I will then offer a step-by-step tutorial on how to quickly get started with your own ChatGPT App locally for quick prototyping and experimentation.


What is a ChatGPT App?

A ChatGPT App is an interactive widget that appears directly within the chat from the conversation context or manual triggering.

It can be broken down into 3 main components:

  1. MCP Server - The backend that defines tools which you can think of as functions the model can call (in this case ChatGPTs), and resources (UI templates that ChatGPT renders).

  2. Widget - HTML that runs in a sandboxed iframe with its own state, event handling, and direct communication with your backend through the window.openai object that ChatGPT injects. This object offers different interaction options such as direct tool calls (window.openai.callTool()) or a follow-up message (window.openai.sendFollowUpMessage()) which sends a message back into the chat to keep the conversational loop going.

  3. ChatGPT - The host which orchestrates the tool calling, rendering of the widget and the conversation state.

An example of a tool definition is as follows:

Tool: find_houses

# Description used by ChatGPT to decide when to trigger the tool
Description: "Finds houses by location and number of rooms"

# Inputs schema outlines the parameters
Inputs: location (required), number_rooms (optional)

# Outputs defines which resource to render with the data as UI
Output: → ui://widget/list.html
Enter fullscreen mode Exit fullscreen mode

It is useful to visualize the full flow as a diagram:


Let's now build our own ChatGPT App

Here is a simple example of a ChatGPT App I built for local testing. It's open source so you can use the repo as a template as we move along this tutorial.

Let's create the App

The repo structure will look something like this:

chatgpt-app/
├─ public/
│  └─ widget.html
├─ server.js
├─ package.json
└─ README.md
Enter fullscreen mode Exit fullscreen mode

Create your files and adapt your own logic for the widget and server. For the server, register the tools and resources you want. For the widget add the UI elements, state and event handling you want. Please refer to the files in my open source repo for inspiration if needed.

Let's run the App

ChatGPT needs an HTTPS URL to reach our local server. For this tutorial we will use ngrok to provide us with an HTTPS URL.

# 1) create repo + install
npm install

# 2) run local MCP
npm run dev

# 3) in another terminal
ngrok http 8787
# copy https://....ngrok.app and add /mcp
Enter fullscreen mode Exit fullscreen mode

Let's connect this App to ChatGPT
You first need to enable developer mode for ChatGPT. This allows you to add unverified connectors. Memory is disabled in this mode.
Settings > Apps > Advanced settings > Developer mode (toggle)

You can then create your App (ie. establish the connection between your MCP server and the ChatGPT host)
Settings > Apps > Create App

In the form, the connector needs to point to the HTTPS URL from ngrok with /mcp, for eg. https://abcd-1234.ngrok.app/mcp
For this demo we will choose 'no authentication'.

Let's trigger the App
ChatGPT can surface an App based on context or explicit tagging.

And there you go! You should now have your own ChatGPT App running locally. 👏👏👏


Before we end, here are a couple of learnings based on personal experience developing my App:

  • due to caching, I often found it faster to delete the connector entirely and establish the connection again instead of trying ot figure out which parts of the UI or metadata were cached
  • I caused unnecessary re-renders and behavior that was hard to debug when I leaned heavily on tool calls for state updates. Moving more state locally to the widget made the setup more reliable.

This tutorial is intentionally limited to local development and fast prototyping. It therefore doesn't cover important aspects such as security, authentication, in-depth state management and privacy which are necessary before moving to production. So I strongly advise you to read the official documentation and implement best practices to mitigate any risks before going live. A few considerations on top of mind include idempotent calls, rate limiting and robust error handling.


With over 800 million weekly active users on ChatGPT, ChatGPT Apps could be a huge opportunity for developers to tap into.

What do you think? Is this just another feature or do you see potential in developing your own ChatGPT App?

Top comments (7)

Collapse
 
itsugo profile image
Aryan Choudhary

I'm not sure, but it seems to me this is exactly the kind of experimentation I've been wanting to get into - integrating ChatGPT into a custom app. The idea of breaking down the process into these three components really helps me visualize the whole thing. I'm definitely going to have to dig into the open-source repository and see if I can learn from their example.

Collapse
 
javz profile image
Julien Avezou

I can see many use cases for products to improve their UX via ChatGPT apps through a clean UI interface, not only text interactions.
I am happy to hear you find the tutorial useful. I hope you have fun experimenting and do share anything you end up building. Would love to see that.

Collapse
 
abewheeler profile image
Abe Wheeler

A couple other tips to help with caching:

  1. Give every new Resource build a unique URI
  2. Refresh the App in ChatGPT (as you mentioned)
  3. Start a new ChatGPT conversation

It's a huge pain, but this is the only way I found to absolutely guarantee a refresh! To skip most refreshes, you can use sunpeak.ai/ (full disclosure, I made it), it has a development server with HMR baked in so your UI changes are reflected instantly in ChatGPT!

Collapse
 
javz profile image
Julien Avezou

Thanks for sharing, this would have been helpful for my caching issues indeed. Nice framework.

Collapse
 
mulishagraves_7969 profile image
Mulisha Graves • Edited

This is exactly what I've been wanting to do! Unfortunately I don't know anything about actually coding and I really don't know what half of the stuff means. I've ran my own local with Sillytavern, but it kinda feels like I'm cheating and I would love to know more about all of this. It seems like it's pretty simple, but I'm sure I can probably mess something up lol. If you ever have any spare time would you consider teaching me some things? Thank you for the post!

Collapse
 
javz profile image
Julien Avezou • Edited

Hi Mulisha! Thanks for the kind words!
It's awesome that you are curious about this and about learning.
What is it in particular that you want to learn?
There are a lot of free courses that are very high quality and that allow you to learn at your own pace. freecodecamp is one of them for example, I would suggest checking them out for inspiration

Collapse
 
mulishagraves_7969 profile image
Mulisha Graves

Thank you for the info. I will check out those things. I'm actually just trying to build my own local LLM that is a replacement for Chatgpt because I can't stand the new model they have now and I want the 4o model back. I was working with that model to do exactly that and move all of my memories and everything to it, but now I have been dealing with the new model telling me lies about how to do it and making json cards that are nothing like the old model made me. Thankfully I saved all the things and instructions for doing it. I'm just running into a few problems with some things I don't quite understand yet.