Start Studio (start.gecx.chat)

start-studio is the zero-install onboarding wizard for the SDK. Open it, click through four screens, and download a runnable Next.js project with a mock transport pre-seeded. Goal: install-to-first-conversation in under three minutes, versus ~25 minutes via the manual quickstart.

Use this when you want to give a developer a working chat in the time it takes to read this paragraph — no git clone, no copy-paste, no env vars.

Run it locally

From the repo root:

pnpm install --frozen-lockfile
pnpm dev:studio          # starts on http://localhost:3003

The wizard runs entirely in the browser. No credentials, no env vars, no backend setup. The right-hand pane renders a live <ChatSession> driven by mock transport, so the developer feels the chat work before clicking download.

What the wizard collects

Four steps, each backed by a typed catalog under apps/start-studio/src/lib/.

StepChoicesCatalog
1. TemplateSupport Concierge · Commerce Conciergetemplate-catalog.ts
2. Tools8 starter client tools, default-checked per templatetool-catalog.ts
3. HandoffNone · Mock · Salesforce · Zendesk · ServiceNow · Genesys · Five9 · Google CCAIhandoff-catalog.ts
4. AnalyticsNone · Console · GA4 · Segment · HTTP sinkanalytics-catalog.ts

Sensible defaults are pre-selected at every step so the fast path is "click Continue four times." Step 1 also collects an app name and a brand name for the generated repo.

What's in the downloaded zip

A complete Next.js App Router project. Unzip and run:

unzip my-chat.zip && cd my-chat
pnpm install      # installs the SDK from the bundled tarball — works offline
pnpm dev          # opens http://localhost:3000

The first chat reply streams within seconds, driven by a scripted mock scenario (order-status for Support, commerce-recommendation for Commerce).

The generated repo layout:

my-chat/
├── package.json                          # deps: gecx-chat (and gecx-chat-ccaas if handoff != none)
├── gecx-chat-0.1.0-prototype.tgz         # bundled SDK, installs offline
├── gecx-chat-ccaas-0.1.0-prototype.tgz   # bundled only when handoff != none
├── app/
│   ├── layout.tsx                        # GA4 gtag script injected when analytics=ga4
│   ├── page.tsx                          # the chat surface
│   └── api/handoff/route.ts              # only present when handoff != none
├── src/lib/
│   ├── tools/                            # one file per selected tool, plus an index barrel
│   └── analytics.ts                      # only present when analytics != none
├── test/gecx-chat-smoke.test.ts          # runs the chosen mock scenario
├── verify.sh                             # typecheck + test in one command
├── AGENTS.md / CLAUDE.md                 # agent-pack files inlined for Codex + Claude Code
└── .claude/skills/headless-chat-vibe-coding/   # for AI coding agents

Every generated file is deterministic given the wizard state — pure functions in apps/start-studio/src/lib/scaffold/.

Architecture

The studio has two server-side touchpoints; everything else runs in the user's browser:

Browser
├─ Wizard UI                      (Next.js App Router, ~116 kB First Load JS)
├─ Live preview                   (real <ChatSession> + createMockTransport)
└─ Web Worker
   ├─ composeFiles(state)         (pure scaffold pipeline)
   ├─ fflate zip                  (~8 kB compressed)
   └─ fetch /sdk/*.tgz            (bundled SDK tarballs)
                                  ↓
Cloud Run
├─ /studio                        (page render, static)
├─ /api/health                    (Cloud Run startup + liveness probe)
└─ /api/studio-telemetry          (collects ProductAnalyticsEvent → Cloud Logging)

The scaffold pipeline is isomorphic — same code runs in the browser worker and in Vitest tests. The agent-pack content (AGENTS.md, CLAUDE.md, headless-chat-vibe-coding skill) is inlined as TypeScript strings in scaffold/agentPack.ts rather than imported from gecx-chat/cli, because the CLI module pulls in node:fs/promises and can't run in a worker.

Self-instrumentation

The studio dogfoods the SDK's own ProductAnalytics surface. Events emitted:

EventPayloadWhen
wizard_startedFirst page load
wizard_step_completed{ step, next, dwellMs }Navigating between steps
wizard_template_selected{ template }Step 1
wizard_tool_toggled{ tool, checked }Step 2
wizard_tools_committed{ count, ids }Step 2 → 3
wizard_handoff_selected{ handoff }Step 3
wizard_analytics_selected{ sink }Step 4
wizard_preview_first_message{ scenarioId }First reply in live preview
wizard_download_clicked{ totalMs, template, toolCount, handoff, analytics }Download button

totalMs on wizard_download_clicked is the time-to-first-conversation KPI. Events POST to /api/studio-telemetry, which logs to stdout — Cloud Run forwards stdout to Cloud Logging automatically.

Verification

The scaffold pipeline is covered by three suites under apps/start-studio/tests/:

  • scaffold.test.ts (12 tests) — file-presence and content-shape assertions across an exhaustive (template × handoff × analytics) matrix.
  • dockerfile.test.ts (7 tests) — static assertions on the container contract (multi-stage, non-root, port 8080, healthcheck on /api/health).
  • quickstart-still-compiles.test.ts (1 test) — guards templates/CLAUDE.md's PRD §3 quickstart snippet shape so the studio's chat-page emission stays compatible.
  • generated-repo-compiles.test.ts (3 tests, gated by STUDIO_FULL_TESTS=1) — the highest-value test: composes files for a representative matrix, writes them to a tmpdir, runs pnpm install against the bundled tarballs, runs pnpm typecheck against the resulting project, and asserts exit 0. Catches snippet drift, wrong import paths, and missing devDependencies that the snapshot tests can't see.
  • wizard.spec.ts (2 Playwright tests) — full landing → 4 steps → download click-through, plus a live-preview streaming check.

Run the fast suites:

pnpm --filter start-studio test     # snapshot + dockerfile + quickstart, ~1s
pnpm --filter start-studio e2e      # Playwright wizard, ~5s

Run the slow suite (real pnpm install per matrix row):

pnpm --filter start-studio pack-sdk
STUDIO_FULL_TESTS=1 pnpm --filter start-studio test    # ~14s

CI runs all three on every PR (STUDIO_FULL_TESTS=1 is set on the Node 22 matrix job).

Deploy to Cloud Run

The studio ships as a Cloud Run service mirroring apps/proxy-reference's container pattern. See apps/start-studio/README.md for the full runbook. Short version:

# One-time
gcloud artifacts repositories create gecx-images \
  --repository-format=docker --location=us-central1

gcloud iam service-accounts create start-studio \
  --display-name="start.gecx.chat service account"

# Every deploy
gcloud builds submit \
  --config=apps/start-studio/cloudbuild.yaml \
  --substitutions=_REGION=us-central1,_REPOSITORY=gecx-images

Cloud Run scales to zero when idle, so the bill is roughly nothing until the site sees traffic. Custom domain via gcloud beta run domain-mappings create --service=start-studio --domain=start.gecx.chat.

Comparison to the manual quickstart

PathTime to first conversationWhere the dev customizes
Quickstart~5 min (no UI), ~25 min (full app)Hand-edits TS files, copies recipes
React Quickstart~10 minHand-edits TS + JSX
create-gecx-chat CLI~5 minInteractive prompts in the terminal
start-studio<3 minWizard UI with live preview

The studio is additive — the existing paths keep working. Use it when you want a developer to feel the chat work before committing to learning the SDK surface; use the others when you already know what you want to build.

Source: docs/demos/start-studio.md