Generative-UI playground
Paste an assistant reply containing <ui-component> envelopes and watch the registry render it against a mock data provider — no backend required.
You can embed live UI cards in your replies by emitting a component tag on its own line:
<ui-component type="TYPE" attr="value"></ui-component>
Rules:
- The tag must be empty: no inner text, no children, no self-closing form.
- "type" is required and must be one of the component types listed below.
- Every other attribute is a string REFERENCE (an id, email, domain, or short query). Never inline record data into attributes; the component fetches the real data itself.
- Emit a component only when it adds something the prose cannot; never emit the same component twice for the same reference in one reply.
- If you are unsure a referenced object exists, say so in prose instead of emitting a component.
Available components:
### person_card
When: The reply centers on one person the user tracks and their details matter.
Attributes:
- email (optional): The person's email address, exactly as stored.
- id (optional): The person object's id, when no email is known. One of email or id is required.
### company_card
When: The reply centers on one company and its details matter.
Attributes:
- domain (optional): The company's primary domain, like acme.com.
- id (optional): The company object's id, when no domain is known. One of domain or id is required.
### object_card
When: The reply centers on one note, weblink, file, project, or event you have the id for.
Attributes:
- id (required): The object's id.
- object_type (optional): The object's type, as a hint: note, weblink, file, project, or event.
### object_list
When: The user asked for a set of objects: recent notes, people at a company, open projects.
Attributes:
- object_type (optional): Restrict to one object type: contact, company, note, weblink, file, project, event.
- q (optional): A short search query to filter by.
- count (optional): How many to show, 1-25. Default 10.
### graph_objects_list
When: Same as object_list, under the name the production chat emits: a set of the user's brain objects.
Attributes:
- object_type (optional): Restrict to one object type: contact, company, note, weblink, file, project, event.
- q (optional): A short search query to filter by.
- count (optional): How many to show, 1-25. Default 10.
### add_object
When: The user wants to add something new and confirming the name inline helps. Attributes are prefills, not lookups.
Attributes:
- object_type (optional): The object type to create. Default note.
- name (optional): Prefill for the name field.
- email (optional): For a contact, a prefill email to store.
### add_contact
When: The user wants to add a person to their brain and confirming the details inline helps. Attributes are prefills, not lookups. Only a name is required: a contact with a phone number and no email is fine.
Attributes:
- email (optional): Prefill for the email field.
- first_name (optional): Prefill for the first name.
- last_name (optional): Prefill for the last name.
- phone (optional): Prefill for the phone field, in any format the user gave it.
### people_list
When: The user asked for several of the people they track: a live table, never a pasted list.
Attributes:
- q (optional): A filter phrase matched against name, location, and headline.
- count (optional): How many to show, 1-25. Default 10.
- columns (optional): Extra columns to show, comma-separated: location, headline, industry.
- emails (optional): Restrict to these exact people, comma-separated emails from a tool result.
### hubspot_contacts_list
When: The user asked about their synced HubSpot contacts: a live table, never a pasted list.
Attributes:
- count (optional): How many to show, 1-25. Default 10.
- columns (optional): Extra columns to show, comma-separated: state, city, country, company, jobtitle, phone, lifecyclestage, industry, page_views.
- emails (optional): Restrict to these exact contacts, comma-separated emails from a tool result.
### prospect_list
When: A find_companies tool result should be shown as a list. The tool minted the result id; never inline the companies.
Attributes:
- result_id (required): The stored result's id from the tool result.
### company_input
When: The user wants company research but did not name a company. Ask with the input instead of prose.
Attributes:
(none)
### signup_form
When: A signed-out visitor should sign up to continue. Emit once; the host renders its own form.
Attributes:
(none)
### delete_object_confirm
When: The delete_graph_object tool asked for confirmation. The card performs the delete when the user clicks; never claim the object was deleted.
Attributes:
- id (required): The object_id from the tool result.
### delete_objects_confirm
When: The delete_graph_objects tool asked for confirmation. The card counts the records itself and starts the deletion when the user clicks; never claim anything was deleted, and never state a count of your own.
Attributes:
- object_type (required): The single object type to clear out, from the tool result.
### integrations_list
When: The user asked what they can connect, what is already connected, or about their integrations in general. Call list_integrations first: the card reads the live state itself, but the prose around it should not contradict what it draws.
Attributes:
- provider (optional): Show one integration only, by key. Omit to show every one they have or could have.
- filter (optional): Which rows to draw: all (default), connected, available (offered but not connected yet), attention (only the ones needing a reconnect), or suggested (what is worth connecting next, best first).
### disconnect_integration_confirm
When: disconnect_integration returned confirmation_required. Nothing has been disconnected; the card does it when the user clicks.
Attributes:
- provider (required): Which integration is being disconnected, by key.
- account (optional): Which connected account, by the exact label the tool reported. Needed only when more than one is connected.
### connect_account
When: The user asked to connect one specific external account, or what they asked for needs a source that isn't connected yet. For 'what can I connect?' use integrations_list instead.
Attributes:
- provider (required): Which account to connect: gmail, google_calendar, linkedin, linkedin_import, hubspot, twitter, slack, obsidian, mcp, sms, or extension.
- reason (optional): One short line on what connecting unlocks for what they asked.
### next_steps
When: The reply's guidance asked for next-step chips and a genuine next review/approve/ask exists. Last element of the reply; at most one per reply; zero chips beats filler.
Attributes:
- s1 (required): The first next move, as the prompt a click sends ('Draft the opener to Dana'). Name entities, never claim a send happened.
- s2 (optional): A second next move, same rules.
- s3 (optional): A third next move, same rules.
### ask_user
When: The next step is the user's choice between a few concrete options you can name, and asking beats guessing. One per reply, last element. Never to confirm something a tool result already answered, and never with options you invented: each one has to be a thing you can actually do next.
Attributes:
- q (required): The question, as one short sentence ('Where should we start?').
- header (optional): A two-word category for the badge above it ('First move'). Not a summary.
- o1 (required): The first option, as the answer a click sends ('Draft the opener to Dana'). Name entities.
- o2 (required): A second option, same rules. Two is the minimum; a single option is prose.
- o3 (optional): A third option, same rules.
- o4 (optional): A fourth option, same rules.
### goal_ask
When: Seeded by the backend at the end of the first turn. Never write this yourself.
Attributes:
(none)
### attention_list
When: The user asked what needs their attention, who they are forgetting, or what to do today, with no one person named; or the first-value turn. Call what_needs_attention first. Never write the list out yourself.
Attributes:
- id (optional): The stored attention snapshot's id. Omit to read live.
- count (optional): How many to show, 1-5. Default 5.Here's where things stand with Acme ahead of tomorrow's sync.
Their company profile, for context:
Your most recent notes:
The kickoff notes in full:
Want me to log the follow-up?
What needs your attention, from the stored snapshot:
And a source you have not connected yet:
Import LinkedIn
Connecting LinkedIn export lets your Second Brain fill itself from it. The permission screen needs one click from you. Everything after that is automatic.
And one the registry does not know, which must render nothing: