Project 2: Hello World Widget

Build your first ChatGPT component with deterministic states and bridge-driven interactions.

Quick Reference

Attribute Value
Difficulty Beginner
Time Estimate Weekend
Main Programming Language TypeScript (Alternatives: JavaScript, Svelte)
Coolness Level Level 3
Business Potential Foundation Feature
Prerequisites Basic component state, async calls, event handling
Key Topics window.openai, UI state machine, result rendering

1. Learning Objectives

  1. Build a component that renders tool output in ChatGPT.
  2. Handle loading, success, empty, and error states.
  3. Trigger safe follow-up actions through the bridge.
  4. Persist minimal widget state across turns.

2. All Theory Needed (Per-Concept Breakdown)

Bridge-Driven UI State Machines

Fundamentals A widget inside ChatGPT is not a standalone web app. It receives tool outputs and user actions inside a conversation-driven host. This means your state transitions must be explicit and recoverable. The model may trigger calls, users may retry, and output can arrive asynchronously. A state machine approach avoids hidden transitions and stale rendering.

Deep Dive into the concept State design must separate transient UI state from server truth. Keep local state for interactions (expanded card, selected row), and keep server-authoritative state for business data (task status, totals). Use clear transitions: idle -> loading -> success and loading -> error -> retry. Include explicit partial state when only some data is available. Ensure each interaction has deterministic outcomes even if the same action fires twice.

Bridge interactions should be treated as intent events. Avoid passing large mutable objects; pass stable IDs and required arguments. Keep render logic idempotent and based on latest known server result plus controlled local overlays.

Minimal concrete example

onRefreshClick:
  setState(loading)
  bridge.callTool("list_tasks", { filter:"today" })
  if success -> setState(success)
  if failure -> setState(error)

3. Project Specification

3.1 What You Will Build

A task summary widget card with refresh and detail actions.

3.2 Functional Requirements

  1. Render tool output card list.
  2. Support refresh action.
  3. Show deterministic state transitions.
  4. Persist user-selected view mode.

3.3 Non-Functional Requirements

  • Performance: perceived update under 2 seconds for fixture payload.
  • Reliability: no duplicate action side effects.
  • Usability: clear loading/error messaging.

3.4 Real World Outcome

User asks for current tasks -> Widget appears.
User clicks Refresh -> spinner appears.
Tool returns -> Widget updates with new timestamp.

4. Solution Architecture

Tool output -> view model mapper -> widget state reducer -> render layer
                     ^                               |
                     |                               v
                bridge events <---------------- user actions

5. Implementation Guide

5.1 The Core Question You’re Answering

“How do I keep a conversational widget understandable when asynchronous events overlap?”

5.2 Concepts You Must Understand First

  1. Render state transitions.
  2. Client/server state boundaries.
  3. Idempotent action handling.

5.3 Questions to Guide Your Design

  1. Which values are persisted between turns?
  2. How are error retries surfaced?
  3. Which actions are disabled while requests run?

5.4 Thinking Exercise

Draw a transition table for all UI states and triggers.

5.5 The Interview Questions They’ll Ask

  1. Why use state machines for widgets?
  2. How do you avoid stale UI snapshots?
  3. What should be persisted in widget state?
  4. How do you handle duplicate clicks safely?
  5. How do you test asynchronous UI transitions?

5.6 Hints in Layers

  • Hint 1: Build states first, styling second.
  • Hint 2: Add timestamps for freshness trust.
  • Hint 3: Keep event payloads small and stable.
  • Hint 4: Add simulated latency tests.

5.7 Books That Will Help

Topic Book Chapter
Interface clarity “Clean Code” Meaningful naming and clarity
Practical design “The Pragmatic Programmer” Feedback loops
Reliable state handling “Code Complete” Defensive design

6. Testing Strategy

  • State transition tests.
  • Bridge event tests.
  • Failure/retry UX tests.

7. Common Pitfalls & Debugging

Pitfall Symptom Solution
Missing loading state Frozen-looking UI Add explicit loading transitions
Duplicate action calls Repeated backend writes Disable in-flight controls
Stale snapshots Old data after refresh Re-fetch authoritative payload

8. Extensions & Challenges

  • Add multi-tab view mode.
  • Add optimistic UI with rollback messaging.
  • Add accessibility keyboard shortcuts.

9. Real-World Connections

  • Team status widgets
  • Operational task summaries

10. Resources

  • OpenAI ChatGPT UI guide
  • OpenAI state-management docs

11. Self-Assessment Checklist

  • I can describe all widget states and transitions.
  • I can separate local state and server truth.
  • I can debug stale-render issues quickly.

12. Submission / Completion Criteria

Minimum Viable Completion

  • Deterministic widget with refresh and error recovery.

Full Completion

  • Includes persisted preferences and robust transition tests.