add-channel-setup-guide
GitHub为新增聊天渠道生成前端设置引导指南,实现步骤导航、凭据保存及连接状态轮询。
Trigger Scenarios
Install
npx skills add novuhq/novu --skill add-channel-setup-guide -g -y
SKILL.md
Frontmatter
{
"name": "add-channel-setup-guide",
"description": "Add a new chat channel's layer-1 setup guide — the in-dashboard <Channel>SetupGuide that walks a developer through connecting the channel itself (create app\/bot → save credentials → install\/verify → send first message) with live connection detection — in apps\/dashboard, following the existing Slack, MS Teams, and Telegram guides. Use when a new agent channel needs its numbered setup stepper, credential drawer wiring, and connectedAt polling under components\/agents."
}
Add a Channel's Setup Guide (Layer 1)
Layer 1 = connecting the channel itself: the numbered stepper a developer follows to
create the provider app/bot, save its credentials in Novu, install/verify, and send a first
message — with a live "Listening… / Connected" indicator. ResolveAgentIntegrationGuide
renders this <Channel>SetupGuide as the setup view until the integration is connected,
then swaps to the connected/"what's next" view (separate add-channel-whats-next-onboarding skill).
Files live in apps/dashboard/src/components/agents/. Siblings: slack-setup-guide.tsx (quick/manual
modes + manifest), teams-setup-guide.tsx, telegram-setup-guide.tsx (simplest), whatsapp-setup-guide.tsx.
How it works
<Channel>SetupGuide
├─ useFetchIntegrations() → find integration by _id + providerId
├─ SetupStepperRail
│ └─ SetupStep × N → create app · save creds · install/verify
│ └─ SetupButton / IntegrationCredentialsSidebar trigger
├─ ListeningStatus → polls listAgentIntegrations every 1s;
│ fires onConnected + confetti when connectedAt is set
└─ IntegrationCredentialsSidebar → generic credential save (useUpdateIntegration)
Connection is detected, not asserted. A channel is "connected" only when the backend sets
connectedAt on the integration link (on the first real inbound message). Saving credentials or
finishing OAuth/install does not mean connected — keep those as separate local states.
Building blocks
All from setup-guide-primitives.tsx and setup-guide-step-utils.ts:
| Symbol | Role |
|---|---|
SetupStepperRail |
Vertical numbered rail wrapping the steps column |
SetupStep |
One step: index, status, title, description, rightContent?, extraContent?, fullWidthContent?, headerSlot?, dimmed?, sectionLabel?, inlineSectionLabel? |
SetupButton |
Secondary outline action; href opens a new tab, else onClick; supports leadingIcon, disabled |
SetupModeToggle + SetupMode ('quick' | 'manual') |
Optional dual-path setup (Slack) |
IntegrationCredentialsSidebar |
Drawer that saves provider credentials via the generic integration form; onSaveSuccess, agentOnboarding |
ListeningStatus |
Polls listAgentIntegrations; fires onConnected + confetti on connectedAt |
deriveStepStatus(i, firstIncomplete) |
→ 'completed' | 'current' | 'upcoming' |
hasIntegrationCredentials(credentials) |
True once any string credential is saved |
Step 0 — Prerequisites
ChatProviderIdEnum.<Channel>exists in@novu/shared, and the provider exists inpackages/providers(brand-new providers are ask-first).- The integration can be created/selected (the "add provider" flow passes you an
integrationId).
File checklist
Copy the closest sibling, then rename. Full template: see reference.md.
- CREATE
apps/dashboard/src/components/agents/<channel>-setup-guide.tsx— export<Channel>SetupGuide - EDIT
agent-integration-guides/resolve-agent-integration-guide.tsx— in the setupswitch, render<Channel>SetupGuide ... embedded />and setsetupDisplayName(theadd-channel-whats-next-onboardingskill covers the rest of this resolver) - (optional) Add a provider-specific server action in
@/api/agentsor@/api/integrationsonly if the channel needs webhook registration / quick-setup / subscriber-link beyond a plain credential save
Component contract
Props: { agent: AgentResponse; integrationId: string; stepOffset?: number; onStepsCompleted?: () => void; embedded?: boolean }
(stepOffset defaults to 1; Overview mounts the guide at a higher base, the Integrations detail page at 1).
State machine:
- Resolve
selectedIntegrationfromuseFetchIntegrations()by_id === integrationId && providerId === ChatProviderIdEnum.<Channel>. - Track progress:
hasIntegrationCredentials(...)‖ a localcredentialsSavedLocally, plus any install/connected flags. Reset all of it inuseEffect([integrationId]). - Derive
const base = stepOffset→ computefirstIncompleteStep→deriveStepStatus(stepIndex, firstIncompleteStep)perSetupStep. - Render the steps in
SetupStepperRail, thenListeningStatus(in apl-8wrapper), thenIntegrationCredentialsSidebar. ListeningStatus.onConnected→ mark connected and callonStepsCompleted?.().- Provide both an
embeddedreturn (no Overview chrome — used by the resolver) and the standalone return.
Typical 3-step recipe
- Create the app/bot —
SetupButton href=the provider console. Optional: a manifest (CodeBlock, escape injected values) or a quick-setup input that calls a server action. - Save credentials in Novu —
SetupButton onClick={() => setIsCredentialsSidebarOpen(true)}; the sidebar'sonSaveSuccessflipscredentialsSavedLocally(and may trigger a provider action like webhook registration). - Install / verify + send first message — a provider connect button or copyable instructions;
ListeningStatuswatches forconnectedAt.
Conventions & gotchas
- Keep installed/credentialed and connected as distinct states — only
connectedAtadvances the final step (see the Slack guide's comments). - Server state through TanStack Query; after a mutation, invalidate
getAgentIntegrationsQueryKey(currentEnvironment?._id, agent.identifier). - Escape any value injected into a manifest/snippet (e.g. Slack YAML double-quoted strings).
- Reset local state when
integrationIdchanges so switching integrations doesn't leak progress. - Novu/dashboard conventions:
type(notinterface) on the frontend, named exports, blank line before everyreturn, no nested ternaries, animations frommotion/react. Don't build/start the dashboard (port 4201) — check types via diagnostics.
Build & verify
- Don't start the dashboard — check types via Cursor diagnostics.
- From the agent Integrations tab, add/open a
<Channel>integration: confirm steps advance as credentials save, the credential drawer opens/saves, and "Listening…" flips to "Connected" with confetti once a real message lands.
Version History
- 56a8a16 Current 2026-08-29 05:10


