Widget Registration Summary

This document summarizes how the three wardrobe widgets (ItemCard, MultiItemCard, OutfitCard) have been registered with the starter template.

✅ Components Created

1. ItemCard (/frontend/widgets/components/ItemCard.tsx)

  • Displays a single wardrobe item with image and category
  • Uses inline styles for consistent appearance
  • Accesses data via globalThis.openai?.toolOutput?.structuredContent

2. MultiItemCard (/frontend/widgets/components/MultiItemCard.tsx)

  • Displays multiple wardrobe items in a 3-column grid
  • Handles empty state gracefully
  • Maps over items array from structured content

3. OutfitCard (/frontend/widgets/components/OutfitCard.tsx)

  • Displays a complete outfit with top and bottom pieces
  • Uses TypeScript CSSProperties for type safety
  • Shows "Today's pick" header with labeled sections

✅ Frontend Registration

Exports in frontend/widgets/widget.tsx

export { default as ItemCard } from "./components/ItemCard.tsx"; export { default as MultiItemCard } from "./components/MultiItemCard.tsx"; export { default as OutfitCard } from "./components/OutfitCard.tsx";

✅ Backend Registration

Resource URIs Defined

const ITEM_CARD_URI = "ui://ItemCard"; const MULTI_ITEM_CARD_URI = "ui://MultiItemCard"; const OUTFIT_CARD_URI = "ui://OutfitCard";

Individual Widget Resources

Each widget is registered as a separate MCP resource with:

  • Unique URI (e.g., ui://ItemCard)
  • Dedicated HTML template that imports the specific component
  • Proper CSP configuration for external domains
  • Skybridge MIME type for ChatGPT integration

MCP Tools Created

  1. show_item_card - Creates single item with sample data
  2. show_multi_item_card - Creates multiple items (1-9 configurable)
  3. show_outfit_card - Creates outfit with top and bottom pieces

✅ Data Schemas

Added to shared/types.ts

export const WardrobeItemSchema = z.object({ id: z.number(), imageUrl: z.string(), category: z.string(), }); export const ItemCardOutputSchema = z.object({ kind: z.literal("item_card"), item: WardrobeItemSchema, }); export const MultiItemCardOutputSchema = z.object({ kind: z.literal("multi_item_card"), items: z.array(WardrobeItemSchema), }); export const OutfitCardOutputSchema = z.object({ kind: z.literal("outfit_card"), top: WardrobeItemSchema, bottom: WardrobeItemSchema, });

✅ Key Features

Sample Data Integration

  • Uses Unsplash images for realistic wardrobe items
  • Random selection from predefined categories
  • Configurable item counts for multi-item displays

Widget Template System

  • Individual HTML templates for each component
  • Automatic component importing and rendering
  • Consistent styling with TailwindCSS and custom styles

MCP Integration

  • Proper _meta configuration with openai/outputTemplate
  • Structured content matching component expectations
  • Error handling for missing data

✅ Testing

ChatGPT Prompts

  • "Show me an item card"
  • "Show me an item card for a dress"
  • "Show me multiple wardrobe items"
  • "Show me 4 wardrobe items"
  • "Show me an outfit"
  • "Create an outfit for me"

Technical Verification

  • ✅ Components transpile correctly
  • ✅ Exports are accessible from widget.tsx
  • ✅ Individual component files serve properly
  • ✅ MCP resources are registered
  • ✅ Sample data generates correctly

Architecture Notes

Individual vs Route-Based Widgets

  • These widgets are individual components (not routes)
  • They render as standalone widgets in ChatGPT
  • Each has its own ui:// resource URI
  • Different from the route-based widgets (Counter, Todo, Weather)

Data Access Pattern

  • Uses globalThis.openai?.toolOutput?.structuredContent
  • Direct access to structured data (no hooks needed)
  • Matches the original component specifications exactly

Styling Approach

  • Uses inline styles for maximum compatibility
  • No dependency on theme hooks or external CSS
  • Consistent with the original component designs

The three wardrobe widgets are now fully registered and ready for use in ChatGPT!