No Dashboard, No Menus: How We Built an Interface Around Intent

Introduction
Traditional dashboards force users to hunt through menus and learn complex interfaces before they can complete a simple task. We wanted to reverse that relationship. A merchant should be able to say:
“Give customers 10% cashback on orders over $50.”
From there, the app brings the relevant controls to the merchant, updates a live preview, and guides them toward publishing the configuration. Instead of navigating the product to find the right interface, the merchant describes the outcome, and the interface comes to them.
An agent orchestrates this experience, deciding which approved interface elements to present as the conversation develops.
The user stops operating the software and starts directing it.

* The merchant configures everything manually.

* The agent assembles the experience.
From a UX Vision to a Technical Foundation
The idea began with a bold decision from our UX designer, Mika Soffer: instead of asking merchants to navigate a fixed dashboard, bring the right interface to them. I loved the simplicity of that vision and quickly discovered how challenging it would be to support technically.
To create that experience, we decided to let an agent orchestrate the dashboard’s presentation. The agent interprets the merchant’s intent and decides which approved UI components to present and when.
More Than a Chat Window
Using frontend-registered components, the agent composes the experience across two rendering areas: in-chat widgets, such as pickers and action cards, and page previews shown in the main content area.

The frontend controls which components exist, which props they accept, and where they can appear. The agent controls when they appear and the values they receive. The agent controls the sequence. The frontend controls the building blocks.
Making that model work raised three architectural questions:
Persistence: How can an interface assembled during a conversation survive a page refresh?
Communication: How can a visual control send exact values to the agent without exposing technical messages in the visible chat?
Synchronization: How can independently rendered in-chat widgets and page previews stay synchronized when neither knows whether the other is currently mounted?
1. Restoring an Interface the Agent Assembled
The agent builds the interface as the conversation progresses. That creates an immediate persistence problem.
If a preview exists only in React state, it disappears when the merchant refreshes the page or returns to the conversation later. We could have persisted the layout separately. But that would create two sources of truth: the conversation and a separate representation of the interface.
Those two records could eventually disagree. Instead, we made the conversation itself the record of what the agent rendered. When the agent decides to display a component, it does not send HTML or React code. Instead, it sends a structured render request: a small data object containing the name of an approved component and the props that component should receive.
The chat SDK, the library connecting our frontend to the agent, delivers that request to the browser:
{
"componentName": "CASHBACK_PREVIEW",
"props": {
"rewardType": "percent",
"rewardValue": 10,
"minimumOrderAmount": 50
}
}A client-side component registry receives the request. Think of the registry as an approved catalog of components. It checks that CASHBACK_PREVIEW is allowed, validates the supplied props, and maps the request to the corresponding React component.
The registry routes each component to one of two rendering areas. In-chat widgets, such as settings controls, appear directly inside the transcript. Page previews appear in the page’s main content area.
For each page preview, we store an invisible render entry in the transcript and use a small projection layer to render the corresponding component in the main area. The invisible render entry acts as a persistent instruction: “Render this preview with these props.” It is part of the conversation history even though the merchant does not see it as a chat message.
The conversation does not store pixels. It stores the instructions needed to rebuild the interface. Because older render requests may be replayed by newer frontend versions, component contracts must evolve carefully.
2. Sending Exact Data Without Cluttering the Chat
Interactive in-chat widgets create another problem. A selection may be visually obvious to the merchant, but the agent still needs the exact value. Our In-chat widgets send structured messages instead:
{
"hidden": true,
"cashbackSettings": {
"rewardType": "percent",
"rewardValue": 15,
"minimumOrderAmount": 70
}
}The message becomes part of the agent’s context but remains absent from the visible transcript. The merchant interacts with an in-chat widget, the agent receives exact, machine-readable values.


3. Draft in the Frontend, Decisions in the Conversation
An in-chat widget and its corresponding page preview render independently, so neither can assume that the other is mounted.
To keep them loosely coupled, they communicate through an in-memory event bus. As the merchant edits a setting in the widget, it keeps the draft locally and emits a frontend event. Any mounted page preview that subscribes to that event updates immediately, without involving the agent.

The events are intentionally temporary. If no matching page preview is mounted, the events are discarded. A page preview rendered later initializes from the values supplied by the agent.
When the merchant confirms the configuration, the in-chat widget sends the exact values as a non-visible structured message. They become part of the conversation and can be passed to later components or publishing actions.
This creates three phases:
Experiment: Keep drafts local and update mounted previews.
Confirm: Record the selected values in the conversation.
Publish: Turn the confirmed configuration into a backend action.
Draft state belongs to the live interface. Confirmed state belongs to the conversation.
What We Learned
On the day we released our chat-based setup, a merchant used it to launch a new cashback program in about ten minutes with just a few simple "yes" responses. The agent brought the settings, live preview, and publishing steps directly to them. That moment proved the concept worked. From there, we took away three core lessons:
1. "Dashboardless" does not mean "without UI."
Users still need visual interfaces to make decisions. The agent doesn't replace the frontend; it simply brings the right tools to the user exactly when they need them.
2. The conversation is the source of truth.
While frontend events handle temporary draft states (like tweaking a setting), the chat transcript stores confirmed decisions and the instructions needed to rebuild the interface. This eliminates the need to maintain a separate layout record.
3. The component registry is a critical boundary.
Because the transcript drives the UI, the component registry must strictly validate the agent's requests and ensure backward compatibility so older conversations can still be replayed safely.
The agent does not replace the frontend. It changes who composes the experience.

This post was written by Idan Layfer
More of Wix Engineering's updates and insights:
Join our Telegram channel
Visit us on GitHub
Subscribe to our YouTube channel


Comments