Skip to content

Guided Setup

Overview

Guided Setup is Upvendo's interactive onboarding flow that walks new merchants through the essential configuration steps needed to get their business operational. It is presented as a checklist panel inside the Emily assistant (not a standalone page), reachable from any backoffice page. The merchant first picks their POS provider, and the panel then shows an ordered checklist of setup steps (set up payment profile, set up billing profile, set up store branding, create location, connect the POS, sync the menu, and so on). Each step links to the backoffice page where the action is performed.

The current onboarding flow is powered by Upvendo's AI assistant Emily. The step list is generated by Emily during a "discovery" conversation and then served from Emily's knowledge base; there is no built-in per-provider list in the front end, so a missing or failed step lookup produces an empty checklist rather than a fallback. Completion is detected automatically: the backend inspects the merchant's actual data (does a payment profile exist? is a location created? is the POS connected and tested?) and reports which steps are done, so checkmarks appear without the merchant having to mark anything manually.

Note: an older, separate config-driven guided-setup system also exists in the codebase (service paths self-service / online-ordering / qr-code with categories and tasks). The frontend store module explicitly marks it deprecated and being migrated to Emily's onboarding state. The customer-facing onboarding flow described here is the Emily/POS-provider one.

Purpose

This page lets you follow a structured onboarding flow to configure your Upvendo business. You select your POS provider, then work through an ordered checklist that links you to each setup page and tracks which steps are already done.

Key Concepts

  • Onboarding checklist: The live checklist UI is src/components/emily/EmilySetupPanel.vue, rendered inside the Emily widget (src/components/emily/EmilyWidget.vue, lines 14 and 27). It opens on the emily:open-setup-panel window event, handled at EmilyWidget.vue lines 744-746 (listener registered at line 778). There is no page you can navigate to — the checklist only exists inside the Emily widget.
  • The old EmilyGuidedSetupDialog is dead code. It is imported and registered in src/App.vue (lines 12 and 23) but appears nowhere in App.vue's template, so it never renders — dead since backoffice 36e3a3745 (2025-12-19, "Replace EmilyGuidedSetupDialog with EmilySetupPanel"). The show_guided_setup_dialog store flag (setShowGuidedSetupDialog) is inert with it: three call sites still write it (src/layouts/components/NavBarGuidedSetup.vue line 16, src/components/dialogs/guided-setup/GuidedSetupVideoContentDialog.vue line 128, src/layouts/components/DefaultLayoutWithVerticalNav.vue line 440) but no template reads it, which also means the boot-time auto-open at DefaultLayoutWithVerticalNav.vue lines 429-443 no longer opens anything.
  • Where it opens from: the unlabelled clipboard icon (tabler-clipboard-list) in the navbar (src/components/navbar/NavBarGuidedSetup.vue, rendered at src/layouts/components/DefaultLayoutWithVerticalNav.vue line 604) and the Guided Setup entry in the account menu (src/components/navbar/UserProfile.vue lines 85-90 and 125-127). Both dispatch the same emily:open-setup-panel event. On a brand-new account Emily also opens itself — see "First run" below.
  • POS provider selection: The provider tiles the merchant actually sees come from the backend, not from a hardcoded frontend list. GET /back-office/merchant/reseller-providers (ResellerService::getMerchantResellerProviders) filters config/pos-providers.php by the provider's active flag, its test_only flag, and either the merchant's country (no reseller) or the reseller's assigned provider catalog. In production a Belgian merchant with no reseller sees Hendrickx, Vanhoutte and MplusKassa; Shopcaisse, Lightspeed K-Series and the first-party Upvendo POS are test_only (still shown to merchants flagged is_test), and Square is limited to US / CA / GB / AU / JP / IE / FR / ES. The upvendo entry sets first_party => true (which bypasses the country and reseller-catalog filters — the test_only check runs first) and is 'active' => true, 'test_only' => true at config/pos-providers.php:51-52, so Upvendo POS appears only for test merchants until test_only is dropped. Selecting a provider saves it to Emily's onboarding state with phase: 'discovery' and opens the Emily chat. (Verified: src/components/emily/EmilyWidget.vue line 136; src/store/modules/app.ts lines 722-728; app/Services/BackOffice/ResellerService.php lines 666-689.)
  • POS_PROVIDERS in types.ts is not the live list. It drives only POSSelectionGrid.vue, which lives inside the unrendered EmilyGuidedSetupDialog. Its PRODUCTION_POS_PROVIDERS array does list Upvendo POS, but that is legacy and reflects nothing a merchant sees. The live selection UI is Emily's providerOptions cards in EmilyWidget.vue.
  • Setup step: A single onboarding task with title, an optional id, and an optional route (the backoffice page it links to). Some steps carry a channel (the POS channel to connect) or an action (currently only open_location_selector). Steps are typed by the SetupStep interface in types.ts.
  • Base steps vs channel steps (legacy): BASE_SETUP_STEPS (per POS provider) and the two shared channel checklists KIOSK_CHANNEL_STEPS / ONLINE_ORDERING_CHANNEL_STEPS live in types.ts, but only the unrendered dialog and ChannelSetupTabs.vue read them. They are not what a merchant sees — see "Legacy step definitions" below.
  • Where the live steps come from: the setup_steps already in the Vuex store (written by the Emily chat during discovery) when the store also carries a pos_provider; otherwise getSetupSteps(pos_provider, channel) against Emily's knowledge base. There is no per-provider frontend fallback: an unresolved provider, or a failed/empty knowledge-base response, produces an empty checklist. Some step routes are corrected at runtime by getStepRouteOverride (e.g. "Connect Hendrickx" → /hendrickx, "Sync Menu" → the current POS page). (Verified: EmilySetupPanel.vue lines 374-398 and 433-441.)
  • Automatic completion detection: The backend endpoint GET /api/back-office/setup-status returns boolean flags about the merchant's real data. The frontend (setupStepMappings.ts) maps those flags to completed step IDs and merges them with any manually tracked IDs from Emily's state. A step shows a checkmark when its ID is in the merged completed list.
  • Completion is an exact ID match, normalized on read via canonicalizeStepId(). A step is ticked by completedStepIds.value.includes(canonicalizeStepId(step.id)) (EmilySetupPanel.vue). Historical onboarding docs used retired spellings (setup_menu_kiosk, setup_menu_online, configure_kiosk, pos_setup). canonicalizeStepId() in src/utils/emily/setupStepIds.ts normalizes those retired spellings to their canonical forms (menu_for_kiosk, menu_for_online_ordering, kiosk_device, connect_pos), and setupStepMappings.ts emits only single canonical step IDs. Step gating is governed strictly by the prerequisite dependency graph in setupStepLock.ts, not by list index or required flags. (Verified: upvendo-backoffice/src/utils/emily/setupStepLock.ts and setupStepIds.ts.)

Route

  • Access: A panel inside the Emily widget — there is no /guided-setup page route, and none exists in the backoffice's file-based pages or its redirects array. Opened by the navbar clipboard icon, the Guided Setup entry in the account menu, or programmatically by dispatching the emily:open-setup-panel window event. (Verified: no src/pages/guided-setup* entry and no /guided-setup path in src/plugins/1.router/additional-routes.ts on origin/production. /guided-setup-videos is a separate global-admin page for managing tutorial videos, not this feature.)
  • Checklist component: src/components/emily/EmilySetupPanel.vue, rendered by src/components/emily/EmilyWidget.vue at lines 14 and 27.
  • Legacy, not rendered: src/components/dialogs/EmilyGuidedSetupDialog.vue is imported and registered in src/App.vue (lines 12 and 23) but never appears in its template. The still older src/components/dialogs/GuidedSetupDialog.vue is reachable only through Emily's modal registry (src/utils/emilyModalRegistry.ts line 139, key guided-setup). Neither is what a merchant sees.
  • Legacy sub-components (imported only by EmilyGuidedSetupDialog.vue lines 8-11, therefore also unrendered): src/components/dialogs/guided-setup/POSSelectionGrid.vue, SetupProgressList.vue, ChannelSetupTabs.vue, DisconnectRequiredNotice.vue. GuidedSetupVideoContentDialog.vue is separate.
  • What the live panel imports: EmilySetupPanel.vue line 117 takes only the types SetupStep and OnboardingState from guided-setup/types.ts, plus setupStepMappings, setupStepLock, posSetupTitle and emilyApi.
  • Step definitions (legacy): src/components/dialogs/guided-setup/types.ts (SetupStep, POS_PROVIDERS, BASE_SETUP_STEPS, KIOSK_CHANNEL_STEPS, ONLINE_ORDERING_CHANNEL_STEPS) — consumed only by the unrendered dialog and ChannelSetupTabs.vue.
  • Step ↔ status mapping: src/utils/emily/setupStepMappings.ts
  • Onboarding-state API client: src/utils/api/emilyApi.ts (getOnboardingState, saveOnboardingState, deleteOnboardingState, getSetupSteps)
  • Store module: src/store/modules/guidedSetup.ts
  • Backend status endpoint: GET /api/back-office/setup-statusapp/Http/Controllers/Api/BackOffice/SetupStatusController.php (logic in app/Services/SetupStatusService.php)
  • Backend video endpoints: app/Http/Controllers/Api/BackOffice/GuidedSetupManagementController.php (logic in app/Services/BackOffice/Settings/GuidedSetupVideoService.php)
  • Task/video catalog config: config/guided-setup.php

The legacy backend artifacts the previous version of this page listed (GuidedSetupController, GuidedSetupOrchestrator, GuidedSetupService, GuidedSetupProgress model, GuidedSetupProgressRepository, GuidedSetupTaskListener, app/Events/GuidedSetup/*, UpdateGuidedSetupProgress command) do not exist in the backend and have been removed from this doc.

Legacy step definitions (BASE_SETUP_STEPS) — not what merchants see

These lists are legacy. BASE_SETUP_STEPS, KIOSK_CHANNEL_STEPS and ONLINE_ORDERING_CHANNEL_STEPS in guided-setup/types.ts are reachable only from EmilyGuidedSetupDialog.vue and ChannelSetupTabs.vue, both of which sit behind the dialog that App.vue registers but never renders. The live panel has no per-provider frontend fallback — its steps come from the store or from Emily's knowledge base (see Business Rules). The canonical checklists a merchant actually receives are the setup_steps served from merchant/onboarding/*.md in this knowledge base. The lists below are kept only as a record of the historical ordering. (Verified: grep BASE_SETUP_STEPS src/ matches only guided-setup/types.ts and EmilyGuidedSetupDialog.vue; EmilySetupPanel.vue line 117 imports types only.)

These lists record historical ordering only. The setup_steps fences in merchant/onboarding/*.md are canonical, and they no longer match the order below: payment and billing moved to the end flagged optional_for_go_live, and the menu steps moved up directly after the connect.

Hendrickx / Vanhoutte / Shopcaisse / Lightspeed K-Series (Lightspeed omits "Select Location from Topbar" and "Sync Menu"):

  1. Set up Store Branding — /settings/brand
  2. Create Location — /settings/locations
  3. Select Location from Topbar — action: open_location_selector
  4. Connect <POS> — /hendrickx / /vanhoutte / /shopcaisse / /lightspeed
  5. Sync Menu — the current POS page
  6. Build Menu for Kiosk / Build Menu for Online Ordering — /menus/menu-builder
  7. Channel configuration (in-house / device / kiosk, or online settings / online ordering)
  8. Set up Payment Profile — /settings/payments (optional_for_go_live)
  9. Set up Billing Profile — /settings/billing (optional_for_go_live)
  10. Test steps (optional_for_go_live)

Square (POS imports locations, so it has a shorter list):

  1. Set up Store Branding — /settings/brand
  2. Connect Square — /square
  3. Review Imported Locations — /settings/locations

MplusKassa (merchant-scoped, syncs locations):

  1. Set up Payment Profile — /settings/payments
  2. Set up Billing Profile — /settings/billing
  3. Set up Store Branding — /settings/brand
  4. Connect MplusKassa — /mpluskassa
  5. Sync Locations — /mpluskassa
  6. Complete Location Details — /settings/locations
  7. Sync Menu — /mpluskassa

Kiosk channel steps (KIOSK_CHANNEL_STEPS, shown after base steps):

  1. Build Menu for Kiosk — /menus/menu-builder
  2. Set up In-House Settings — /in-house/settings
  3. Create Device Profile — /device-management/profiles
  4. Set up Kiosk & Activate Payment — /device-management/devices
  5. Activate Kiosk & Test Order — (no route)

Online Ordering channel steps (ONLINE_ORDERING_CHANNEL_STEPS):

  1. Build Menu for Online Ordering — /menus/menu-builder
  2. Set up Online Settings — /online-settings
  3. Set up Online Ordering — /online/online-ordering
  4. Open Online Ordering URL & Test Order — /online/online-ordering

Actions

First run (a brand-new account)

Three things happen automatically for a merchant who has not started onboarding:

  1. Emily opens by itself and starts discovery. Once the onboarding state has loaded, if the merchant's onboarding phase is none, Emily opens once per session and auto-launches discovery — it does not need the persisted dock flag a returning user has. It only fires in merchant context, only when Emily is available, and is suppressed while the user is on a /settings/locations page, where the location co-pilot takes priority. (Verified: src/components/emily/EmilyWidget.vue lines 922-939; src/utils/emily/onboardingGating.ts.)
  2. /home shows a Welcome card. A regular merchant user with no location yet lands on a "Welcome … Let's get your restaurant set up" card with a Start setup with Emily button (which dispatches emily:start-onboarding) instead of being redirected to the first permission-accessible page. Global-admin and partner logins still go to their own dashboards, and the decision is made only after the location list has loaded, so a slow load is not misread as "no location". (Verified: src/pages/home/index.vue lines 10-21, 55-71 and 157-186.)
  3. The operational nav is visible but locked. Until the merchant has a location, every left-sidebar nav link and group stays on screen but is greyed out, non-navigable and marked with a tabler-lock icon. The top bar and Settings stay reachable, so the merchant can still create the location that unlocks everything. The code assumes a location exists until the location list resolves, so an existing merchant never flashes the locked state. (Verified: src/navigation/vertical/index.ts lines 259 and 321-328; src/@layouts/components/VerticalNavLink.vue lines 89-96.)

Select a POS provider

On first open (no POS connected, no provider saved), Emily asks which POS the merchant uses and offers the provider cards. Selecting a provider saves { pos_provider, phase: 'discovery', current_question_index: 0, answers: {}, setup_steps: [], completed_steps_ids: [] } to Emily's onboarding state and opens the Emily chat to begin discovery.

  • Saves via: POST {emily-endpoint}/onboarding-state/{merchantId} (saveOnboardingState)

View setup progress

When a POS provider is connected or saved, the panel loads the step list (from the store, otherwise from Emily's knowledge base) and overlays auto-detected completion. Each step renders with a number, checkmark, or lock; the overall progress bar reflects the completed/total ratio.

  • Fetches state via: GET {emily-endpoint}/onboarding-state/{merchantId} (getOnboardingState)
  • Fetches steps via: getSetupSteps(pos_provider, channel) against Emily's knowledge base
  • Fetches completion via: GET /api/back-office/setup-status?location_id={locationId} (fetchSetupStatus)

Click a step

Navigates to the step's route and closes the panel. Special cases: a step with action: 'open_location_selector' dispatches the guided-setup:open-location-selector window event instead of navigating; a POS-connection step whose channel is not yet connected opens the in-house channel connect dialog (pre-selecting that channel) first.

The "Continue to Channel Setup" tabs, the "Change POS" link and the disconnect-required notice belonged to the old EmilyGuidedSetupDialog, which no longer renders. EmilySetupPanel.vue contains none of them. To change POS provider today, go through Emily's chat or disconnect the integration from its own settings page.

Get the video for a page

When a step navigates to a backoffice page, the app fetches a contextual tutorial video for that route.

  • Endpoint: GET /api/back-office/guided-setup-management/video/url?url={pagePath}
  • Backend: GuidedSetupManagementController::getVideoByUrl. Returns video metadata, or an empty object (HTTP 200) when no video is configured for that URL.

Manage onboarding state (programmatic)

The store exposes helper actions used by the Emily widget and setup panel: fetchEmilyOnboardingState, completeEmilyOnboardingStep, and resetEmilyOnboardingState (which calls DELETE {emily-endpoint}/onboarding-state/{merchantId}).

Fields

FieldWhereTypeNotes
POS providerPOS selectionStringA provider key from GET /back-office/merchant/reseller-providers (for a Belgian merchant in production: hendrickx, vanhoutte, mpluskassa)
Step IDSetup status / step listStringe.g. payment_profile, billing_profile, branding_profile, create_location, connect_pos, lightspeed_order_profiles, sync_menu, complete_location
Location IDSetup status requestStringOptional query param scoping completion to a location
PhaseOnboarding stateStringnone / discovery / checklist / completed (and execution is accepted by the store)

Setup-status flags (backend response)

GET /api/back-office/setup-status returns success plus boolean/string flags including: has_payment_profile, has_billing_profile, has_branding, has_location, location_selected, any_incomplete_location, has_menu_items, has_menu_for_kiosk, has_menu_for_online_ordering, pos_connected, pos_provider, menu_synced, has_integration_test, has_pos_order_profiles, has_kiosk_test_order, kiosk_test_order_id, has_online_ordering_test_order, online_ordering_test_order_id, has_in_house_settings, has_online_settings, has_online_ordering_settings, has_device_profile, has_kiosk_device.

Business Rules

  • POS selection drives the flow. When no POS is connected and none is saved in Emily's state, Emily asks for the provider first. The offered list is whatever GET /back-office/merchant/reseller-providers returns for that merchant, filtered by active, test_only and country / reseller catalog — not a hardcoded frontend list. Upvendo POS is staged test_only, so in production it is offered only to merchants flagged is_test.
  • There is no per-provider frontend fallback. The panel uses the setup_steps already in the Vuex store (put there by the Emily chat) when the store also carries a pos_provider (EmilySetupPanel.vue line 375). Otherwise it resolves the provider from store > connected POS > Emily's onboarding state; if none resolves it renders an empty checklist without calling the knowledge base (lines 396-398). When a provider does resolve it fetches getSetupSteps(pos_provider, channel) from Emily's knowledge base, and a failed or empty response also yields an empty checklist (lines 434-441). BASE_SETUP_STEPS[posProvider] is not consulted anywhere in the rendered UI.
  • Completion is auto-detected, not stored as task records. A step is marked complete when its ID appears in the merged list of (a) backend-detected IDs from /setup-status and (b) any IDs already in Emily's onboarding state. There is no per-task progress collection.
  • The "connect POS" step requires a real, tested integration. In setupStepMappings.ts, connect_pos is only completed when both pos_connected and has_integration_test are true. The backend treats a POS as connected only when its integration is in a connected state or has stored credentials. (Verified: upvendo-backoffice/src/utils/emily/setupStepMappings.ts lines 67-72; upvendo-backend/app/Services/SetupStatusService.php lines 364-368 and 434-439.)
  • First-party Upvendo POS is the other exception. When pos_provider is upvendo the backend hard-codes pos_connected = true and has_integration_test = false — there is no ThirdPartyIntegration row at all — so connect_pos (and its retired alias pos_setup) complete on pos_connected alone. The provider is staged test_only (config/pos-providers.php:51-52): in production, only merchants flagged is_test can select it via POST /back-office/pos/select-provider; a live merchant gets a 403 from the test_only gate in FirstPartyPosProvisioningService::selectFirstPartyPos() (FirstPartyPosProvisioningService.php:70-77). The console seeders (pos:seed-demo / test-account) also call selectFirstPartyPos() directly. (Verified: setupStepMappings.ts lines 67-72; SetupStatusService.php lines 325-333; config/pos-providers.php lines 36-54; app/Http/Requests/BackOffice/Pos/SelectPosProviderRequest.php lines 28-37; app/Services/Pos/PosDemoSeederService.php line 254.)
  • has_integration_test means the integration has a last_successful_test timestamp. For Hendrickx, Vanhoutte, Square, MplusKassa, and Shopcaisse that timestamp is only written when a connection check against the provider succeeds — in practice, the merchant clicking Test Connection on the integration page. (Shopcaisse additionally records it when loading the integration-details view finds the connection live.) (Verified: app/Services/Common/AbstractKassanetService.php lines 2540-2546 for Hendrickx/Vanhoutte; SquareIntegrationService.php lines 198-221; MplusKassaIntegrationService.php lines 1596-1611; ShopCaisseIntegrationService.php lines 1560-1570, plus the details-view stamp at lines 955-967.)
  • Lightspeed K-Series is the exception — connect_pos self-completes on connect. The Lightspeed OAuth callback fetches the merchant's business from /o/op/data/businesses; because that is a live authenticated round-trip, a successful fetch stamps last_successful_test right there. The step therefore completes as soon as the merchant authorizes Upvendo, with no separate Test Connection click, on both the first connect and a re-auth (they run the same callback). If that businesses fetch fails, the stamp is skipped and any earlier genuine stamp is preserved. (Verified: app/Services/BackOffice/LightspeedKSeriesIntegrationService.php lines 336-354 and 414-421. Square's OAuth callback does not stamp it — SquareIntegrationService.php lines 434-445.)
  • Lightspeed K-Series adds a step: lightspeed_order_profiles ("Set up Order Profiles & Tax"). It auto-completes when pos_provider === 'lightspeed' and has_pos_order_profiles is true. The backend returns true only for Lightspeed K-Series, and only when a location mapping carries a non-empty settings.account_profiles — the map the merchant saves in the back-office Order-profiles dialog. Scoped to one location when the request carries location_id, otherwise any active mapping counts; false for every other provider and when no POS is connected. (Verified: app/Services/SetupStatusService.php lines 378 and 393-410; upvendo-backoffice/src/utils/emily/setupStepMappings.ts line 56.)
  • Step gating is by declared prerequisites, not list order. DEPENDS_ON in upvendo-backoffice/src/utils/emily/setupStepLock.ts declares what each step actually needs (e.g. connect_pos needs branding, a location and a selected location; test_kiosk needs kiosk_device). A step that merely sits later in the list than an incomplete one is not thereby blocked. Three rules make one graph serve every provider: (1) a prerequisite absent from a provider's checklist is transitively replaced by its own prerequisites, so Square — which has no sync_menu — resolves menu_for_kiosk back to connect_pos; (2) a completed step is never locked, which guards the case where a completion flag is stricter than the gate that actually let the merchant past it (has_branding needs is_completed = true, while the connect gate only needs a branding profile to exist); (3) a prerequisite flagged optional_for_go_live counts as satisfied, because the backend enforces a branding profile at connect only for Hendrickx, Vanhoutte, Shopcaisse and MplusKassa (ThirdPartyIntegrationHelper::checkRequiredProfiles) — Square and Upvendo flag branding optional for exactly that reason, and without rule 3 "Connect Square" would be locked behind a step Square never requires. payment_profile and billing_profile are nobody's prerequisite and gate nothing.
  • optional_for_go_live replaces the old required flag, and is labelling only. It surfaces the "complete before you go live" hint on payment_profile, billing_profile and lightspeed_order_profiles, and (via rule 3 above) stops a step the backend does not enforce from blocking one it does. It does not remove the step from the progress denominator. The retired required field is no longer read by the front end.
  • The billing step is omitted under reseller_collects. When the merchant's reseller uses the reseller_collects billing model the reseller invoices the merchant and Upvendo bills the reseller, so billing_profile is filtered out of the checklist entirely rather than shown as optional — a task that is never coming should not sit in the list or in the progress denominator. Under platform_collects, and for a merchant with no reseller, it stays. The signal is userData.billing_model, set at login by upvendo-backend AuthService from the merchant's reseller (null when there is no reseller). Note the back office's pre-existing isResellerManaged computed means platform_collects — the opposite case — so do not reuse that predicate.
  • Merchant-scoped providers add location-sync steps. For MplusKassa and Square, having a location adds sync_locations; if no location is incomplete, complete_location is also added.
  • Test orders require a completed order on that channel. has_kiosk_test_order / has_online_ordering_test_order are true only when a Complete transaction exists for that channel at the selected location.
  • The legacy config system is deprecated. The store module header marks the old /back-office/guided-setup/* flow deprecated in favor of Emily's onboarding state; treat the Emily/POS flow as authoritative.

Customer Impact

  • Kiosk: After the base steps, the Kiosk channel checklist guides you through building a kiosk menu, in-house settings, a device profile, activating the kiosk with payment, and placing a test order.
  • Online Ordering: The Online Ordering channel checklist covers building an online-ordering menu, online settings, configuring online ordering, and opening the online-ordering URL to place a test order.
  • POS connection: A central step is connecting your POS provider (e.g. Hendrickx, Vanhoutte, Square, MplusKassa, Shopcaisse, Lightspeed K-Series) and syncing your menu.
  • Time to first order: Guided Setup is the primary path from registration to a working kiosk or online-ordering channel, with steps marked done automatically as you complete the underlying configuration.

FAQs

Is Guided Setup mandatory?

No. It is a helpful onboarding aid you can close at any time and configure everything manually through the standard backoffice pages. Reopen it from the clipboard icon in the navbar or the Guided Setup entry in the account menu.

How do steps get marked as completed?

Automatically. The backend setup-status endpoint inspects your actual data (payment profile, billing profile, branding, locations, menus, POS connection, devices, test orders, etc.) and the frontend maps those results to step checkmarks. You generally don't mark steps yourself.

Why does a step still show as incomplete after I did it?

Completion is detected from real data and can be location-scoped. Make sure you have the correct location selected in the topbar, and that the underlying record actually meets the check (for example, "connect POS" needs both a connected POS and a successful integration test — click Test Connection on the integration page if you have not; a payment profile must be verified/enabled). Lightspeed K-Series is the exception to the test click: its OAuth callback records the successful test for you.

Which POS providers can I choose?

Whichever providers GET /back-office/merchant/reseller-providers returns for your account. It filters the platform's provider catalog by each provider's active and test_only flags and by your country (or, if you were onboarded through a reseller, that reseller's assigned catalog). In production a Belgian merchant with no reseller sees Hendrickx, Vanhoutte and MplusKassa. Shopcaisse, Lightspeed K-Series and Upvendo's own first-party Upvendo POS are marked test-only and appear only for test merchants and non-production environments (Upvendo POS in every country — first_party bypasses the country filter); Square is offered in US, CA, GB, AU, JP, IE, FR and ES. (The POS_PROVIDERS constant in types.ts is legacy and does not describe this list.)

Can I change my POS later?

Yes, via the "Change POS" link. If a POS is already connected you'll be asked to disconnect it from its settings page first; otherwise you go straight back to the POS selection grid.

How do the tutorial videos work?

When a step opens a backoffice page, the app calls GET /back-office/guided-setup-management/video/url?url=<page> to fetch a contextual video. If no video is configured for that page, the endpoint returns an empty object and a placeholder is shown. Global administrators can manage these videos from the Guided Setup Videos admin page.

Troubleshooting

Emily keeps asking which POS I use

Emily asks for the provider when no POS is connected and no pos_provider is saved in your onboarding state. Pick one (which saves the state and starts discovery), or connect a POS so it is auto-detected.

Emily opened by itself on my first login

That is deliberate. On a brand-new account whose onboarding phase is still none, Emily opens once and starts discovery so setup does not have to be found. It does not do this on a /settings/locations page, where the location co-pilot takes priority. See "First run" under Actions.

Most of my sidebar is greyed out with a padlock

Also deliberate, and temporary. Until your account has a location, the operational navigation stays visible but locked so you can see what is coming without being able to walk into empty pages. Settings and the top bar stay reachable — create your first location there and the rest unlocks. Existing accounts never see this.

Steps are missing or the list looks empty

There is no per-provider fallback list in the front end, so an empty checklist means one of two things. Either no POS provider could be resolved at all (nothing in the store, no connected POS, nothing in Emily's onboarding state) — in which case the panel does not even call the knowledge base — or the provider resolved but the getSetupSteps call to Emily's knowledge base failed or came back with no steps. Start (or restart) discovery with Emily so a provider and a step list get saved. (Verified: EmilySetupPanel.vue lines 393-398 and 433-441.)

Progress shows 0% even though I configured things

Completion is detected per merchant and (often) per selected location. Confirm the correct location is selected in the topbar so setup-status evaluates the right data, and verify each underlying record satisfies its check.

"Connect POS" never completes

connect_pos requires both pos_connected and has_integration_test to be true. Ensure the integration is connected (connected status or stored credentials) and that a successful integration test has been recorded.

Two exceptions to that rule. Lightspeed K-Series records the test itself during OAuth (see below). And first-party Upvendo POS never records one at all: the backend hard-codes pos_connected = true and has_integration_test = false for it, so connect_pos (and its retired alias pos_setup) complete on pos_connected alone. That branch is reachable in production only by test-flagged merchants — the upvendo provider is staged test_only and POST /pos/select-provider 403s a live merchant — and by accounts placed there by the pos:seed-demo / test-account console seeders.

For Hendrickx, Vanhoutte, Square, MplusKassa, and Shopcaisse, recording that test means a successful connection check — normally clicking Test Connection on the integration page. That timestamp is what has_integration_test reads.

For Lightspeed K-Series there is nothing to click: the OAuth callback records the successful test itself when it fetches your business from Lightspeed, so the step completes on connect. If it is still not complete, the businesses fetch after authorization failed — reconnect from /lightspeed → Settings, and check the Status tab for the error. (Verified: app/Services/BackOffice/LightspeedKSeriesIntegrationService.php lines 336-354 and 414-421.)

Video content is not loading

Verify a video is configured for that exact page URL in config/guided-setup.php (or via a custom video override managed by a global admin). The lookup matches the current page path against task URLs; an unmatched URL returns an empty result and the no-video placeholder is shown.

Assistant Guidance

When users ask about Guided Setup, describe it as a checklist panel inside the Emily assistant (not a separate page), opened from the clipboard icon in the navbar or the Guided Setup entry in the account menu — and note that on a brand-new account Emily opens itself on first login. Explain the flow: pick a POS provider, then work through an ordered checklist that links to each setup page. Emphasize that step completion is detected automatically from the merchant's real data via the backend setup-status endpoint, so users usually don't mark steps themselves. If a step won't complete, suggest checking the selected location and the specific condition (e.g. "connect POS" needs a connected and tested integration — for most providers that means clicking Test Connection, but for Lightspeed K-Series the test is recorded automatically by the OAuth callback, so don't tell a Lightspeed merchant to click it; a payment profile must be verified). Do not state a fixed production provider list: it depends on the merchant's country and reseller, and Upvendo's own first-party POS is offered only to test-flagged merchants while it is staged test_only. Avoid referencing the older config-driven self-service/online-ordering/qr-code task system as the current behavior; it is deprecated in favor of the Emily/POS flow.

Relations

Depends On

  • Merchant / Vendor: Onboarding state and setup status are keyed by merchant ID.
  • Locations: Many completion checks are location-scoped; "Select Location from Topbar" is itself a step, and devices/test orders are evaluated per location.
  • POS Integrations: The provider list and the "connect POS"/"sync menu" steps depend on third-party integrations (Hendrickx, Vanhoutte, Square, MplusKassa, Shopcaisse, Lightspeed K-Series).
  • Emily: Dynamic steps and persisted onboarding state come from Emily's onboarding-state and setup-steps endpoints via the proxy.
  • Backend setup-status service: SetupStatusService aggregates data from payment, billing, branding, location, item, menu, integration, transaction, and device repositories.

Affects

  • Onboarding experience: Guided Setup is the primary onboarding tool for new merchants, directly affecting time-to-first-order.
  • Setup pages: Steps deep-link to payments, billing, branding, locations, menus, in-house settings, online settings, online ordering, and device management pages.
  • Tutorial videos: Each backoffice page can surface a contextual guided-setup video via the video-by-URL endpoint.