Vibe Coding a Chat Surface
Describe the chat surface you want and let Claude Code build it on the agent client SDK.
Getting Started shows how to hand-write a chat surface on @limio/sdk/ai. This guide takes the faster path: describe the surface you want and let Claude Code generate it as a Limio custom component, grounded in the SDK docs so it builds on the real primitives.
A chat surface is a custom component like any other, so the workflow is the one from Guide: Vibe Code Custom Components with Claude Code: prompt, push, preview in Storybook, deploy in Page Builder. What differs is the grounding and the prompt, which is what this page covers.
The agent client SDK (@limio/sdk/ai) is available from Release 117 onwards. You also need a published agent to test against; see Configuring an Agent.
Prerequisites
Claude Code (or Cursor or a similar AI coding tool)
Access to your organisation's component repo (getting started with the components repository)
CI/CD pipeline connected, if you use GitHub or GitLab (Connecting External CI)
The Limio Skills plugin installed (Skills), so Claude knows the repo conventions: component structure,
package.jsondependencies, Page Builder props, Storybook
Ground Claude in the agent SDK
The Limio Skills plugin covers components in general; the agent knowledge comes from the SDK docs. Start the conversation by pointing Claude at them:
Read these two pages before writing any code:
- https://docs.limio.com/agents/limio-agents/getting-started
- https://docs.limio.com/agents/limio-agents/sdk-reference
Build only on the documented @limio/sdk/ai exports. Do not call the
Chat API directly and do not invent SDK methods.The exports Claude should reach for:
useChat
The conversation state machine: session bootstrap, lazy conversation creation, optimistic sends, the pending reply bubble, error rollback.
MessageContent
Renders a message's content blocks: markdown replies formatted, visitor text literal, component blocks via a registry.
contentToText
Flattens a message to a plain string, for rendering the visitor's own bubbles.
createMessageComponentRegistry
Optional. Renders interactive blocks the agent surfaces inline, such as a file upload.
themeRootProps
Optional. Applies the agent's admin-configured theme to a surface built on Limio design tokens.
Write your prompt
Be specific about behaviour, states, and styling, the same as for any vibe-coded component. A worked example, a slide-in help sidebar:
Claude inspects existing components in the repo before generating, to match structure and styling conventions. Expect it to declare the configurable props via limioProps in the component's package.json.
Review what it generated
The SDK does the heavy lifting, so the review is mostly checking Claude used it instead of reimplementing it:
Messages come from
useChat'smessagesarray, greeting included. There should be no hand-rolledfetchto/api/chat/.The pending bubble (
message.pendingistrue) renders a typing indicator, not empty content.Sending is disabled while
status === "sending".Visitor text renders literally, never through a markdown renderer.
Any "start over" affordance calls
reset(), which keeps the session but drops the conversation.
Two ways to pick up the agent's theme. themeRootProps(session.presentation?.theme) spreads Limio design-token overrides onto your root element, which restyles anything that consumes those tokens; this suits surfaces built on the Limio design system. A component with its own palette should instead read the hex fields off session.presentation?.theme directly, as the example prompt does. The SDK Reference lists all nine theme fields and the bubble-style presets; Theming an Agent covers what each one controls for admins.
Preview in Storybook
useChat calls the Chat API, so stories need it mocked:
This gives you every visual state without a live agent, including the ones that are awkward to reproduce by hand, like the pending bubble and the error banner.
Test against a real agent
Storybook validates the UI; the conversation needs a real agent. Push the component through your CI/CD pipeline, then add it to a page in a sandbox environment where an agent is published. Pages on your shop domain authenticate with the visitor's Limio session cookie automatically, so there is nothing to configure. Send a message and check:
The greeting and replies render formatted.
The reply to a real question arrives in the surface, with the typing indicator while it is pending.
Component blocks the agent surfaces (a file upload, for example) either render through your registry or are skipped cleanly.
Iterate
Chat-specific follow-up prompts that work well:
Tips and troubleshooting
No greeting appears? The page's domain may not route to an agent, or the agent has no greeting configured. Domains are matched by a workflow, not by the agent itself, so check that a published workflow lists the domain and reaches an agent.
Component blocks render nothing?
MessageContentskips them when no registry entry matches. Register a renderer, or leave them unhandled deliberately.Theme not applying?
themeRootPropsonly affects styles that consume Limio design tokens. If your component has its own palette, read the hex values fromsession.presentation?.themedirectly.401 responses on a non-shop domain? Cross-origin embeds need
configureChatTransportwith a bearer-token source; same-origin shop pages need nothing. See the SDK Reference.
We are actively improving this experience. Please reach out to support@limio.com if you hit any issues.
Last updated
Was this helpful?

