Account – Channels
- Path:
/account/channels - Parent:
README.md - Children:
channels-social-channels.mdchannels-review-platforms.mdchannels-facebook-messenger.mdchannels-web-chat.mdchannels-whatsapp.mdchannels-sms.md
- Status: Implemented (v1): global channels hub with shared filters, stable tab totals, and per-family table sections.
Historical design reference
Section titled “Historical design reference”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.
Purpose (business goal)
Section titled “Purpose (business goal)”Centralize channel configuration: discover available connectors, connect/disconnect channels, and monitor channel health.
Get Started integration:
- Channel types selected during
Get startedStep 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).
- by completing
User roles & permissions
Section titled “User roles & permissions”- Workspace Admin
- Permissions:
channels.view,channels.connect,channels.disconnect(TBD)
Reference: Roles & Permissions Model
Layout structure
Section titled “Layout structure”- Top bar breadcrumb:
Account > ChannelsChannelsis a dropdown; clicking it opens the Account submenu for quick navigation within Account.
- Merged top section:
Channelstitle + 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
addConnectioncalls from this wizard passaddedVia: "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 label Channel type key 1 Social comments social-comments2 Review platforms review-platforms3 FB Messenger facebook-messenger4 Web chat web-chat5 WhatsApp whatsapp6 SMS sms -
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 inlocalStorageunder the keychannels-active-tabso the user’s last-selected tab is restored on next visit. If no stored value is found, fall back tosocial-comments. -
The tab list is rendered using the shadcn
Tabs/TabsList/TabsTrigger/TabsContentprimitives (already in the project). EachTabsContentwraps 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-lgoverride on the page; base isrounded-md), internal paddingp-1, no border. The list is content-width (not full-width) — it wraps only the tab triggers. Do not addw-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 defaultdata-[state=active]:bg-background data-[state=active]:shadow-sm. Do not override tobg-[#e5e5e5]or any dark-gray value.- No underline, no
border-b, noborder-transparent, noborder border-borderclasses on the list or any trigger. - Sizing rule: Use
px-3 py-1.5 text-smon triggers andp-1on 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
Agentcolumn 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=agentswhen workspace context is resolvable. - The column is not shown for
social-commentsorreview-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).
- Each connector is presented as a
Components used
Section titled “Components used”- 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 aplatformandchannelType. 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. Acceptsplatform: stringandchannelType: stringprops.
Add channel wizard
Section titled “Add channel wizard”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.tsxadd-review-profile-dialog.tsxadd-fb-messenger-dialog.tsx
Modal shell
Section titled “Modal shell”- 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
- a standard dialog header consistent with other dialogs such as
Step structure
Section titled “Step structure”| # | Step | Purpose | Skip rule |
|---|---|---|---|
| 1 | Channel | Choose the channel type: Social comments, Review platforms, FB Messenger, Web chat, WhatsApp, SMS | Never skipped |
| 2 | Platform | Choose the concrete platform for multi-platform families | Skip for single-platform families |
| 3 | Connect | Complete the in-wizard connect/setup action where needed | Skipped for Social comments and Review platforms after successful platform auth |
| 3.5 | Greetings | Configure FB Messenger welcome message and ice breakers | FB Messenger only; always shown after Connect for that family |
| 4 | Customization | Configure web chat widget settings and appearance | Included only for Web chat |
| 5 | Destination | Choose 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 rules
Section titled “Step rules”- 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
Continuebutton. - 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 onChannelConnection.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 theChannelConnectionasmessengerWelcomeMessageandmessengerIceBreakers). - Step icon:
waving_hand. Step label: “Greetings”. Step title: “Set up greetings”.
- Shown only for
- 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.
Footer behavior
Section titled “Footer behavior”- First visible step: show
CancelandNext - Middle steps: show
Back,Cancel, andNext - Final step (
Destination): showBack,Cancel, andAdd Nextstays disabled until the current step is valid.Cancelalways 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.
Entry-point behavior
Section titled “Entry-point behavior”- 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).
Data/commit rules
Section titled “Data/commit rules”- Every
addConnection(...)call from the wizard must passaddedVia: "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 genericProfile N. - If the selected KB is incomplete, the existing warning toast behavior still applies.
Implementation targets
Section titled “Implementation targets”- 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.
Channel tabs — implementation spec
Section titled “Channel tabs — implementation spec”One-line summary for the implementer: Use the Shadcn default pill style —
TabsListgets only layout overrides (h-auto rounded-lg p-1; now-full, the list is content-width); eachTabsTriggergets onlyrounded-md px-3 py-1.5 text-sm font-medium— the base@/components/ui/tabsalready suppliesbg-mutedfor the list anddata-[state=active]:bg-background data-[state=active]:shadow-smfor the active trigger; do not addborder border-border,bg-[#f5f5f5],shadow-smon the list, ordata-[state=active]:bg-[#e5e5e5]on the trigger.
Where to add the tab UI
Section titled “Where to add the tab UI”- 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,TabsContentprimitives (imported from@/components/ui/tabs).
Tab ids and order
Section titled “Tab ids and order”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"];State management
Section titled “State management”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);}, []);useStateinitializer reads fromlocalStorageon first render (client-only; safe because the page is"use client").- On tab change, persist to
localStorage.
JSX structure
Section titled “JSX structure”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.
TabsContentwithclassName="mt-0"removes the default top margin.- The
TabsListis a self-contained pill container — no wrappingborder-brow needed. The base@/components/ui/tabsalready providesbg-mutedon the list anddata-[state=active]:bg-background data-[state=active]:shadow-smon 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 addw-fullorjustify-start; it shrinks to fit the triggers and is left-aligned by default within itspx-6 py-3wrapper. - Do not add
border border-border,bg-[#f5f5f5], orshadow-smon the list. Do not adddata-[state=active]:bg-[#e5e5e5]on the trigger — the default white (bg-background) is correct. - Do not use
border-b,border-transparent,rounded-none, orbg-transparenton the list or triggers.
What does NOT change
Section titled “What does NOT change”- 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.
Table sorting
Section titled “Table sorting”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:
| Table | Sortable columns |
|---|---|
| Social comments | Profile, Platform, Workspace, Knowledge base |
| Review platforms | Profile, Platform, Workspace, Knowledge base |
| FB Messenger | Profile, Workspace, Knowledge base |
| Web chat | Widget title, Workspace, Knowledge base |
| Phone number, Workspace, Knowledge base | |
| SMS | Phone number, Workspace, Knowledge base |
States
Section titled “States”- 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.
Ownership summary
Section titled “Ownership summary”| Channel family | KB set on | KB editable in table | Agent required |
|---|---|---|---|
| Social comments | Connection | Yes — inline selector | No |
| Review platforms | Connection | Yes — inline selector | No |
| FB Messenger | Agent | No — read-only, derived from agent | Yes |
| Web chat | Agent | No — read-only, derived from agent | Yes |
| Agent | No — read-only, derived from agent | Yes | |
| SMS | Agent | No — read-only, derived from agent | Yes |
Business logic (high-level)
Section titled “Business logic (high-level)”- 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
knowledgeBaseIdis 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 haveknowledgeBaseId; workspace is derived from the KB’sworkspaceId. - 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 startedmain-menu entry remains available so the user can resume setup (see Get Started – Stepper (3 steps)).
Domain refs:
Social comments — add profile flow
Section titled “Social comments — add profile flow”Trigger
Section titled “Trigger”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 |
|---|---|
| 1 | |
| 2 | |
| 3 | |
| 4 | Threads |
The list is defined as SOCIAL_PLATFORMS and reused by the wizard. Clicking a platform selects it and advances to the Connect step.
Step 2 — Connect step inside the wizard
Section titled “Step 2 — Connect step inside the wizard”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.
State wiring
Section titled “State wiring”- The wizard open state is page-level.
SocialCommentsSectionno longer owns its own add-profile dialog state.
Platform constant
Section titled “Platform constant”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
idvalues use PascalCase (e.g."Facebook", not"facebook"). This is the canonical form stored inChannelConnection.platform. All filtering, matching, andChannelIconlookups 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
onAddhandler must calladdConnection(...)withaddedVia: "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-widthTabsList, 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
Selectbound to localpendingSelectedLabelstate.addConnectionis 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). addConnectionmust return the new connectionid(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.
Required behaviour
Section titled “Required behaviour”-
If the user saves (or confirms) a connection with a knowledge base whose status is incomplete (e.g.
status === "incomplete"), the platform must:- 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.”
- 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 profileaction above the Workspace field.- Clicking
Reconnect profileopens an in-place auth dialog (skeleton external login simulation) from the Connection settings dialog. - Clicking
Log inin that auth dialog closes the auth modal and shows a reconnect-success toast. Reconnect profileis not shown for Web chat, WhatsApp, or SMS.
- Clicking
-
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. WhenonSaveis invoked, the parent (or the dialog) should check the chosen KB’s status; if incomplete, calltoast.warning(...)(e.g. after callingsetConnectionKnowledgeBaseor in the same handler). The dialog receivesknowledgeBaseOptionsthat include KB metadata (id, name, workspaceId); the options must also expose status (or the Channels page passes a lookup/map ofkbId → 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 onChannelConnection.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).
Three-dots dropdown menu
Section titled “Three-dots dropdown menu”| Property | Value |
|---|---|
| Trigger | MoreBtn — the existing more_horiz icon button in the last cell of each row |
| Component | shadcn DropdownMenu / DropdownMenuTrigger / DropdownMenuContent / DropdownMenuItem (add dropdown-menu to the project via npx shadcn@latest add dropdown-menu if not present) |
| Alignment | align="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 style | Destructive 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 behaviour | Clicking “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).
Delete confirmation dialog
Section titled “Delete confirmation dialog”Because deletion is destructive and irreversible, the user must confirm before the app calls removeConnection(id).
| Property | Value |
|---|---|
| Component | A 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 file | src/app/account/channels/_components/delete-connection-dialog.tsx |
| Trigger | Opening is driven by `pendingDeleteId: string |
| Element | Copy |
|---|---|
| Title | Remove connection? |
| Body | This will permanently remove the connection. This action cannot be undone. |
| Cancel button | Cancel (secondary / outline variant) |
| Confirm button | Remove (destructive variant — variant="destructive" on the shadcn Button) |
Behaviour
Section titled “Behaviour”- User clicks Cancel → dialog closes,
pendingDeleteIdis set tonull. No side-effect. - User clicks Remove →
removeConnection(pendingDeleteId)is called, thenpendingDeleteIdis set tonulland the dialog closes. The row disappears from the table immediately (optimistic, driven by context state). - Clicking the backdrop (overlay) → same as Cancel.
Props interface
Section titled “Props interface”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.
State wiring (per section component)
Section titled “State wiring (per section component)”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 removedpendingDeleteId is local state (useState<string | null>(null)) owned by each section component (e.g. SocialCommentsSection). It is not lifted to the page.
Analytics events
Section titled “Analytics events”channel.connection.delete_initiated— fired when the user clicks “Delete” in the dropdown (before confirmation).channel.connection.deleted— fired afterremoveConnectionis called (confirmed delete).
API dependencies
Section titled “API dependencies”GET /channels/connectorsGET /workspaces/{id}/channelsPOST /channels/{type}/connectPOST /channels/{type}/disconnect
Enterprise constraints
Section titled “Enterprise constraints”- Credentials must be masked; actions audited.
Edge cases
Section titled “Edge cases”- 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).
Security & compliance considerations
Section titled “Security & compliance considerations”- Strict permission gating for connect/disconnect
- Prevent secret exposure
Reference: Security & Compliance
Analytics events (if applicable)
Section titled “Analytics events (if applicable)”account.channels.viewedchannel.connectedchannel.disconnectedchannel.connection.delete_initiated— user opens the delete confirmation dialogchannel.connection.deleted— user confirms and the connection is removed
Reference: Analytics Events (MVP)
Web Chat — Widget visibility settings
Section titled “Web Chat — Widget visibility settings”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:
| Field | Type | Notes |
|---|---|---|
| Auto-show widget | Toggle (Switch) | Enables automatic widget display without user interaction. Default: off. |
| Delay (seconds) | Number input | 0–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:
| Field | Type | Notes |
|---|---|---|
| Auto-show widget | Toggle (Switch) | Same as above. |
| Delay (seconds) | Number input | Same as above. |
Data model
Section titled “Data model”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 }Agent modal — Visibility tab removed
Section titled “Agent modal — Visibility tab removed”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.
FB Messenger — Greetings persistence
Section titled “FB Messenger — Greetings persistence”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.
Data model
Section titled “Data model”interface ChannelConnection { // ... existing fields ... messengerWelcomeMessage?: string; // facebook-messenger only messengerIceBreakers?: string[]; // facebook-messenger only; max 5 items}Storage behavior
Section titled “Storage behavior”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.
Where greetings are set
Section titled “Where greetings are set”- Add Channel wizard — Greetings step (FB Messenger only): user sets welcome message and ice breakers before the Destination step. On wizard completion,
setConnectionMessengerGreetingsis called with the new connection id. - Connection settings dialog — not yet surfaced for editing existing connections (future iteration).
Neo Handoff (March 2026)
Section titled “Neo Handoff (March 2026)”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)
- header with top separator (
- Connection settings dialogs now use the shared width scale:
md/max-w-[480px]for standard variantslg/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-mdconsistently 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 profileaction shown above the Workspace field. Reconnect profilenow opens an in-place auth dialog (skeleton external login simulation) with platform logo + title.- Clicking
Log inin 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).