### Install Dependencies and Start Local Development Source: https://github.com/alpic-ai/skybridge/blob/main/docs/README.md Run these commands to install project dependencies and start a local development server for previewing the documentation. ```bash pnpm install pnpm dev ``` -------------------------------- ### Start Dev Server Source: https://github.com/alpic-ai/skybridge/blob/main/skills/chatgpt-app-builder/references/run-locally.md Installs dependencies and starts the development server in the background. Use 'deno task dev' for Deno projects. Hot reload is enabled for both server and widgets. ```bash {pm} install && {pm} run dev ``` -------------------------------- ### Start Production Server Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/build-for-production.mdx Once your app is built, start the production server to serve your compiled application. This command runs `skybridge start` and prepares your app for live use. ```bash npm start ``` ```bash pnpm start ``` ```bash yarn start ``` ```bash bun start ``` ```bash deno task start ``` -------------------------------- ### Create Skybridge Project with Overwrite and Immediate Start Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/cli.mdx Creates a new Skybridge project in the current directory (`.`), overwrites existing files without prompting, and automatically installs dependencies and starts the development server. ```bash npm create skybridge@latest . --overwrite --immediate ``` -------------------------------- ### Install Dependencies Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-auth0/README.md Install project dependencies using npm, pnpm, or bun. ```bash npm install # or pnpm install # or bun install ``` -------------------------------- ### Full MCP Server Example with Widgets Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/mcp-server.mdx A comprehensive example demonstrating the initialization of an `McpServer`, registration of widgets with input and output schemas, and type export for client-side inference. Ensure method chaining is used for type safety. ```typescript import { McpServer } from "skybridge/server"; import { z } from "zod"; const server = new McpServer( { name: "hotel-booking", version: "1.0.0" }, {} ) .registerWidget("search-hotels", { description: "Search for hotels", }, { inputSchema: { city: z.string().describe("City to search"), checkIn: z.string().describe("Check-in date"), checkOut: z.string().describe("Check-out date"), guests: z.number().optional().default(2), }, outputSchema: { hotels: z.array(z.object({ id: z.string(), name: z.string(), price: z.number(), rating: z.number(), })), }, }, async ({ city, checkIn, checkOut, guests }) => { const hotels = await searchHotels({ city, checkIn, checkOut, guests }); return { content: [{ type: "text", text: `Found ${hotels.length} hotels in ${city}` }], structuredContent: { hotels }, }; }) .registerWidget("hotel-details", { description: "Get hotel details", }, { inputSchema: { hotelId: z.string(), }, }, async ({ hotelId }) => { const hotel = await getHotel(hotelId); return { content: [{ type: "text", text: `Showing details for ${hotel.name}` }], structuredContent: hotel, }; }); export type AppType = typeof server; export default server; ``` -------------------------------- ### Start Local Server Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-auth0/README.md Start the local development server using npm, pnpm, or bun. This command launches the MCP server and the Skybridge DevTools UI. ```bash npm run dev # or pnpm dev # or bun dev ``` -------------------------------- ### Start Local Development Server Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-clerk/README.md Run the development server to start your MCP server and Skybridge DevTools. ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` -------------------------------- ### Install Dependencies with npm/yarn/pnpm/bun Source: https://github.com/alpic-ai/skybridge/blob/main/examples/ecom-carousel/README.md Installs project dependencies. Choose the command corresponding to your package manager. ```bash npm install ``` ```bash yarn install ``` ```bash pnpm install ``` ```bash bun install ``` -------------------------------- ### Combined Example: Todo List with State Management Source: https://github.com/alpic-ai/skybridge/blob/main/skills/chatgpt-app-builder/references/state-and-context.md This example demonstrates combining `useWidgetState` for persistent task data, `useState` for ephemeral UI focus, and `data-llm` for LLM context, illustrating how different state management approaches serve distinct purposes. ```tsx function TaskList() { // PERSIST: All tasks with completed status const [{ tasks }, setState] = useWidgetState({ tasks: [ { id: 1, title: "Buy groceries", completed: false }, { id: 2, title: "Call mom", completed: true }, ] }); // EPHEMERAL: Task user is viewing — reset on reopen const [viewing, setViewing] = useState(null); return ( // CONTEXT: What user is looking at — LLM answers "how should I handle this task?"
!t.completed).length} tasks remaining` }> {tasks.map(t => ( setViewing(t)} onToggle={() => setState((prev) => ({ ...prev, tasks: prev.tasks.map(task => task.id === t.id ? { ...task, completed: !task.completed } : task ) }))} /> ))}
); } ``` -------------------------------- ### Install Dependencies with Bun Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Installs project dependencies using Bun. Ensure Node.js 24+ is installed. ```bash bun install ``` -------------------------------- ### Start Local Development Server with Bun Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Starts the local development server using Bun. This command launches the MCP server and Skybridge DevTools UI. ```bash bun dev ``` -------------------------------- ### Fullscreen Media Player Example Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-display-mode.mdx An example of using the useDisplayMode hook to implement a media player that can toggle between inline and fullscreen modes. ```tsx import { useDisplayMode } from "skybridge/web"; function MediaPlayer() { const [displayMode, setDisplayMode] = useDisplayMode(); const isFullscreen = displayMode === "fullscreen"; return (
); } ``` -------------------------------- ### Install Dependencies with npm Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Installs project dependencies using npm. Ensure Node.js 24+ is installed. ```bash npm install ``` -------------------------------- ### Install Dependencies Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-clerk/README.md Install project dependencies using your preferred package manager. ```bash npm install # or yarn install # or pnpm install # or bun install ``` -------------------------------- ### One-Time Setup for generateHelpers Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/generate-helpers.mdx This code snippet demonstrates the one-time setup required in your web project to create typed hooks using `generateHelpers`. It imports the server type and then exports the typed `useCallTool` and `useToolInfo` hooks. ```ts // web/src/helpers.ts import type { AppType } from "../server"; // type-only import import { generateHelpers } from "skybridge/web"; export const { useCallTool, useToolInfo } = generateHelpers(); ``` -------------------------------- ### Install Dependencies with Yarn Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Installs project dependencies using Yarn. Ensure Node.js 24+ is installed. ```bash yarn install ``` -------------------------------- ### Start Local Development Server Source: https://github.com/alpic-ai/skybridge/blob/main/examples/ecom-carousel/README.md Starts the development server for both the MCP server and Skybridge DevTools. Use the command for your preferred package manager. ```bash npm run dev ``` ```bash yarn dev ``` ```bash pnpm dev ``` ```bash bun dev ``` -------------------------------- ### Install Manifest UI Component Source: https://github.com/alpic-ai/skybridge/blob/main/examples/manifest-ui/README.md Installs a specific Manifest UI component, such as 'post-card', into the '/web' directory using npx. This command is run from the '/web' folder. ```bash cd web npx shadcn@latest add @manifest/post-card ``` -------------------------------- ### Clone and Install Dependencies Source: https://github.com/alpic-ai/skybridge/blob/main/CONTRIBUTING.md Clone the Skybridge repository and install project dependencies using pnpm. ```bash git clone https://github.com/alpic-ai/skybridge.git cd skybridge pnpm install ``` -------------------------------- ### Start Skybridge Production Server Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/cli.mdx Starts the production server using the compiled output from `skybridge build`. It sets `NODE_ENV=production` and serves the MCP endpoint at `http://localhost:3000/mcp` along with pre-built widget assets. ```bash skybridge start ``` -------------------------------- ### Loading State Example Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-tool-info.mdx Illustrates how to display a loading indicator while the tool is executing, using the `isPending` flag. ```APIDOC ## Loading State Example This example shows how to conditionally render a loading state using the `isPending` flag from `useToolInfo`. ```tsx import { useToolInfo } from "skybridge/web"; function DataWidget() { const { input, isPending, isSuccess, output } = useToolInfo<{ input: { query: string }; output: { results: string[] }; }>(); return (

Search: {input.query}

{isPending && (

Searching...

)} {isSuccess && ( )}
); } ``` ``` -------------------------------- ### useToolInfo Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference.mdx Get initial tool input, output and metadata. ```APIDOC ## useToolInfo ### Description Get initial tool input, output and metadata. ### Method N/A (Hook) ### Parameters N/A ### Request Example N/A ### Response N/A ``` -------------------------------- ### Start Local Development Server with pnpm Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Starts the local development server using pnpm. This command launches the MCP server and Skybridge DevTools UI. ```bash pnpm dev ``` -------------------------------- ### Install Skybridge Dependencies Source: https://github.com/alpic-ai/skybridge/blob/main/CLAUDE.md Run this command to set up the project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Start the Skybridge development server Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/create-new-app.mdx Run this command from your project's root directory to start the development server. It includes an MCP server, a React frontend with HMR, and hot-reloading for server code. ```bash npm run dev ``` ```bash pnpm dev ``` ```bash yarn dev ``` ```bash bun dev ``` ```bash deno task dev ``` -------------------------------- ### Start Local Development Server with Yarn Source: https://github.com/alpic-ai/skybridge/blob/main/examples/generative-ui/README.md Starts the local development server using Yarn. This command launches the MCP server and Skybridge DevTools UI. ```bash yarn dev ``` -------------------------------- ### Start Skybridge Development Server Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/cli.mdx Starts the development server with hot module reloading and DevTools. The server runs on `http://localhost:3000/`, exposes the MCP server at `http://localhost:3000/mcp`, and enables file watching with automatic restarts. ```bash skybridge dev ``` -------------------------------- ### Configure Stripe Environment Variables Source: https://github.com/alpic-ai/skybridge/blob/main/examples/ecom-carousel/README.md Copies the example environment file and prompts to add your Stripe test secret key. ```bash cp .env.example .env ``` -------------------------------- ### Logging Requests Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/mcp-server.mdx This example shows how to use `mcpMiddleware` to log details of incoming requests, such as the HTTP method and parameters. ```APIDOC ## Logging Requests ### Description Use `mcpMiddleware` to intercept and log request details. ### Method `server.mcpMiddleware("request", (request, extra, next) => { ... });` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript server.mcpMiddleware("request", (request, extra, next) => { console.log(`[MCP] ${request.method}`, request.params); return next(); }); ``` ### Response None directly from middleware, but `next()` is called to continue processing. ``` -------------------------------- ### Set up Web Project with Vite Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/add-to-existing-app/server.mdx Initialize a web project, add necessary dependencies, and configure Vite for skybridge. ```bash mkdir web && cd web pnpm init pnpm add react react-dom skybridge pnpm add -D vite typescript @types/react @types/react-dom ``` ```typescript import { defineConfig } from "vite"; import { skybridge } from "skybridge/web"; export default defineConfig({ plugins: [skybridge()], }); ``` -------------------------------- ### Reading Theme Context Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-mcp-app-context.mdx This example shows how to use `useMcpAppContext` to get the current theme and apply it to the component's styling. It conditionally sets background and text colors based on the theme. ```tsx import { useMcpAppContext } from "skybridge/web"; function ThemedWidget() { const theme = useMcpAppContext("theme"); return (

Current theme: {theme}

); } ``` -------------------------------- ### MCP Server with Method Chaining Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/generate-helpers.mdx An example of an MCP server definition using method chaining, which is a prerequisite for `generateHelpers` to perform type inference. This setup allows `registerWidget` and `registerTool` calls to be chained. ```ts // ✅ Works — chain registerWidget/registerTool calls const server = new McpServer({ name: "my-app", version: "1.0" }, {}) .registerWidget("search-voyage", {}, { inputSchema: { destination: z.string() } }, async ({ destination }) => { return { content: [{ type: "text", text: `Found trips to ${destination}` }] }; }); export type AppType = typeof server; ``` -------------------------------- ### Adapt Widget Theme with useLayout Source: https://github.com/alpic-ai/skybridge/blob/main/docs/guides/host-environment-context.mdx Use the `useLayout` hook to get the host's theme and apply corresponding styles. This example shows direct style manipulation for background and text colors. ```tsx import { useLayout } from "skybridge/web"; function ThemedWidget() { const { theme } = useLayout(); const isDark = theme === "dark"; return (

Hello

); } ``` -------------------------------- ### Build Application for Production Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/build-for-production.mdx Run the build command from your project root to compile widgets and server code for production. This prepares your application for deployment. ```bash npm run build ``` ```bash pnpm build ``` ```bash yarn build ``` ```bash bun build ``` ```bash deno task build ``` -------------------------------- ### Configure and run the MCP server Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-stytch/README.md Set up environment variables for Stytch integration and run the MCP server using pnpm. This starts the MCP server, OAuth pages, and Skybridge DevTools. ```env STYTCH_PROJECT_ID=project-test-... STYTCH_DOMAIN=https://.stytch.com VITE_STYTCH_PUBLIC_TOKEN=public-token-test-... SERVER_URL=http://localhost:3000 ``` ```bash pnpm install pnpm dev ``` -------------------------------- ### Interactive Tutorial with Step-by-Step Follow-ups Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-send-follow-up-message.mdx Build an interactive tutorial where each step prompts the AI for the next piece of information or guidance. The `sendFollowUpMessage` function is used to advance the tutorial by asking specific questions. ```tsx import { useSendFollowUpMessage } from "skybridge/web"; import { useState } from "react"; const tutorialSteps = [ { content: "Welcome to the tutorial!", followUp: "What will I learn in step 1?", }, { content: "Step 1: Getting started", followUp: "How do I proceed to step 2?", }, { content: "Step 2: Advanced features", followUp: "Can you summarize what I learned?", }, ]; function Tutorial() { const sendFollowUpMessage = useSendFollowUpMessage(); const [step, setStep] = useState(0); const currentStep = tutorialSteps[step]; const isLastStep = step === tutorialSteps.length - 1; const handleNext = async () => { await sendFollowUpMessage(currentStep.followUp); if (!isLastStep) { setStep((s) => s + 1); } }; return (

{currentStep.content}

Step {step + 1} of {tutorialSteps.length}
); } ``` -------------------------------- ### Shopping Cart Example Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-widget-state.mdx Demonstrates using `useWidgetState` to manage a shopping cart's state, including adding, removing items, and calculating the total. ```APIDOC ## Shopping Cart ```tsx import { useWidgetState } from "skybridge/web"; type CartItem = { id: string; name: string; price: number; quantity: number; }; type CartState = { items: CartItem[]; }; function ShoppingCart() { const [cart, setCart] = useWidgetState({ items: [] }); const addItem = (item: Omit) => { setCart((prev) => { const existing = prev.items.find((i) => i.id === item.id); if (existing) { return { items: prev.items.map((i) => i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i ), }; } return { items: [...prev.items, { ...item, quantity: 1 }] }; }); }; const removeItem = (id: string) => { setCart((prev) => ({ items: prev.items.filter((i) => i.id !== id), })); }; const total = cart.items.reduce( (sum, item) => sum + item.price * item.quantity, 0 ); return (

Shopping Cart

{cart.items.length === 0 ? (

Your cart is empty

) : ( <>
    {cart.items.map((item) => (
  • {item.name} x{item.quantity} - ${item.price * item.quantity}
  • ))}

Total: ${total}

)}
); } ``` ``` -------------------------------- ### Image Upload and Preview Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-files.mdx Uploads an image file and then uses `getDownloadUrl` to generate a preview URL. This example requires importing both `upload` and `getDownloadUrl` from `useFiles`. Error handling for the upload process is included. ```tsx import { useFiles } from "skybridge/web"; import { useState } from "react"; function ImageUploader() { const { upload, getDownloadUrl } = useFiles(); const [previewUrl, setPreviewUrl] = useState(null); const [isUploading, setIsUploading] = useState(false); const handleUpload = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; setIsUploading(true); try { const { fileId } = await upload(file); const { downloadUrl } = await getDownloadUrl({ fileId }); setPreviewUrl(downloadUrl); } catch (error) { console.error("Upload failed:", error); } finally { setIsUploading(false); } }; return (
{isUploading &&

Uploading...

} {previewUrl && Preview}
); } ``` -------------------------------- ### Initialize McpServer Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/mcp-server.mdx Instantiate McpServer with server information and options. ```typescript const server = new McpServer( serverInfo: { name: string; version: string }, options: McpServerOptions ); ``` -------------------------------- ### McpServer Constructor Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/mcp-server.mdx Initializes a new McpServer instance. Requires server information and optional configuration options. ```APIDOC ## Constructor ```typescript const server = new McpServer( serverInfo: { name: string; version: string }, options: McpServerOptions ); ``` ### Parameters | Parameter | Type | Description | |-----------|------|-------------| | `serverInfo.name` | `string` | Name of your MCP server | | `serverInfo.version` | `string` | Version of your server | | `options` | `McpServerOptions` | Configuration options | ### Options ```typescript type McpServerOptions = { // Additional options as needed }; ``` ``` -------------------------------- ### Install Skybridge Skill with deno Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/migrate.mdx Use deno to install the Skybridge skill. This command adds the skill to your project, enabling migration capabilities. ```bash deno run -A npm:skills add alpic-ai/skybridge -s skybridge ``` -------------------------------- ### Initialize Stytch Client and Configure Login Source: https://github.com/alpic-ai/skybridge/blob/main/examples/auth-stytch/assets/login.html Initializes the Stytch UI client with a public token and configures OTP and OAuth login options. This setup is necessary before mounting the login component. ```javascript import { StytchUIClient, Products, OTPMethods, OAuthProviders } from 'https://esm.sh/@stytch/vanilla-js'; const stytch = new StytchUIClient('%VITE_STYTCH_PUBLIC_TOKEN%'); const config = { products: [Products.otp, Products.oauth], otpOptions: { expirationMinutes: 10, methods: [OTPMethods.Email], }, oauthOptions: { providers: [{ type: OAuthProviders.Google }], loginRedirectURL: window.location.origin + '/assets/authenticate.html', signupRedirectURL: window.location.origin + '/assets/authenticate.html', }, }; const callbacks = { onEvent: (evt) => { if (evt.type !== 'AUTHENTICATE_FLOW_COMPLETE') return; const returnTo = sessionStorage.getItem('returnTo'); if (returnTo) { sessionStorage.removeItem('returnTo'); window.location.href = returnTo; } else { window.location.href = '/'; } }, }; // When @stytch/vanilla-js is loaded via CDN (esm.sh), the custom element // is registered in a separate module graph and does not automatically receive the client // instance. mountLogin registers and inserts the element, but we must call render() // manually to pass the client. This extra step is not needed when using the npm package. stytch.mountLogin({ elementId: '#login', config, callbacks }); await customElements.whenDefined('stytch-ui'); const el = document.querySelector('#login stytch-ui'); if (el?.render) { el.render({ client: stytch, config, callbacks }); } ``` -------------------------------- ### Install Skybridge Skill with bun Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/migrate.mdx Use bun to install the Skybridge skill. This command adds the skill to your project, enabling migration capabilities. ```bash bunx skills add alpic-ai/skybridge -s skybridge ``` -------------------------------- ### Todo List with Actions using createStore Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/create-store.mdx Demonstrates how to create a state store with actions for managing a todo list. This includes adding, toggling, removing, and clearing completed todos. Use this pattern for complex state logic and when actions are integral to state updates. ```tsx import { createStore } from "skybridge/web"; import type { StateCreator } from "zustand"; type Todo = { id: string; text: string; completed: boolean; }; type TodoState = { todos: Todo[]; addTodo: (text: string) => void; toggleTodo: (id: string) => void; removeTodo: (id: string) => void; clearCompleted: () => void; }; const useTodoStore = createStore((set) => ({ todos: [], addTodo: (text) => set((state) => ({ todos: [ ...state.todos, { id: crypto.randomUUID(), text, completed: false }, ], })), toggleTodo: (id) => set((state) => ({ todos: state.todos.map((todo) => todo.id === id ? { ...todo, completed: !todo.completed } : todo ), })), removeTodo: (id) => set((state) => ({ todos: state.todos.filter((todo) => todo.id !== id), })), clearCompleted: () => set((state) => ({ todos: state.todos.filter((todo) => !todo.completed), })), })); function TodoWidget() { const todos = useTodoStore((state) => state.todos); const addTodo = useTodoStore((state) => state.addTodo); const toggleTodo = useTodoStore((state) => state.toggleTodo); const removeTodo = useTodoStore((state) => state.removeTodo); const clearCompleted = useTodoStore((state) => state.clearCompleted); const [input, setInput] = useState(""); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (input.trim()) { addTodo(input.trim()); setInput(""); } }; return (

Todo List

setInput(e.target.value)} placeholder="Add a todo..." />
    {todos.map((todo) => (
  • toggleTodo(todo.id)} /> {todo.text}
  • ))}
); } ``` -------------------------------- ### Install Skybridge Skill with yarn Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/migrate.mdx Use yarn to install the Skybridge skill. This command adds the skill to your project, enabling migration capabilities. ```bash yarn dlx skills add alpic-ai/skybridge -s skybridge ``` -------------------------------- ### Install Skybridge Skill with pnpm Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/migrate.mdx Use pnpm to install the Skybridge skill. This command adds the skill to your project, enabling migration capabilities. ```bash pnpm dlx skills add alpic-ai/skybridge -s skybridge ``` -------------------------------- ### Start Local Server Source: https://github.com/alpic-ai/skybridge/blob/main/docs/quickstart/test-your-app.mdx Run your development server without the tunnel flag for testing with local MCP clients like VSCode or Goose. Your server will be available at http://localhost:3000/mcp. ```bash npm run dev ``` -------------------------------- ### Setting URL with Form Input Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-set-open-in-app-url.mdx This example shows how to integrate `useSetOpenInAppUrl` with a form, allowing users to input a URL dynamically. It includes state management for the URL, error messages, and success feedback. ```tsx import { useSetOpenInAppUrl } from "skybridge/web"; import { useState } from "react"; function UrlSetter() { const setOpenInAppUrl = useSetOpenInAppUrl(); const [url, setUrl] = useState(""); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); setSuccess(false); try { await setOpenInAppUrl(url); setSuccess(true); } catch (err) { setError(err instanceof Error ? err.message : "Failed to set URL"); } }; return (
setUrl(e.target.value)} placeholder="Enter URL" /> {success &&

✓ URL successfully set!

} {error &&

× {error}

}
); } ``` -------------------------------- ### Install Skybridge Skill Source: https://github.com/alpic-ai/skybridge/blob/main/docs/devtools/skills.mdx Add the Skybridge skill to your AI coding assistant using your preferred package manager. This command installs the skill and makes it available for use. ```bash npx skills add alpic-ai/skybridge -s skybridge ``` ```bash pnpm dlx skills add alpic-ai/skybridge -s skybridge ``` ```bash yarn dlx skills add alpic-ai/skybridge -s skybridge ``` ```bash bunx skills add alpic-ai/skybridge -s skybridge ``` ```bash deno run -A npm:skills add alpic-ai/skybridge -s skybridge ``` -------------------------------- ### Build and Start Skybridge Production Server Source: https://context7.com/alpic-ai/skybridge/llms.txt Use `skybridge build` to compile React widgets and transpile the TypeScript server for production. `skybridge start` then runs the compiled server with `NODE_ENV=production`. ```bash skybridge build ``` ```bash skybridge start ``` -------------------------------- ### useToolInfo Example: Loading State Handling Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-tool-info.mdx Shows how to use the 'isPending' flag from useToolInfo to display a loading indicator while a tool is executing. It also conditionally renders results when 'isSuccess' is true. ```tsx import { useToolInfo } from "skybridge/web"; function DataWidget() { const { input, isPending, isSuccess, output } = useToolInfo<{ input: { query: string }; output: { results: string[] }; }>(); return (

Search: {input.query}

{isPending && (

Searching...

)} {isSuccess && (
    {output.results.map((result, i) => (
  • {result}
  • ))}
)}
); } ``` -------------------------------- ### Initial Project Deployment to Alpic Source: https://github.com/alpic-ai/skybridge/blob/main/skills/chatgpt-app-builder/references/deploy.md Use this command for the first deployment of a project. It requires specifying a project name and the path to your project directory. Ensure the `.alpic/` folder does not exist in your project directory. ```bash npx alpic@latest deploy --yes --project-name {project-name} {path-to-project} ``` -------------------------------- ### Initiate Guided Actions with useSendFollowUpMessage Source: https://github.com/alpic-ai/skybridge/blob/main/docs/guides/communicating-with-model.mdx Trigger guided actions by sending specific prompts to the LLM using `useSendFollowUpMessage`. This allows for complex requests like adding items to an order and confirming the total. ```tsx ``` -------------------------------- ### Create and Configure MCP Server Source: https://context7.com/alpic-ai/skybridge/llms.txt Instantiate and configure the McpServer, registering protocol and HTTP middleware, and defining tools like 'search-hotels' and 'hotel-details'. Method chaining is crucial for type inference. Export AppType for helper generation. ```typescript import { McpServer } from "skybridge/server"; import { z } from "zod"; const server = new McpServer({ name: "hotel-booking", version: "1.0.0" }, {}) // Register MCP protocol-level middleware (onion model) .mcpMiddleware("tools/call", async (request, extra, next) => { const token = extra.requestInfo?.headers?.["authorization"]; if (!token) throw new Error("Unauthorized"); console.log(`Tool called: ${request.params.name}`); return next(); }) // Register Express HTTP middleware .use(cors()) // Register a widget tool .registerWidget( "search-hotels", { description: "Search for available hotels" }, { inputSchema: { city: z.string().describe("City to search"), checkIn: z.string().describe("Check-in date (YYYY-MM-DD)"), checkOut: z.string().describe("Check-out date (YYYY-MM-DD)"), guests: z.number().optional().default(2), }, outputSchema: { hotels: z.array(z.object({ id: z.string(), name: z.string(), price: z.number(), rating: z.number(), })), }, }, async ({ city, checkIn, checkOut, guests }) => { const hotels = await searchHotels({ city, checkIn, checkOut, guests }); return { content: [{ type: "text", text: `Found ${hotels.length} hotels in ${city}` }], structuredContent: { hotels }, }; }, ) .registerWidget( "hotel-details", { description: "Get full details for a specific hotel" }, { inputSchema: { hotelId: z.string() } }, async ({ hotelId }, extra) => { const email = extra.authInfo?.extra?.email as string | undefined; const hotel = await getHotel(hotelId); if (!hotel) { return { content: [{ type: "text", text: `Hotel ${hotelId} not found` }], structuredContent: { error: "not_found" }, }; } return { content: [{ type: "text", text: `Showing details for ${hotel.name}` }], structuredContent: { ...hotel, viewedBy: email }, }; }, ); // Export type for end-to-end inference in web widgets export type AppType = typeof server; export default server; ``` -------------------------------- ### McpServer Configuration Source: https://context7.com/alpic-ai/skybridge/llms.txt Demonstrates how to create and configure an MCP server using method chaining for type inference. Includes registering MCP middleware, Express middleware, and custom widgets. ```APIDOC ## McpServer — Create and configure the MCP server The main server class. Extend the MCP SDK with Skybridge capabilities. Must use **method chaining** for end-to-end type inference to work. Export `typeof server` as `AppType` for use with `generateHelpers`. ```typescript import { McpServer } from "skybridge/server"; import { z } from "zod"; const server = new McpServer({ name: "hotel-booking", version: "1.0.0" }, {}) // Register MCP protocol-level middleware (onion model) .mcpMiddleware("tools/call", async (request, extra, next) => { const token = extra.requestInfo?.headers?.["authorization"]; if (!token) throw new Error("Unauthorized"); console.log(`Tool called: ${request.params.name}`); return next(); }) // Register Express HTTP middleware .use(cors()) // Register a widget tool .registerWidget( "search-hotels", { description: "Search for available hotels" }, { inputSchema: { city: z.string().describe("City to search"), checkIn: z.string().describe("Check-in date (YYYY-MM-DD)"), checkOut: z.string().describe("Check-out date (YYYY-MM-DD)"), guests: z.number().optional().default(2), }, outputSchema: { hotels: z.array(z.object({ id: z.string(), name: z.string(), price: z.number(), rating: z.number(), })), }, }, async ({ city, checkIn, checkOut, guests }) => { const hotels = await searchHotels({ city, checkIn, checkOut, guests }); return { content: [{ type: "text", text: `Found ${hotels.length} hotels in ${city}` }], structuredContent: { hotels }, }; }, ) .registerWidget( "hotel-details", { description: "Get full details for a specific hotel" }, { inputSchema: { hotelId: z.string() } }, async ({ hotelId }, extra) => { const email = extra.authInfo?.extra?.email as string | undefined; const hotel = await getHotel(hotelId); if (!hotel) { return { content: [{ type: "text", text: `Hotel ${hotelId} not found` }], structuredContent: { error: "not_found" }, }; } return { content: [{ type: "text", text: `Showing details for ${hotel.name}` }], structuredContent: { ...hotel, viewedBy: email }, }; }, ); // Export type for end-to-end inference in web widgets export type AppType = typeof server; export default server; ``` ``` -------------------------------- ### Example SPEC.md for Pizza Ordering App Source: https://github.com/alpic-ai/skybridge/blob/main/skills/chatgpt-app-builder/references/discover.md This markdown example demonstrates the structure and content expected in a SPEC.md file after completing the discovery workflow. It includes sections for Value Proposition, Why LLM?, UI Overview, and Product Context. ```markdown # Pizza Ordering App ## Value Proposition Order pizza through conversation. Target: PizzaCo customers wanting quick orders. Pain: navigating menus is slower than describing what you want. **Core actions**: Browse menu, customize order, track delivery. ## Why LLM? **Conversational win**: "My usual but with mushrooms" = one sentence vs. multiple screens. **LLM adds**: Intent from natural descriptions, handles modifications. **What LLM lacks**: Real menu and pricing data, order placement. ## UI Overview **First view**: Popular pizzas with quick "reorder last" option. **Browsing**: Menu with categories, filters, and customization options. **Checkout**: Order summary, confirm, and place order. **Tracking**: Live delivery status with ETA and map. ## Product Context - **Existing products**: Mobile app, website - **API**: REST at api.pizzaco.com (OAuth2, 100 req/min) - **Auth**: PizzaCo account (OAuth2) - **Constraints**: Payment via existing account only ``` -------------------------------- ### Example Usage of useCallTool in a Widget Source: https://context7.com/alpic-ai/skybridge/llms.txt This example demonstrates how to use the useCallTool hook within a React component to search for hotels. It showcases autocompletion for the tool name and type inference for input and output, along with handling success and error states. ```tsx import { useCallTool, useToolInfo } from "../helpers"; export function HotelSearchWidget() { // Tool name "search-hotels" is autocompleted; input/output shapes are inferred const { callTool, isPending, isSuccess, data } = useCallTool("search-hotels"); const handleSearch = () => { callTool( { city: "Paris", checkIn: "2025-09-01", checkOut: "2025-09-07", guests: 2 }, { onSuccess: (response) => console.log("Hotels:", response.structuredContent.hotels), onError: (err) => console.error("Search failed:", err), } ); }; return (
{isSuccess && (
    {data.structuredContent.hotels.map((hotel) => (
  • {hotel.name} — ${hotel.price}/night ⭐{hotel.rating}
  • ))}
)}
); } ``` -------------------------------- ### Settings Modal Example Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/use-request-modal.mdx Demonstrates using `useRequestModal` to open a settings form. The widget's state is managed locally and displayed when `isOpen` is true. ```tsx import { useRequestModal } from "skybridge/web"; import { useState } from "react"; function SettingsWidget() { const { open, isOpen } = useRequestModal(); const [settings, setSettings] = useState({ notifications: true, darkMode: false, language: "en", }); if (isOpen) { return (
); } return (
Settings
); } ``` -------------------------------- ### ToolOutput Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/infer-utility-types.mdx Get the output type for a specific tool. ```APIDOC ## ToolOutput Get the output type for a specific tool: ```typescript import type { ToolOutput } from "skybridge/server"; import type { AppType } from "../../server/src/index"; type SearchOutput = ToolOutput; // { hotels: Array<{ id: string; name: string; price: number }> } ``` ``` -------------------------------- ### ToolInput Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/infer-utility-types.mdx Get the input type for a specific tool. ```APIDOC ## ToolInput Get the input type for a specific tool: ```typescript import type { ToolInput } from "skybridge/server"; import type { AppType } from "../../server/src/index"; type SearchInput = ToolInput; // { city: string; checkIn: string; checkOut: string; guests?: number } ``` ``` -------------------------------- ### Subsequent Project Deployments to Alpic Source: https://github.com/alpic-ai/skybridge/blob/main/skills/chatgpt-app-builder/references/deploy.md Execute this command for deployments after the initial setup. It assumes the `.alpic/` folder exists in your project directory and only requires the project path. ```bash npx alpic@latest deploy --yes {path-to-project} ``` -------------------------------- ### Run Skybridge Package Manager Scripts Source: https://github.com/alpic-ai/skybridge/blob/main/docs/api-reference/cli.mdx Demonstrates how to execute the `dev`, `build`, and `start` scripts for a Skybridge project using various package managers like npm, pnpm, yarn, bun, and deno. ```bash npm run dev npm run build npm start ``` ```bash pnpm dev pnpm build pnpm start ``` ```bash yarn dev yarn build yarn start ``` ```bash bun dev bun build bun start ``` ```bash deno task dev denotask build denotask start ```