Skip to content

Multi-Step Wizard

Use ggui’s stack model to build multi-step wizards. Each step is a separate card pushed onto the session stack. The pop() method enables “Back” navigation.

import { GguiClient, GguiSessionNotFoundError } from "@ggui-ai/mcp-client";
import type { ActionEnvelope } from "@ggui-ai/mcp-client";
const ggui = new GguiClient({
apiKey: process.env.GGUI_API_KEY!,
appId: process.env.GGUI_APP_ID!,
});
async function onboardingWizard() {
// Step 1: Personal info
const { sessionId, url } = await ggui.push({
story: {
intent: "Onboarding wizard — step 1 personal info",
prompt: `Show step 1 of 3: Personal Information form.
Fields: full name, email, phone number.
Include a "Next" button.`,
context: { step: 1, totalSteps: 3 },
},
});
console.log(`Start the onboarding: ${url}`);
const step1Data = await waitForSubmit(sessionId);
// Step 2: Company info (pushed onto same session)
await ggui.push({
session: { id: sessionId },
story: {
intent: "Onboarding wizard — step 2 company info",
prompt: `Show step 2 of 3: Company Information form.
Fields: company name, role, team size.
Include "Back" and "Next" buttons.`,
context: { step: 2, totalSteps: 3, previousData: step1Data },
},
});
const step2Events = await waitForSubmit(sessionId);
// Handle "Back" button
if (step2Events?.action === "back") {
await ggui.pop(sessionId); // Remove step 2, showing step 1 again
}
// Step 3: Confirmation
await ggui.push({
session: { id: sessionId },
story: {
intent: "Onboarding wizard — step 3 review + confirm",
prompt: `Show step 3 of 3: Review and Confirm.
Display all collected data and ask for confirmation.
Include "Back" and "Confirm" buttons.`,
context: {
step: 3,
totalSteps: 3,
personalInfo: step1Data,
companyInfo: step2Events,
},
},
});
const confirmation = await waitForSubmit(sessionId);
await ggui.close(sessionId);
return {
personal: step1Data,
company: step2Events,
confirmed: confirmation?.confirmed === true,
};
}
async function waitForSubmit(sessionId: string): Promise<Record<string, unknown> | null> {
const events = await ggui.waitForCompletion(sessionId, {
pollInterval: 1000,
maxWait: 600_000,
});
const submit = events.find((e) => e.type === "data:submit");
return (submit?.payload as Record<string, unknown>) ?? null;
}
After Step 1: [PersonalInfo]
After Step 2: [PersonalInfo, CompanyInfo] ← user sees CompanyInfo
After Pop: [PersonalInfo] ← user sees PersonalInfo again
After Step 3: [PersonalInfo, CompanyInfo, Confirmation]
const state = await ggui.getSession(sessionId);
console.log(`Stack depth: ${state.stack.length}`);
console.log(`Current index: ${state.currentStackIndex}`);