Skip to content

Account – Channels

  • Path: /account/channels
  • Parent: README.md
  • Children:
    • channels-social-channels.md
    • channels-review-platforms.md
    • channels-facebook-messenger.md
    • channels-web-chat.md
    • channels-whatsapp.md
    • channels-sms.md
  • Status: Implemented (v1): global channels hub with shared filters, stable tab totals, and per-family table sections.

These Figma links are kept for legacy context only. If they conflict with the shipped UI or the route spec below, follow the docs and current implementation.

Centralize channel configuration: discover available connectors, connect/disconnect channels, and monitor channel health.

Get Started integration:

  • Channel types selected during Get started Step 1 must be reflected here for the active workspace.
  • Channels added during Get Started Step 2 are linked to the default workspace, default workspace group, and default knowledge base (see Default Workspace, Knowledge Base & Agent). The Channels table must display the default workspace name, default group name, and default KB name in the Workspace, Group, and Knowledge base columns for those connections (MVP: all connections use the default).
  • Users can connect/add needed channels either:
    • by completing Get started (recommended for first-time setup), or
    • directly on this Channels page (admin surface).
  • Workspace Admin
  • Permissions: channels.view, channels.connect, channels.disconnect (TBD)

Reference: Roles & Permissions Model

  • Top bar breadcrumb: Account > Channels
    • Channels is a dropdown; clicking it opens the Account submenu for quick navigation within Account.
  • Merged top section:
    • Channels title + count badge
    • In the same surface, below the title row and with no divider, the filters/CTA row:
    • Workspace filter: A multi-select combobox (replaces the former “All workspaces” button). The user can select one or more workspaces; the channel tables show only connections that belong to the selected workspace(s). When no workspace is selected, show all (or use a sensible default). Supports multiple selection. The filter lists only real workspaces from the workspace store; orphaned knowledge-base references must not create extra workspace filter options.
    • Knowledge base filter: A multi-select combobox (replaces the former “All knowledge bases” button). The user can select one or more knowledge bases; the channel tables show only connections linked to the selected KB(s). When no KB is selected, show all. Supports multiple selection.
    • The search icon button is removed.
    • Add channel button (standard button, no arrow icon): clicking it opens the unified Add channel wizard in a large centered modal. This is the primary entry point for adding any channel family from the page header. The wizard replaces the former page-level sheet and the ad-hoc platform popovers/dialogs. All addConnection calls from this wizard pass addedVia: "channels-page" so the Get Started overlay does not re-appear.
  • Channel type tabs (between the filters row and the table content area):
    • A horizontal tab list with 6 tabs, in fixed order:

      #Tab labelChannel type key
      1Social commentssocial-comments
      2Review platformsreview-platforms
      3FB Messengerfacebook-messenger
      4Web chatweb-chat
      5WhatsAppwhatsapp
      6SMSsms
    • Only the active tab’s section (section header + table) is shown; all other sections are hidden.

    • Default active tab: social-comments (first tab). The active tab is persisted in localStorage under the key channels-active-tab so the user’s last-selected tab is restored on next visit. If no stored value is found, fall back to social-comments.

    • The tab list is rendered using the shadcn Tabs / TabsList / TabsTrigger / TabsContent primitives (already in the project). Each TabsContent wraps one section component unchanged.

    • Tab count rule: each tab label count shows the total number of channels in that channel type across the page dataset. Workspace, knowledge-base, and platform filters change the visible table rows below, but they do not change the counts shown on the tab labels.

    • Visual style: Shadcn default pill style — matches the reference image and the Shadcn TabsDemo. Do not add a border or a dark-gray active background.

      • TabsList: light grey background (bg-muted), rounded corners (rounded-lg override on the page; base is rounded-md), internal padding p-1, no border. The list is content-width (not full-width) — it wraps only the tab triggers. Do not add w-full; the list is left-aligned naturally within its wrapper. The container itself carries no shadow — the active trigger provides the depth.
      • TabsTrigger (inactive): transparent background (blends with container), muted text (text-muted-foreground), regular font weight, no shadow.
      • TabsTrigger (active): white background (bg-background) with a subtle shadow (shadow-sm) so the selected tab appears raised — this is the Shadcn default data-[state=active]:bg-background data-[state=active]:shadow-sm. Do not override to bg-[#e5e5e5] or any dark-gray value.
      • No underline, no border-b, no border-transparent, no border border-border classes on the list or any trigger.
      • Sizing rule: Use px-3 py-1.5 text-sm on triggers and p-1 on the list to match the reference proportions.
  • Per-table layout control: Each channel table has a column visibility control (e.g. a “Columns” or view-column icon button) that opens a popover listing all table columns with switchers (checkboxes or toggles). The user can show or hide specific columns to customize the table layout. At least one primary column (e.g. Profile / Widget title / Phone number) should remain visible. The previous “discover_tune” icon button in the section header is removed.
  • Agent column: The Agent column is shown only for Chatti Live channel tables (facebook-messenger, web-chat, whatsapp, sms).
    • The cell is an editable single-select dropdown (same interaction style as Workspace/Knowledge base cells).
    • The selected value is staged and confirmed through a Sonner confirm/cancel toast before persisting.
    • Assigned values link to /account/workspaces/{workspaceId}?tab=agents when workspace context is resolvable.
    • The column is not shown for social-comments or review-platforms.
  • Connector grid/list:
    • Each connector is presented as a ChannelCard (see component doc below)
    • Card body: connector identity + connection state + primary action (Connect/Disconnect/Configure) (TBD per connector)
    • Card bottom section shows the App name (the downstream app surface that will be used once connected)
    • Empty state: if no connectors are connected yet, show an “add your first channel” empty state with a primary CTA to start a connect flow (TBD exact CTA label/target).
  • Tables: All channel tables use the standard shadcn Table component (Table, TableHeader, TableBody, TableRow, TableHead, TableCell) for consistent styling and accessibility.
  • Channel Card: Component: Channel Card
  • Channel Selector: Component: Channel Selector
  • Add channel wizard: src/app/account/channels/_components/add-channel-wizard.tsx
  • Shared connection-flow modules: Per-channel connection UI (platform buttons, chip lists, instructions, SMS controls, etc.) is extracted into src/components/onboarding/shared-connection-flows.tsx. Both the Add Channel wizard and the Get Started Step 2 overlay import from this shared module. This avoids duplication and ensures consistent UX across both surfaces.
  • ChannelIcon (src/app/account/channels/_components/channel-icon.tsx): Renders a platform-specific logo (SVG icon) given a platform and channelType. Used in channel table rows, the node view’s channel detail nodes, and any surface that needs to identify a channel connection by its platform logo. Accepts platform: string and channelType: string props.

Use one unified centered modal wizard for every add-channel entry point on the Channels page.

  • The page-level Add channel CTA opens the wizard with the currently active channel tab preselected in Step 1 — Channel while keeping that step visible, so users can switch to a different family before continuing.
  • The wizard replaces:
    • add-channel-dialog.tsx (right sheet)
    • add-social-profile-dialog.tsx
    • add-review-profile-dialog.tsx
    • add-fb-messenger-dialog.tsx
  • Use a centered modal, not a side sheet.
  • Preferred implementation: shadcn Dialog / DialogContent.
  • Width: max-w-[640px]
  • Height: fixed feeling with a scrollable body and persistent footer
  • The modal must include:
    • a standard dialog header consistent with other dialogs such as Add knowledge base
    • a stable dialog title such as Add channel
    • close button in the top-right
    • step indicator near the top of the body content
    • step title below the step indicator
    • persistent footer with navigation actions
    • use Material Symbols in the step indicator rather than numbered badges or radio-style icons
#StepPurposeSkip rule
1ChannelChoose the channel type: Social comments, Review platforms, FB Messenger, Web chat, WhatsApp, SMSNever skipped
2PlatformChoose the concrete platform for multi-platform familiesSkip for single-platform families
3ConnectComplete the in-wizard connect/setup action where neededSkipped for Social comments and Review platforms after successful platform auth
3.5GreetingsConfigure FB Messenger welcome message and ice breakersFB Messenger only; always shown after Connect for that family
4CustomizationConfigure web chat widget settings and appearanceIncluded only for Web chat
5DestinationChoose workspace and knowledge base; KB defaults to the workspace’s default KB. For Chatti Live families (FB Messenger, Web chat, WhatsApp, SMS), also choose exactly one Agent.Never skipped
  • Step 1 — Channel
    • Render as a vertical radio list.
    • Present the list inside a single rounded container with an outer border and subtle dividers between rows.
    • Each row shows the channel family label and a one-line description.
    • Do not repeat the step title as body helper copy when it adds no new information.
    • Selecting a row enables the footer Continue button.
    • The user advances with Continue; auto-advance is not used for this step.
    • Use comfortable vertical spacing between rows so the list reads as a clear form step, not a compressed menu.
    • Do not use full row borders on each item; use the grouped container and inner dividers instead.
  • Step 2 — Platform
    • Render as a list of selectable platform rows.
    • Social comments uses the social platform set.
    • Review platforms uses the review platform set.
    • FB Messenger, Web chat, WhatsApp, and SMS skip this step because each is single-platform in MVP.
    • For Social comments and Review platforms, clicking a platform opens a second modal that imitates the external auth/login flow with skeleton UI.
    • On successful login, that auth modal closes and the wizard advances directly to Destination.
    • If the auth modal is cancelled or closed, the user stays on the Platform step and does not advance.
  • Step 3 — Connect
    • FB Messenger preserves the existing New profile / Select existing one dual-flow behavior inside this step.
    • Web chat shows embed onboarding only (Instructions, embed code snippet + Copy code, Check status).
    • WhatsApp reuses the same Connect UI pattern as Get Started Step 2:
      • Instructions list
      • Add number action that opens the same auth/login modal flow used by Social comments
      • Connected number chip with remove affordance
      • On successful login, the wizard advances to Destination and shows the connected number chip there (read-only, no remove action)
    • SMS reuses the same controls and logic as Get Started Step 2:
      • Mode tabs: Get a new number / Use my number
      • Country code selector, area code input, and number selector
      • No inline Add action in the wizard; user proceeds with Next
      • Compliance warning block
      • The SMS flow also collects and persists a structured 10DLC compliance payload on the connection via smsCompliance
      • Compliance fields are split into two groups:
        • Brand fields: entity, vertical, display name, company name, registration number, brand type, contact phone, contact email, website, address, country, state, city, zip code
        • Campaign fields: campaign description, message flow, privacy policy URL, use case type, 5 message samples, opt-in / opt-out / help keywords and messages, plus compliance booleans such as number pooling and embedded links
      • The campaign form uses accordion sections so operators can complete the submission progressively while seeing completion indicators on filled sections
      • On wizard completion, the payload is persisted through setSmsCompliance(id, compliance) and stored on ChannelConnection.smsCompliance
      • Destination shows the connected SMS number as a read-only chip based on values provided in Connect
  • Step 3.5 — Greetings (FB Messenger only)
    • Shown only for facebook-messenger, inserted between Connect and Customization.
    • Welcome message: textarea, max 160 characters. Shown to users who open the conversation for the first time.
    • Ice breakers: repeatable text inputs, max 5 items, max 20 characters each. Shown as quick-reply prompts at the start of a conversation.
    • This step is always valid (no required fields); the user can proceed with empty values.
    • On wizard completion, greetings are persisted via setConnectionMessengerGreetings(id, welcomeMessage, iceBreakers) in the channels context (stored on the ChannelConnection as messengerWelcomeMessage and messengerIceBreakers).
    • Step icon: waving_hand. Step label: “Greetings”. Step title: “Set up greetings”.
  • Step 4 — Customization
    • This step is shown only for Web chat.
    • Displays a minimal skeleton placeholder only (no section subtitles/labels) while controls are being finalized.
    • The standalone Customize widget button is removed.
  • Step 5 — Destination
    • Show Workspace and Knowledge base as editable selectors.
    • For Chatti Live families (FB Messenger, Web chat, WhatsApp, SMS) only, show Agent as a required single-select field.
    • The Agent selector options are filtered to agents in the selected Workspace and selected Knowledge base.
    • Agent multi-select is not allowed.
    • Group is removed from the wizard UI.
    • Workspace and Knowledge base dropdown options are ordered alphabetically by label.
    • The Knowledge base selector is filtered to the selected workspace’s KBs only.
    • Workspace is unselected by default when the wizard opens.
    • The Knowledge base selector stays disabled until a workspace is selected.
    • Preselect workspace.defaultKbId; if absent, fall back to the first KB in that workspace.
    • Workspace and Knowledge base are always required to continue.
    • Agent is additionally required for Chatti Live families only.
    • Optional helper copy under the KB field: AI will use this knowledge base to handle this channel.
    • This is the final step; the footer primary action label is Add.
  • First visible step: show Cancel and Next
  • Middle steps: show Back, Cancel, and Next
  • Final step (Destination): show Back, Cancel, and Add
  • Next stays disabled until the current step is valid.
  • Cancel always closes the wizard.
  • For FB Messenger’s “new profile” flow, Cancel must preserve the documented rollback behavior for any pending new connections created during that session.
  • Header CTA opens the wizard with Step 1 (Channel) visible and the active tab preselected (Social comments, Review platforms, FB Messenger, Web chat, WhatsApp, or SMS).
  • Every addConnection(...) call from the wizard must pass addedVia: "channels-page".
  • Final commit assigns each created connection to the resolved default KB for the selected workspace using setConnectionKnowledgeBase(...).
  • New social/review/FB connection labels are workspace-oriented and human-readable (brand-like), for example: Starbucks, @starbucks, Starbucks Official, Starbucks on Google, instead of generic Profile N.
  • If the selected KB is incomplete, the existing warning toast behavior still applies.
  • Primary file: src/app/account/channels/_components/add-channel-wizard.tsx
  • Main wiring: src/app/account/channels/page.tsx
  • Reuse/extract logic from the current sheet where practical:
    • platform sign-in behavior
    • FB Messenger pending selection and rollback logic
    • existing platform constants
  • Remove or stop using the deprecated dialog/sheet entry points once the wizard is live.

One-line summary for the implementer: Use the Shadcn default pill style — TabsList gets only layout overrides (h-auto rounded-lg p-1; no w-full, the list is content-width); each TabsTrigger gets only rounded-md px-3 py-1.5 text-sm font-medium — the base @/components/ui/tabs already supplies bg-muted for the list and data-[state=active]:bg-background data-[state=active]:shadow-sm for the active trigger; do not add border border-border, bg-[#f5f5f5], shadow-sm on the list, or data-[state=active]:bg-[#e5e5e5] on the trigger.

  • File: src/app/account/channels/page.tsx
  • No new component file is needed; the tab wiring lives entirely in the page.
  • Use the existing shadcn Tabs, TabsList, TabsTrigger, TabsContent primitives (imported from @/components/ui/tabs).
const CHANNEL_TABS = [
{ id: "social-comments", label: "Social comments" },
{ id: "review-platforms", label: "Review platforms" },
{ id: "facebook-messenger", label: "FB Messenger" },
{ id: "web-chat", label: "Web chat" },
{ id: "whatsapp", label: "WhatsApp" },
{ id: "sms", label: "SMS" },
] as const;
type ChannelTabId = typeof CHANNEL_TABS[number]["id"];
const LS_KEY = "channels-active-tab";
function readStoredTab(): ChannelTabId {
if (typeof window === "undefined") return "social-comments";
const stored = localStorage.getItem(LS_KEY);
const valid = CHANNEL_TABS.map((t) => t.id) as string[];
return (stored && valid.includes(stored) ? stored : "social-comments") as ChannelTabId;
}
const [activeTab, setActiveTab] = React.useState<ChannelTabId>(readStoredTab);
const handleTabChange = React.useCallback((value: string) => {
const id = value as ChannelTabId;
setActiveTab(id);
localStorage.setItem(LS_KEY, id);
}, []);
  • useState initializer reads from localStorage on first render (client-only; safe because the page is "use client").
  • On tab change, persist to localStorage.

Replace the current <div className="flex flex-col gap-10 p-6"> channel sections block with:

<Tabs value={activeTab} onValueChange={handleTabChange} className="flex flex-col">
<div className="px-6 py-3">
<TabsList className="h-auto rounded-lg p-1">
{CHANNEL_TABS.map((tab) => (
<TabsTrigger
key={tab.id}
value={tab.id}
className="rounded-md px-3 py-1.5 text-sm font-medium"
>
{tab.label}
</TabsTrigger>
))}
</TabsList>
</div>
<div className="p-6">
<TabsContent value="social-comments" className="mt-0">
<SocialCommentsSection ... />
</TabsContent>
<TabsContent value="review-platforms" className="mt-0">
<ReviewPlatformsSection ... />
</TabsContent>
<TabsContent value="facebook-messenger" className="mt-0">
<FacebookMessengerSection ... />
</TabsContent>
<TabsContent value="web-chat" className="mt-0">
<WebChatSection ... />
</TabsContent>
<TabsContent value="whatsapp" className="mt-0">
<PhoneSection title="WhatsApp" ... />
</TabsContent>
<TabsContent value="sms" className="mt-0">
<PhoneSection title="SMS" ... />
</TabsContent>
</div>
</Tabs>
  • Pass all existing props to each section component unchanged.
  • TabsContent with className="mt-0" removes the default top margin.
  • The TabsList is a self-contained pill container — no wrapping border-b row needed. The base @/components/ui/tabs already provides bg-muted on the list and data-[state=active]:bg-background data-[state=active]:shadow-sm on the trigger (white active tab with subtle shadow). The page only needs layout overrides (h-auto rounded-lg p-1). The list is content-width — do not add w-full or justify-start; it shrinks to fit the triggers and is left-aligned by default within its px-6 py-3 wrapper.
  • Do not add border border-border, bg-[#f5f5f5], or shadow-sm on the list. Do not add data-[state=active]:bg-[#e5e5e5] on the trigger — the default white (bg-background) is correct.
  • Do not use border-b, border-transparent, rounded-none, or bg-transparent on the list or triggers.
  • Section components (SocialCommentsSection, ReviewPlatformsSection, FacebookMessengerSection, WebChatSection, PhoneSection) are untouched.
  • Filtering logic (filterConnections, workspace/KB comboboxes) is untouched.
  • Filtering semantics and table column customization stay unchanged.

Column sorting is now part of the shipped Channels page behavior.

  • Sort is handled client-side per visible table and affects the current section only.
  • Clicking a sortable header toggles between ascending and descending order.
  • The active sort indicator changes from the neutral swap icon to directional arrows.
  • There is no forced default sort on first render; tables keep their incoming data order until the user selects a sortable column.

Sortable columns by table:

TableSortable columns
Social commentsProfile, Platform, Workspace, Knowledge base
Review platformsProfile, Platform, Workspace, Knowledge base
FB MessengerProfile, Workspace, Knowledge base
Web chatWidget title, Workspace, Knowledge base
WhatsAppPhone number, Workspace, Knowledge base
SMSPhone number, Workspace, Knowledge base

  • Empty: user has no connected channels (“nothing added”)
    • Show an empty-state panel in the main canvas (illustration/text is UI-level).
    • Primary CTA: connect a channel (TBD whether it opens a picker, starts the current category connect flow, or routes to Get Started step 2).
    • Secondary guidance (TBD): explain that connected channels power downstream apps (Comment Responder / Chatti Live) and that the channel cards will show the App name once connected.
  • Loading: load channel catalog + current connections
  • Error: provider outage / permissions error
  • Complete: channel list and statuses displayed

Channel ownership model: Agent → KB → Channel

Section titled “Channel ownership model: Agent → KB → Channel”

Channel families split into two ownership tiers based on how the Knowledge base is assigned.

Direct KB channels (Social comments, Review platforms)

Section titled “Direct KB channels (Social comments, Review platforms)”
  • The Knowledge base is set directly on the connection (ChannelConnection.knowledgeBaseId).
  • Users assign and change the KB inline in the channel table row.
  • No agent is involved in this tier.

Agent-managed channels (FB Messenger, Web chat, WhatsApp, SMS)

Section titled “Agent-managed channels (FB Messenger, Web chat, WhatsApp, SMS)”
  • The Knowledge base is owned by the Agent, not the connection.
  • The connection is assigned to an Agent; the Agent carries the KB.
  • The effective KB for the channel is derived as: connection → agent → agent.knowledgeBaseId → KB.
  • Each workspace also carries a defaultAgentId. In the Add Channel wizard, that default agent is preselected for agent-managed channel families when it is eligible for the selected channel type.
  • Users cannot set a KB directly on the connection for these families. The KB shown in the channel table is read-only, resolved from the assigned agent.
  • To change the KB for an agent-managed channel, the user must update the agent’s KB in the Agents tab.
  • The Agent selector in the wizard (Step 5 — Destination) is filtered to agents in the selected workspace and by channel-type eligibility, so the KB is effectively chosen by choosing the agent.

This model is enforced in the UI:

  • The KB column in agent-managed channel tables is read-only (displays the agent’s KB name, or if no agent is assigned yet).
  • The KB column in direct KB channel tables (Social comments, Review platforms) is an editable inline selector.
Channel familyKB set onKB editable in tableAgent required
Social commentsConnectionYes — inline selectorNo
Review platformsConnectionYes — inline selectorNo
FB MessengerAgentNo — read-only, derived from agentYes
Web chatAgentNo — read-only, derived from agentYes
WhatsAppAgentNo — read-only, derived from agentYes
SMSAgentNo — read-only, derived from agentYes

  • Filtering: Table data is filtered by the workspace and/or knowledge base combobox selections. A connection is shown if: (1) its knowledge base belongs to one of the selected workspaces (when workspace filter is applied), and (2) its knowledgeBaseId is in the selected knowledge bases (when KB filter is applied). Empty selection for a filter means “no filter” (show all). MVP: workspace and KB options come from seed (e.g. SEED_WORKSPACES, SEED_KNOWLEDGE_BASES); connections have knowledgeBaseId; workspace is derived from the KB’s workspaceId.
  • Connection flows and health checks per channel type.
  • The bottom “App name” section is derived from the channel’s downstream handling surface (assignment rules TBD; must be consistent across Account and Get Started flows).
  • Primary actions are gated by permissions and plan/contract constraints; disabled reasons must be visible.
  • If onboarding is incomplete, the Get started main-menu entry remains available so the user can resume setup (see Get Started – Stepper (3 steps)).

Domain refs:

Use the page-level Add channel CTA to open the wizard. The active tab preselects the channel family, so from the Social comments tab the wizard opens with Social comments preselected while keeping Step 1 — Channel visible.

Step 1 — Platform selection inside the wizard

Section titled “Step 1 — Platform selection inside the wizard”

Inside the wizard, the first visible step for Social comments is the Platform step. It shows a selectable list of 4 platform options:

#Platform
1Facebook
2Instagram
3LinkedIn
4Threads

The list is defined as SOCIAL_PLATFORMS and reused by the wizard. Clicking a platform selects it and advances to the Connect step.

A centered modal wizard remains open on top of the page. After the user selects a social platform, a second auth/login modal opens to imitate the external provider flow. On successful login, that modal closes and the wizard advances directly to Assign. If the auth modal is cancelled or closed, the user remains on the Platform step.

  • The wizard open state is page-level.
  • SocialCommentsSection no longer owns its own add-profile dialog state.
src/app/account/channels/_components/add-channel-wizard.tsx
export const SOCIAL_PLATFORMS = [
{ id: "Facebook", label: "Facebook" },
{ id: "Instagram", label: "Instagram" },
{ id: "LinkedIn", label: "LinkedIn" },
{ id: "Threads", label: "Threads" },
] as const;
export const REVIEW_PLATFORMS = [
{ id: "Trustpilot", label: "Trustpilot" },
{ id: "Google Review", label: "Google Review" },
{ id: "Yelp", label: "Yelp" },
] as const;

Note: Platform id values use PascalCase (e.g. "Facebook", not "facebook"). This is the canonical form stored in ChannelConnection.platform. All filtering, matching, and ChannelIcon lookups must use PascalCase ids.

Get Started overlay must not re-appear after adding from Channels page

Section titled “Get Started overlay must not re-appear after adding from Channels page”

Adding a connection from the Channels page (via the Add profile dialog) must not re-show the Get Started overlay. Only connections added during the Get Started onboarding flow may clear the session dismissal flag.

Rule: The add-connection mutation in the setup-status store accepts an optional addedVia?: "combobox" | "channels-page" field. The store clears dismissedForSession only when addedVia is undefined (i.e. the call originates from the Get Started flow). When addedVia is set, dismissedForSession is left unchanged.

Implementation contract:

  • The Add profile dialog’s onAdd handler must call addConnection(...) with addedVia: "channels-page".
  • The combobox (existing profile picker) already passes addedVia: "combobox" — no change needed there.
  • Get Started Step 2 does not pass addedVia, so it continues to clear the session dismissal as before.

Get Started overlay must not re-appear after deleting or editing a connection

Section titled “Get Started overlay must not re-appear after deleting or editing a connection”

Rule: The remove-connection, toggle-connection-field, and set-comment-type mutations in the setup-status store must not clear dismissedForSession. These are routine channel management operations performed from the Channels page and must never re-show the onboarding overlay.

Bug history: Prior to this fix, remove-connection (and the two other mutations) unconditionally set dismissedForSession = false. Because AccountShell re-fetches setup status whenever connections.length changes, deleting a connection caused the overlay to reappear immediately after the dialog closed.

Implementation contract: In src/server/setup-status-store.ts, the remove-connection, toggle-connection-field, and set-comment-type cases must not touch dismissedForSession.


FB Messenger — Add Facebook profile dialog

Section titled “FB Messenger — Add Facebook profile dialog”

Full spec lives in Account – Channels – Facebook Messenger“Add Facebook profile dialog (FB Messenger)”.

Summary for quick reference:

  • Connect UI lives inside: src/app/account/channels/_components/add-channel-wizard.tsx
  • Two tabs (shadcn Tabs, content-width TabsList, same pill style as page channel tabs):
    • Tab 1 “New profile” (default): “Add a new profile” button opens auth dialog. On successful login, a single pending profile is created and the wizard advances to Destination.
    • Tab 2 “Select existing one”: single-select shadcn Select bound to local pendingSelectedLabel state. addConnection is called only on final Add click.
  • Add enabled: Tab 1 → one pending new profile exists; Tab 2 → one existing profile is selected.
  • Backdrop click must call handleCancel (same rollback logic as Cancel button).
  • addConnection must return the new connection id (required for Tab 1 rollback).

Connection settings — incomplete knowledge base

Section titled “Connection settings — incomplete knowledge base”

When the user assigns a channel in the Connection settings dialog:

  • they select a Workspace and then a Knowledge base in that workspace;
  • for Chatti Live channel types (facebook-messenger, web-chat, whatsapp, sms) they also select an Agent after the KB field.

AI engines require a complete (configured) knowledge base to handle the channel. Every workspace has at least one KB (see Default Workspace, Knowledge Base & Agent — new workspaces get a blank KB automatically), so there is no “workspace with no KBs” case to handle.

  • If the user saves (or confirms) a connection with a knowledge base whose status is incomplete (e.g. status === "incomplete"), the platform must:

    1. Show a warning toast using the sonner component. Message (or equivalent): “This knowledge base is incomplete. Complete its setup so AI can handle this channel.”
    2. The save/apply action still proceeds (the channel is linked to that KB). The toast is informational: the user is warned that the channel will not be fully handled by AI until the KB is completed.
  • For channel families that may require provider re-authentication (Social comments, Review platforms, FB Messenger), the Connection settings dialog includes a Reconnect profile action above the Workspace field.

    • Clicking Reconnect profile opens an in-place auth dialog (skeleton external login simulation) from the Connection settings dialog.
    • Clicking Log in in that auth dialog closes the auth modal and shows a reconnect-success toast.
    • Reconnect profile is not shown for Web chat, WhatsApp, or SMS.
  • Trigger: after the user clicks Save in the Connection settings dialog and the selected KB has status === "incomplete". Do not show the toast when the selected workspace has no KBs (that case no longer occurs once every workspace has at least one KB).

  • Implementation location: src/app/account/channels/_components/connection-settings-dialog.tsx. When onSave is invoked, the parent (or the dialog) should check the chosen KB’s status; if incomplete, call toast.warning(...) (e.g. after calling setConnectionKnowledgeBase or in the same handler). The dialog receives knowledgeBaseOptions that include KB metadata (id, name, workspaceId); the options must also expose status (or the Channels page passes a lookup/map of kbId → status) so the dialog or parent can show the toast when the saved KB is incomplete.

  • SMS settings variant:

    • SMS connection settings use the larger dialog width tier and include editable brand and campaign compliance sections in addition to the shared workspace / KB / agent controls.
    • Saving an SMS settings dialog persists the compliance payload through setSmsCompliance(id, compliance) and stores it on ChannelConnection.smsCompliance.

Reference: Default Workspace, Knowledge Base & Agent — rules 6 (every workspace has a KB; new workspace gets auto blank KB), 7 (only-one-KB cannot be deleted), 8 (incomplete KB → sonner when channel assigned).


Row actions — three-dots menu & delete confirmation

Section titled “Row actions — three-dots menu & delete confirmation”

Every channel table row has a MoreBtn (three-dots more_horiz icon) that appears on row hover (opacity-0 group-hover:opacity-100). Clicking it must open a contextual dropdown menu. The menu includes Delete, and for unassigned Agent-managed channels (facebook-messenger, web-chat, whatsapp, sms) also Assign in Agents (deep-link to workspace Agents tab).

PropertyValue
TriggerMoreBtn — the existing more_horiz icon button in the last cell of each row
Componentshadcn DropdownMenu / DropdownMenuTrigger / DropdownMenuContent / DropdownMenuItem (add dropdown-menu to the project via npx shadcn@latest add dropdown-menu if not present)
Alignmentalign="end" — the menu opens left-aligned to the trigger so it does not overflow the table edge
Items”Delete” and conditional “Assign in Agents” (shown for unassigned agent-managed channels)
“Delete” item styleDestructive text color — use className="text-destructive focus:text-destructive" on DropdownMenuItem (or the shadcn inset destructive variant). Include a delete (trash) Material Symbol icon to the left of the label at fontSize: 16.
Click behaviourClicking “Delete” closes the dropdown and immediately opens the delete confirmation dialog (see below). It does not call removeConnection directly.

MoreBtn must be refactored to accept an onDelete callback prop and wire DropdownMenu internally:

function MoreBtn({ onDelete }: { onDelete: () => void }) { … }

Every call site passes onDelete={() => setPendingDeleteId(row.id)} (or equivalent local state).


Because deletion is destructive and irreversible, the user must confirm before the app calls removeConnection(id).

PropertyValue
ComponentA local modal dialog. Use the same fixed-overlay pattern as add-group-dialog.tsx (fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4). A shadcn AlertDialog is also acceptable if already in the project.
Dialog filesrc/app/account/channels/_components/delete-connection-dialog.tsx
TriggerOpening is driven by `pendingDeleteId: string
ElementCopy
TitleRemove connection?
BodyThis will permanently remove the connection. This action cannot be undone.
Cancel buttonCancel (secondary / outline variant)
Confirm buttonRemove (destructive variant — variant="destructive" on the shadcn Button)
  1. User clicks Cancel → dialog closes, pendingDeleteId is set to null. No side-effect.
  2. User clicks RemoveremoveConnection(pendingDeleteId) is called, then pendingDeleteId is set to null and the dialog closes. The row disappears from the table immediately (optimistic, driven by context state).
  3. Clicking the backdrop (overlay) → same as Cancel.
interface DeleteConnectionDialogProps {
open: boolean;
onClose: () => void;
onConfirm: () => void;
}

The caller resolves id before opening; the dialog itself is stateless and does not need the id.


MoreBtn click (row.id)
→ pendingDeleteId = row.id // opens dialog
dialog Cancel / backdrop
→ pendingDeleteId = null // closes dialog, no-op
dialog Remove (Confirm)
→ removeConnection(pendingDeleteId)
→ pendingDeleteId = null // closes dialog, row removed

pendingDeleteId is local state (useState<string | null>(null)) owned by each section component (e.g. SocialCommentsSection). It is not lifted to the page.


  • channel.connection.delete_initiated — fired when the user clicks “Delete” in the dropdown (before confirmation).
  • channel.connection.deleted — fired after removeConnection is called (confirmed delete).

  • GET /channels/connectors
  • GET /workspaces/{id}/channels
  • POST /channels/{type}/connect
  • POST /channels/{type}/disconnect
  • Credentials must be masked; actions audited.
  • Token expired; connector still “connected” but degraded.
  • App surface assignment unavailable; the bottom “App name” section must degrade gracefully (e.g., show TBD/unknown without breaking connection actions).
  • Strict permission gating for connect/disconnect
  • Prevent secret exposure

Reference: Security & Compliance

  • account.channels.viewed
  • channel.connected
  • channel.disconnected
  • channel.connection.delete_initiated — user opens the delete confirmation dialog
  • channel.connection.deleted — user confirms and the connection is removed

Reference: Analytics Events (MVP)


Widget auto-show behavior is a property of the web chat connection, not the agent. These settings are owned by ChannelConnection and appear in two places:

1. Add Channel wizard — Connect step (web-chat only)

Section titled “1. Add Channel wizard — Connect step (web-chat only)”

During the Connect step for Web chat, show the widget visibility controls below the embed code section:

FieldTypeNotes
Auto-show widgetToggle (Switch)Enables automatic widget display without user interaction. Default: off.
Delay (seconds)Number input0–60 seconds; disabled when auto-show is off. Default: 0.

2. Connection settings dialog — web-chat connections only

Section titled “2. Connection settings dialog — web-chat connections only”

When editing an existing web chat connection, show the widget visibility controls below the Agent selector:

FieldTypeNotes
Auto-show widgetToggle (Switch)Same as above.
Delay (seconds)Number inputSame as above.

These fields are stored on ChannelConnection (not on Agent.integrationConfig):

interface ChannelConnection {
// ... existing fields ...
autoVisibility?: boolean; // web-chat only
visibilityDelay?: number; // web-chat only; 0–60 seconds
}

The corresponding SetupStatusMutation must include a new set-connection-widget-visibility type:

| { type: "set-connection-widget-visibility"; id: string; autoVisibility: boolean; visibilityDelay: number }

The “Visibility” tab has been removed from the agent edit modal. AgentIntegrationConfig.webChat no longer contains autoVisibility or visibilityDelay. Those fields are removed from the type.


Messenger greetings (welcome message + ice breakers) are stored on ChannelConnection, not on Agent.integrationConfig. They are persisted via setConnectionMessengerGreetings(id, welcomeMessage, iceBreakers) in the channels context.

interface ChannelConnection {
// ... existing fields ...
messengerWelcomeMessage?: string; // facebook-messenger only
messengerIceBreakers?: string[]; // facebook-messenger only; max 5 items
}

setConnectionMessengerGreetings updates the connection in the user-data store directly (via setAndPersist). It does not go through the SetupStatusMutation pipeline — there is no set-connection-messenger-greetings mutation type in SetupStatusMutation. This is intentional: greetings are a connection-level property persisted alongside other connection fields.

  1. Add Channel wizard — Greetings step (FB Messenger only): user sets welcome message and ice breakers before the Destination step. On wizard completion, setConnectionMessengerGreetings is called with the new connection id.
  2. Connection settings dialog — not yet surfaced for editing existing connections (future iteration).

Recent implementation updates that should be treated as current behavior:

  • Connection settings dialog shell now matches the same structural pattern used by Add knowledge base:
    • header with top separator (border-b)
    • body content area
    • footer with action row separator (border-t)
  • Connection settings dialogs now use the shared width scale:
    • md / max-w-[480px] for standard variants
    • lg / max-w-[640px] for SMS variants with brand/campaign content
    • reconnect auth modal uses sm / max-w-[400px]
  • Dialog form controls and card-like setting rows use rounded-md consistently across inputs, selects, textareas, and inline utility surfaces.
  • The helper sentence Set the Workspace and Knowledge base for this profile. was removed from this dialog.
  • For Social comments, Review platforms, and FB Messenger, the dialog includes a Reconnect profile action shown above the Workspace field.
  • Reconnect profile now opens an in-place auth dialog (skeleton external login simulation) with platform logo + title.
  • Clicking Log in in that auth dialog closes it and shows reconnect success feedback (toast).
  • Any dialog variant that includes an Active control places it as the last form row in the content area. The row is full width with the label left-aligned and the switch right-aligned.
  • The row three-dots dropdown (Edit / Delete) now closes correctly before launching follow-up UI (no persistent open menu under dialogs).