feat(onboarding): the hosted checklist closes with Connect to Claude (#1971)

Founder call 2026-08-27: the strategic split is Claude-first onboarding
for brand-new businesses (no migration friction) and hosted onboarding
for prior-system users, whose closing CTA now hands them to Claude with
everything already connected: the MCP onboarding skill then opens with
reconciliation findings and the Att göra-list instead of setup steps
(shipped in #1967).

The final checklist step 'Bygg din bokföringsassistent' becomes 'Anslut
till Claude': the button opens claude.ai's Add-custom-connector dialog
prefilled (connectorName from the brand, connectorUrl built from the
page origin so self-hosted and white-label domains link to themselves).
The in-app assistant calibration stays reachable from the assistant
page. sv + en strings added.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-27 11:35:47 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent 5e9cd6f761
commit 23776337c8
3 changed files with 25 additions and 10 deletions
+17 -8
View File
@@ -18,6 +18,7 @@ import { ENABLED_EXTENSION_IDS } from '@/lib/extensions/_generated/enabled-exten
import { useCapability } from '@/contexts/CompanyContext'
import { CAPABILITY } from '@/lib/entitlements/keys'
import type { InitialSetupPath, InitialSetupState } from '@/types'
import { useBranding } from '@/lib/branding/brand-context'
interface NewUserChecklistProps {
initialState: InitialSetupState
@@ -78,6 +79,7 @@ export default function NewUserChecklist({
sieSweep = null,
}: NewUserChecklistProps) {
const t = useTranslations('initial_setup')
const { appName } = useBranding()
const router = useRouter()
const showError = useErrorToast()
const { formatDateLong } = useFormat()
@@ -217,9 +219,17 @@ export default function NewUserChecklist({
captureSetup('onboarding_setup_step_started', { step: 'receipts' })
router.push(hasAi ? '/e/general/invoice-inbox' : '/settings/billing')
}
const goAssistant = () => {
captureSetup('onboarding_setup_step_started', { step: 'assistant' })
router.push(hasAi ? '/onboarding/agent' : '/settings/billing')
// Founder call 2026-08-27: the closing CTA is "Anslut till Claude", not the
// in-app assistant calibration (still reachable from the assistant page).
// A user who finishes the hosted onboarding lands in Claude with everything
// already connected, where the MCP onboarding skill opens with findings and
// the Att göra-list instead of setup. The connector URL is built from the
// page origin so self-hosted and white-label domains link to themselves.
const goClaude = () => {
captureSetup('onboarding_setup_step_started', { step: 'claude' })
const serverUrl = `${window.location.origin}/api/extensions/ext/mcp-server/mcp?tool_namespace=accounted`
const link = `https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=${encodeURIComponent(appName)}&connectorUrl=${encodeURIComponent(serverUrl)}`
window.open(link, '_blank', 'noopener')
}
const dismiss = () =>
void persist({ dismissed: true }, 'dismiss').then((updated) => {
@@ -387,16 +397,15 @@ export default function NewUserChecklist({
number={numbers.assistant}
done={step5Done}
active={activeStep === 5}
title={t('step_assistant_title')}
badge={t('step_assistant_beta')}
title={t('step_claude_title')}
last
action={(variant) => (
<Button size="sm" variant={variant} onClick={goAssistant}>
{t('step_assistant_action')}
<Button size="sm" variant={variant} onClick={goClaude}>
{t('step_claude_action')}
</Button>
)}
>
{t('step_assistant_description')}
{t('step_claude_description')}
</Step>
</ol>
</section>
+4 -1
View File
@@ -1518,7 +1518,10 @@
"step_receipts_description": "Photo the receipt or forward the email to your inbox address, and the document is read and waiting for you.",
"step_receipts_action": "Open the inbox",
"step_receipts_channels": "Email · WhatsApp · upload",
"step_receipts_channels_no_wa": "Email · upload"
"step_receipts_channels_no_wa": "Email · upload",
"step_claude_title": "Connect to Claude",
"step_claude_description": "Do your bookkeeping from the chat: drop receipts and SIE files, reconcile the tax account and ask about your numbers. Everything is already connected.",
"step_claude_action": "Connect to Claude"
},
"tax_assessment_notices": {
"title": "Final tax notices and remaining tax",
+4 -1
View File
@@ -1518,7 +1518,10 @@
"step_receipts_description": "Fota kvittot eller vidarebefordra mejlet till er inkorgsadress, så tolkas underlaget och väntar på dig.",
"step_receipts_action": "Öppna inkorgen",
"step_receipts_channels": "Mejl · WhatsApp · uppladdning",
"step_receipts_channels_no_wa": "Mejl · uppladdning"
"step_receipts_channels_no_wa": "Mejl · uppladdning",
"step_claude_title": "Anslut till Claude",
"step_claude_description": "Bokför via chatten: släpp kvitton och SIE-filer, stäm av skattekontot och ställ frågor om siffrorna. Allt är redan kopplat.",
"step_claude_action": "Anslut till Claude"
},
"tax_assessment_notices": {
"title": "Slutskattebesked och kvarskatt",