• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
damixnr

damixnr

OpenCloset

Remix of laurynas/ChatAppSDKStarter
Public
Like
OpenCloset
Home
Code
7
backend
4
frontend
2
shared
3
.vtignore
README.md
TESTING.md
deno.json
Branches
1
Pull requests
Remixes
History
Environment variables
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
Viewing readonly version of main branch: v15
View latest version
README.md

Val Town ChatGPT App SDK Starter

A starter template for building ChatGPT apps with interactive widgets using MCP (Model Context Protocol) on Val Town.

Tech Stack

  • Backend: Hono + MCP Lite + Drizzle ORM + SQLite
  • Widget: React 19 + TanStack Router + OpenAI App SDK

Quick Start

  1. Visit your deployment URL to get the MCP endpoint

  2. Add to ChatGPT:

    • Open ChatGPT settings β†’ Apps & Connectors -> Create (you will need developer mode enabled)
    • Add MCP server with your endpoint URL
  3. Test in ChatGPT:

    • "List all messages"
    • "Add a message: Hello!"
    • "Show me message #1"
    • "Show me a counter widget"
    • "Show me a todo list"
    • "Show me the weather"

Available Tools

Message Board

  • list_messages - Shows all messages in an interactive widget
  • add_message - Adds a new message and shows updated list
  • get_message - Shows details for a specific message

Counter Widget

  • show_counter - Display an interactive counter with increment/decrement buttons
  • increment_counter - Increment the counter by the step amount
  • decrement_counter - Decrement the counter by the step amount
  • reset_counter - Reset the counter to zero

Todo Widget

  • show_todos - Display an interactive todo list with progress tracking

Weather Widget

  • show_weather - Display current weather information for a location

Widget Components

The project includes several React widget components:

  • CounterWidget (/counter) - Interactive counter with +/- buttons and reset
  • TodoWidget (/todo) - Todo list with completion tracking and progress bar
  • WeatherWidget (/weather) - Weather display with temperature, conditions, and stats
  • DemoWidget (/demo) - Showcase page displaying all three widgets together

How It Works

Tools return discriminated unions that drive widget navigation:

{ kind: "message_list", messages: [...] } // β†’ /list route { kind: "message_detail", id: 1, ... } // β†’ /detail/:id route { kind: "counter", count: 5, step: 1 } // β†’ /counter route { kind: "todo_list", todos: [...] } // β†’ /todo route { kind: "weather", location: "NYC", ... } // β†’ /weather route

The widget automatically navigates based on the kind field.

Message Scoping

Messages are automatically scoped using the openai/subject field that ChatGPT includes in request metadata. This provides authless data isolation - each subject gets its own message board.

The scoping happens in tool handlers:

const subject = ctx.request.params._meta?.["openai/subject"]; const messages = await getMessages(subject);

The exact semantics of openai/subject are determined by ChatGPT.

Where do I go from here?

  1. Add tool in backend/mcp/server.ts
  2. Define output schema in shared/types.ts
  3. Create widget component in frontend/widgets/components/
  4. Add route in frontend/widgets/routes.tsx
  5. Update NavigationSync.tsx to handle new kind
FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2025 Val Town, Inc.